MCP is live.Set upAsk the community
OmniDimension
Your clients

Verify a client

The identity and business checks a client passes before it can buy a number, carrier by carrier. Ask which step is next, run it, and follow the chain.

Where a region requires it, a client has to be verified before it can buy a number. For India that is an Aadhaar eKYC, so each check clears in minutes. For the US it is business verification.

Verification is per carrier. A client verified on one carrier of a region still has to verify on the other before it can buy there, and the two do not run the same steps. carrier is required on every verification and number call, in every region, however few carriers it holds.

This page is the whole verification flow. The endpoints are in the API reference; the flow from adding a client to buying a number is on the Reseller API page.

The carriers

CarrierRegionStocksVerification in short
Carrier 1: carrier-1INLandline, city codes 11, 12 and 80Codes by email and voice call, PAN, Aadhaar by OTP, preview, accept
Carrier 2: carrier-2-newINMobile, 94 and 79 seriesPAN, Aadhaar through a link, a document after each check, confirm
US carrier: carrier-usUSUS local, by area codeBusiness details, address, authorized representative, confirm

You should not hard-code that table. Call without a carrier and the refusal lists the region's carriers with what each one stocks, so you pick up a carrier we add later without shipping anything.

The loop

Read the status once to get the first step, then follow next_step until the status is completed.

GET /api/v1/reseller/kyc/status?user_id=CLIENT_ID&region=IN&carrier=carrier-1

The response has a regions array, one entry per carrier, each with that carrier's status, its next_step, and whether the client can_purchase on it yet.

GET /kyc/statusthe first next_stepPOST /kyc/steps/{next_step}next_stepno next stepstatus: completedthe client can buy a number
One read to start, then each step response hands you the next one. When a step comes back completed, verification is done and the client can buy. That is the same state the purchase endpoint checks, so there is nothing else to poll.
carrier = "carrier-1"
status  = GET /kyc/status?user_id=CLIENT_ID
next    = status.regions.find(r => r.carrier == carrier).next_step

while next:
    step = POST /kyc/steps/{next}   { user_id: CLIENT_ID, region: "IN", carrier: carrier, ...fields }
    next = step.next_step

# status is completed. The client can now buy a number on that carrier.

One endpoint runs every step. The step name is the last part of the path, and its fields go in the body.

POST /api/v1/reseller/kyc/steps/{step}

What a step can ask for

Ask for the carrier's steps and the shape of each field:

GET /api/v1/reseller/kyc/requirements?region=IN&carrier=carrier-1

Every step comes back with a method, and that is the one thing to branch on:

  • submit posts the required fields.
  • otp posts a code the client received.
  • redirect hands you a URL to open in the client's own browser, plus the step to poll for the outcome.
  • upload sends a document as multipart/form-data, with the file in document.

/requirements also publishes each field's patterns (such as the PAN or GSTIN format), required_if for fields needed only with some answers, choices for its fixed lists, and optional for fields it accepts but never needs. An upload step carries document: the form field, the accepted formats, and the size limit. So you can check values in your own form before you send them.

A region we cannot verify through the API returns 404 not_available rather than an empty list. Check kyc_required on the status call to know whether a region needs verification at all before a purchase.


Carrier 1

Send "carrier": "carrier-1" with region IN, landline numbers.

Carrier 1 verification as one line of steps: register, verify-otp with a code by email and by voice call, verify-pan, aadhaar-otp which sends a code, aadhaar-verify with about 30 seconds between tries, then either verify-gst or skip-gst, then preview and accept. After accept the client is verified and can buy.
#StepFields you sendmethodnext_step after it
1registername, email, phonesubmitverify-otp
2verify-otpmobile_otp, email_otpsubmitverify-pan
3verify-panpan, business_typesubmitaadhaar-otp
4aadhaar-otpaadhaarotpaadhaar-verify
5aadhaar-verifyotpotpverify-gst
6verify-gst or skip-gstgst, or nothingsubmitpreview
7previewnonesubmitaccept
8acceptnonesubmitnull: verified
  • Two codes at verify-otp. The email code arrives in the client's inbox. The mobile code arrives as an automated voice call that reads it out. If one did not arrive, call resend-otp with type set to email, mobile, or both (the default). It is never returned as a next_step.
  • business_type is proprietorship, company, or firm.
  • GST is a choice here. Run verify-gst with the GST number, or skip-gst.
  • preview returns what the client confirms before accept commits it. Anything the verification provider does not hold yet is left out, so treat each block as optional.
{
  "success": true,
  "status": "preview",
  "next_step": "accept",
  "message": "Review the details, then call accept.",
  "preview": {
    "client": { "name": "Demo User", "email": "demo@example.com", "mobile": "9876543210", "country_code": "91" },
    "pan": { "pan": "ABCDE1234F", "business_type": "proprietorship" },
    "aadhar": { "name": "Demo User", "address": "..." },
    "gst": { "gst_num": "29ABCDE1234F1Z5", "gstin": "..." }
  }
}

Carrier 2

Send "carrier": "carrier-2-new" with region IN, mobile numbers.

Carrier 2 verification as one line of steps: register with state, district and PIN, verify-pan, upload-pan with the PAN card, verify-aadhaar which returns a single-use link your customer opens in their own browser, aadhaar-status polled until verified, upload-aadhaar with the Aadhaar document. Business accounts then run verify-gst and upload-gst with the certificate. Individuals have no GST step. Both end with one confirm, after which next_step is null and the carrier may still be reviewing.

No codes are sent on this carrier. Instead, each check is followed by its document, and the account type decides whether there is a GST step.

#StepFields you sendmethodnext_step after it
1registername, email, phone, state, district, pincode, account_type, and business_name for a businesssubmitverify-pan
2verify-panpan, pan_holder_namesubmitupload-pan
3upload-panthe PAN card in documentuploadverify-aadhaar
4verify-aadhaaroptionally return_urlredirectaadhaar-status
5aadhaar-statusnonesubmitupload-aadhaar once verified
6upload-aadhaarthe Aadhaar document in documentuploadbusiness: verify-gst. Individual: confirm
7verify-gstgstsubmitupload-gst
8upload-gstthe GST certificate in documentuploadconfirm
9confirmnonesubmitnull

Steps 7 and 8 are for business accounts only. So the two paths are:

  • Individual: register, verify-pan, upload-pan, verify-aadhaar, aadhaar-status, upload-aadhaar, confirm.
  • Business: the same, with verify-gst and upload-gst before confirm.

Register: the account type is permanent

account_type is individual (the default) or business, and it cannot be changed after register. A business must also send business_name, exactly as it appears on its GST certificate, because the GST check compares the two.

phone is a 10-digit mobile number and pincode a 6-digit PIN code. The district is checked against the state, and a mismatch is refused with nothing written.


US carrier

Send "carrier": "carrier-us" with region US, US local numbers.

US carrier verification as one line of steps: business-info, business-address, authorized-rep, then one confirm. After confirm the status is completed with review_status pending_review, and the carrier reviews on its own clock. refresh-review sits off the line: call it any time, about 30 seconds apart, to ask where the review stands.

Business verification rather than identity verification: no codes, no PAN, no Aadhaar. Three forms, then one submit that hands everything to the carrier's review.

#StepFields you sendmethodnext_step after it
1business-infobusiness_name, business_type, business_identity, business_industry, ein, website_url, and optionally regions_of_operationsubmitbusiness-address
2business-addressstreet, city, state, postal_code, and optionally countrysubmitauthorized-rep
3authorized-repfirst_name, last_name, email, phone, business_title, job_positionsubmitconfirm
4confirmnonesubmitnull
  • business_type, business_identity, business_industry, regions_of_operation, and job_position come from fixed lists. Read them from choices on KYC requirements.
  • After confirm, status is completed and review_status is pending_review. refresh-review asks the carrier where its review stands. It is never returned as a next_step, so call it when you want an update, about 30 seconds apart.

The redirect step

{
  "status": "aadhaar_pending",
  "method": "redirect",
  "redirect_url": "https://provider.example/verify/one-time-link",
  "reusable": false,
  "poll_step": "aadhaar-status"
}

The link is good for one attempt. It carries a provider token that expires within minutes, so do not store it and never serve a stored one. If the client closes the tab or the link expires, run the step again for a fresh link, about 30 seconds apart.

Pass return_url to bring the client back into your own app, for example https://app.example.com/kyc/done. It must be https with a host, no #fragment, and no credentials, up to 2,000 characters. Whatever you do, polling poll_step is what completes the step, so poll even if the browser never comes back.

The upload step

On carriers that need documents, each check is followed by its document, and next_step points at the upload when one is due. Send the step as multipart/form-data:

curl -X POST https://backend.omnidim.io/api/v1/reseller/kyc/steps/upload-pan \
  -H "Authorization: Bearer $OMNIDIM_API_KEY" \
  -F user_id=CLIENT_ID -F region=IN -F carrier=carrier-2-new \
  -F document=@pan-card.pdf

The file must be a JPG, PNG, or PDF up to 10 MB, and its contents must match its extension. The step name decides which document it is, so there is no type field to send. Uploading again replaces the earlier document.

Errors

StatusSlugMeaning
400invalid_requestA field is missing, outside its fixed list, or in the wrong shape. /requirements publishes choices and patterns
409step_orderYou ran a step too early. next_step says which one to run first
409carrier_requiredThe region has more than one carrier and the call named none
422verification_failedThe details or the file were refused. Fix them with the client
429too_fastAn Aadhaar step was retried within about 30 seconds
503service_unavailableThe verification service is down. Nothing is wrong with the details. Retry in a few minutes

A step_order refusal does not start the wait. If the client did not get their code, call resend-otp while they are on the OTP step.

On this page