Skip to content

API documentation

Upload numbers, get quotes, place orders and download results over HTTP. Built for teams that process in bulk and automate. The rules match web ordering, and prices follow your account.

Get API access

  1. Ask support to open an account for you.
  2. Send support the services you need, your account and your server egress IPs.
  3. We then issue an API key and the full integration guide. Keys are valid for 1–730 days, and each key allows up to 32 egress IPs.

Basics

Base URLhttps://api.checkim.ai/openapi/v1
Authentication
Send Authorization: Bearer <API key> with every request
User-Agent
Required. Requests without one are blocked by Cloudflare (error 1010)
Format
JSON requests and responses in UTF-8, except file uploads
Time
UTC Unix timestamps in milliseconds
Amounts
Up to eight decimal places. Use a decimal type and do not round to two places

Integration flow

  1. List services and check your balance. Keep the productId you need.
  2. Read the data-use statement and accept it if you have not yet.
  3. Upload the number file and keep the returned fileId.
  4. Get a quote with the productId and fileId. Check the count, unit price and total.
  5. Create and store an idempotency key, then place the order. This charges your balance.
  6. Set up a webhook for order status pushes, and reconcile with updatedSince every 5–10 minutes so nothing is missed.
  7. When the order completes, list the result files, download every one and check its sha256. Download the unsuccessful files too.

curl example

Replace the placeholders. The full quote and order parameters are in the guide you receive with access.

  1. Set your key and list services

    export CHECKIM_TOKEN='replace with the API key from support'
    export CHECKIM_BASE='https://api.checkim.ai/openapi/v1'
    
    curl -H "Authorization: Bearer $CHECKIM_TOKEN" "$CHECKIM_BASE/products"
  2. Upload a number file

    curl -H "Authorization: Bearer $CHECKIM_TOKEN" \
      -F 'file=@./numbers.csv;type=text/csv' \
      "$CHECKIM_BASE/files"
  3. Get a quote

    curl -H "Authorization: Bearer $CHECKIM_TOKEN" \
      -H 'Content-Type: application/json' \
      -d '{"productId":"<productId>","name":"batch-001","fileId":"<fileId>"}' \
      "$CHECKIM_BASE/orders/check"
  4. Place the order

    # Charges your balance. Keep the key and body identical when retrying.
    curl -H "Authorization: Bearer $CHECKIM_TOKEN" \
      -H 'Content-Type: application/json' \
      -H 'Idempotency-Key: partner-request-001' \
      -d '{"quoteId":"<quoteId>","clientOrderId":"partner-batch-001"}' \
      "$CHECKIM_BASE/orders"
  5. Read an order, or reconcile by change time

    curl -H "Authorization: Bearer $CHECKIM_TOKEN" "$CHECKIM_BASE/orders/<orderId>"
    
    curl -H "Authorization: Bearer $CHECKIM_TOKEN" \
      "$CHECKIM_BASE/orders?updatedSince=<UTC ms>&size=100"
  6. List and download results, then check the sha256

    curl -H "Authorization: Bearer $CHECKIM_TOKEN" "$CHECKIM_BASE/orders/<orderId>/results"
    
    curl -H "Authorization: Bearer $CHECKIM_TOKEN" -o result.csv \
      "$CHECKIM_BASE/orders/<orderId>/results/<fileId>/download"
    shasum -a 256 result.csv

Endpoints

Account and statement

Endpoints: Account and statement
EndpointPurpose
GET/complianceRead the data-use statement and whether you accepted it
POST/compliance/acceptAccept the current statement version
GET/balanceRead the account balance
GET/productsList orderable services and your unit prices

Files and quotes

Endpoints: Files and quotes
EndpointPurpose
POST/filesUpload a number file (multipart, field "file")
POST/orders/checkValidate numbers and get a quote, valid for 180 seconds

Orders

Endpoints: Orders
EndpointPurpose
POST/ordersPlace the order for a quote; needs an Idempotency-Key header
GET/ordersList orders: cursor paging, filters by status and creation time, reconcile with updatedSince
GET/orders/{orderId}Read an order status and counts
POST/orders/{orderId}/cancelCancel an order: queued and undispatched orders are fully refunded at once, dispatched ones move to cancelling, running ones cannot be cancelled

Results

Endpoints: Results
EndpointPurpose
GET/orders/{orderId}/resultsList the result files, each with its sha256
GET/orders/{orderId}/results/{fileId}/downloadDownload one result file, with Range resume and If-None-Match

Webhook

Endpoints: Webhook
EndpointPurpose
GET/webhookRead the webhook settings and delivery health
PUT/webhookSet the receiving URL and the events to send
DELETE/webhookTurn the webhook off
GET/webhook/secretRead the signing secret
POST/webhook/secret/rotateRotate the signing secret; old and new both sign for 24 hours
POST/webhook/testSend a test event
GET/webhook/deliveriesList recent deliveries

Listing and reconciling orders

  • Orders are listed newest first. When a page has nextCursor, pass it back as cursor for the next page; cursor paging never skips or repeats an order while new ones arrive.
  • Filter by status and by creation time (createdFrom, createdTo, UTC milliseconds), or look one order up by its clientOrderId.
  • updatedSince returns only orders whose status changed after that time, oldest change first. Pull with it regularly and a missed webhook never loses a status.

Downloading results

  • Every file in the result list has a sha256. The download ETag is the same value, so compare it after downloading.
  • Range requests resume a download. Check the sha256 has not changed first; if it has, the file was rebuilt and you need the whole file again.
  • When you already have the complete file, send If-None-Match and an unchanged file returns 304 with no body.
  • Large orders with batch delivery list finished batches while still running; the final file after completion is the authoritative one.
  • For services with avatars (Telegram and WhatsApp extended or gender and age checks), the avatar column in the result CSV contains a signed image URL that can be fetched directly with GET while results are retained (do not send the Authorization header; If-None-Match is supported).

Webhooks

  • When the status of an order placed through the API changes, we POST an event to your HTTPS URL. Needs the webhook:manage permission.
  • Each event carries a CheckIM-Signature header (t=timestamp,v1=signature). Verify it with HMAC-SHA256 of "t.raw request body" using your signing secret.
  • Any 2xx counts as delivered; failures are retried 9 times over about 2 days. You may receive an event more than once, so deduplicate by its id.
  • Requests come from the fixed egress IP 34.21.195.36, so you can allow only that address.
Webhooks
EventSent when
order.completedThe order is settled and results can be downloaded
order.cancelledThe order was cancelled and fully refunded
order.cancel_pendingThe order is cancelling and settles once execution stops
order.needs_attentionThe order went to after-sales or needs manual handling
order.partial_resultsA new batch of results is ready to download

Order statuses

Order statuses
StatusMeaning
inQueueQueued. Keep polling
orderTakenAccepted. Keep polling
executingRunning. Large orders with batch delivery already offer finished batches
completedDone. Download the results and check the counts
waitAfterSaleAn after-sales request is being handled
pendingCancelCancelling. Keep polling for the final status
cancelledCancelled. Fully refunded if still queued, otherwise billed for the work done

Limits and notes

  • By default, at most 1,200 requests per minute per egress IP, 240 per account and 120 per key. The RateLimit-Limit, RateLimit-Remaining and RateLimit-Reset headers tell you how many are left this minute.
  • Quotes and uploads are slow, so each account can run at most 3 of them at once. More return 429 TOO_MANY_CONCURRENT_REQUESTS.
  • On 429 or 503, wait the seconds given in Retry-After, then retry the same request.
  • There is no sandbox. Every order is a real charge.
  • A polling timeout does not mean the order failed. Look the order up by orderId or clientOrderId before ordering again.

Common errors

Errors carry code, requestId, message and an optional detail.field. Handle them by code; message comes in one of 9 languages by Accept-Language and is for display only.

Common errors
CodeHTTPWhat to do
INVALID_REQUEST400Fix the parameter named in detail.field
INVALID_CURSOR400The cursor is invalid; start from page one
INVALID_API_TOKEN401Check the key is complete, not expired and not revoked
PERMISSION_DENIED403Ask support to check your services and egress IPs
QUOTE_EXPIRED409Confirm no order was placed, then quote again
INSUFFICIENT_BALANCE409Top up, then quote and order again
ORDER_NOT_CANCELLABLE409The order has started or finished and cannot be cancelled
RETRY_SAME_REQUEST409It clashed with another operation; retry the same request with backoff
COMPLIANCE_ACCEPTANCE_REQUIRED422Read and accept the data-use statement first
RATE_LIMITED429Wait for Retry-After and send less often
TOO_MANY_CONCURRENT_REQUESTS429Wait for an earlier quote or upload to finish
DATABASE_UNAVAILABLE503Temporarily unavailable; retry after Retry-After

Need API access?

Send support the services you need and your egress IPs. We will issue a key and the full guide, with a Python sample client.