API reference
Route checks
Check up to three routes with a short real call before you buy them, then buy the ones that passed with the routing order set.
BrowseRoute checks
Check up to three routes before buying
POST/
- Access
- API key. Scoped keys need
voice:send. - Rate limit
- 100 requests per second (the default)
Places one short real call over each route (1 to 3, in your order: the first is your primary, the rest backups) and reports whether it works. Returns 202 with a checkId at once; poll GET /routes/check/{checkId}.
- network (default): the call goes to a public line that answers by itself (a speaking clock or information line) in the destination, chosen from the ones the route's rates cover and, where we have one, of the same line type as number (mobile or fixed). The call is answered, held about two seconds and ended. Where no such line exists yet for a destination, a lighter check runs instead: it confirms only that the route accepts calls, places no call to anyone, and says so (accepts). - ring_me: the route calls number, which must be your own phone in a country the route serves. Ringing counts as working. Satellite and premium-rate ranges are refused; one number can be rung by checks 3 times an hour, and an account can ring 3 different numbers a day (429).
number (network mode) narrows the check to a destination: a dial code (92) or a full number (+923001234567); for an A-Z rate sheet pass it, or the route's own country is used.
Billing: each connected leg is charged at the route's rate (your own effective rate for that number) for the billable seconds, plus the normal platform fee, from your test credit first and then your balance (paidFrom says which). Unanswered legs and suspected false answers cost nothing; a check of your own listing is free. A funded balance is required (400 otherwise). Limits: 10 checks a minute and 60 an hour per account (429); when the limiter cannot be reached checks pause (503) rather than run unlimited. Send X-Idempotency-Key to make a retry safe: the retry returns the first check instead of placing a second. Blended routes cannot be checked yet (400). A test key returns a simulated result immediately: no call, no charge.
You may check routes you have not bought. Private routes need an access grant.
Request body (application/json)
routeIdsrequiredstring (uuid)[]
1 to 3 route ids, in your order: the first is your primary, the rest backupsnumberstring
network mode: a dial code or full number to check for (narrows an A-Z rate sheet to that destination and line type). ring_me mode: your own number, requiredmax 32 charsmodestring
network = our test lines (default); ring_me = the route calls your own numberdefault "network"One ofnetwork,ring_me
Response 202
datarequiredobject
checkIdrequiredstring (uuid) · data.checkId
Errors
- 400
VALIDATION_ERROR,INVALID_INPUTorBAD_REQUEST. ForVALIDATION_ERROR,error.detailsis an array of{ path, message }. - 401
UNAUTHORIZED: missing, invalid, expired or revoked credential. - 403
FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only. - 409
CONFLICT(or a code-specific 409): the change clashes with existing state. - 429
RATE_LIMITED: slow down and retry after theRetry-Afterseconds. - 500
INTERNAL_ERROR: unexpected failure. QuoteX-Request-Idto support. - Also
RATE_LIMITED,SERVICE_UNAVAILABLE
Send a test SMS over an SMS route
POST/
- Access
- API key. Scoped keys need
sms:send. - Rate limit
- 100 requests per second (the default)
Sends ONE short fixed message over exactly this SMS listing (never Smart Routing) to your own mobile, by the same transport a real message uses, and reports what happened. Returns 202 with a checkId at once; poll GET /routes/check/{checkId} (the test is its only route). The text is fixed and so is the sender: "PacketExchange test message: this route delivered to your phone. Ref K7QD", from a platform sender chosen by the route's sender rules (numeric on a route that carries numeric senders only).
Results: accepted (the route took it; no carrier receipt yet), delivered (a carrier receipt confirmed it) or refused (the route refused it, or the receipt said it failed; errorCode says which). Receipts usually arrive within a minute; on a route that returns none the test stays accepted, and routeReturnsReceipts says whether the route has returned any lately. A later receipt updates the test, so it also appears in GET /routes/checks.
number must be a mobile in international format that the route covers (by its rate sheet or its prefixes, longest prefix first); a number it does not cover is refused (400), as are premium-rate, satellite, special-service and short-code ranges, embargoed destinations and numbers on your Do-Not-Contact list.
Billing: the route's normal price for one message for that number (your own effective rate), plus the normal platform fee, from your test credit first and then your balance (paidFrom). A message the route refuses is not charged, and one whose receipt says it failed is refunded. Testing your own listing is free. Limits: 3 test messages to one number an hour (across all accounts), 5 different numbers and 20 test messages per account a day (429); when the limiter cannot be reached tests pause (503). Send X-Idempotency-Key to make a retry safe. A test key returns a simulated result at once: nothing is sent and nothing is charged.
Test messages never count in SMS volume, revenue or quality figures. A buyer's delivered test counts as working and a refused one as a failure on the listing's check health, which the seller sees without learning who ran it.
Request body (application/json)
routeIdrequiredstring (uuid)
The SMS listing to test (a marketplace route id)numberrequiredstring
Your own mobile number in international format (E.164), e.g. +35056012345. The route must cover itmax 32 chars
Response 202
datarequiredobject
checkIdrequiredstring (uuid) · data.checkId
Errors
- 400
VALIDATION_ERROR,INVALID_INPUTorBAD_REQUEST. ForVALIDATION_ERROR,error.detailsis an array of{ path, message }. - 401
UNAUTHORIZED: missing, invalid, expired or revoked credential. - 403
FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only. - 409
CONFLICT(or a code-specific 409): the change clashes with existing state. - 429
RATE_LIMITED: slow down and retry after theRetry-Afterseconds. - 500
INTERNAL_ERROR: unexpected failure. QuoteX-Request-Idto support. - Also
RATE_LIMITED,SERVICE_UNAVAILABLE
Is there a test line for these routes?
GET/
- Access
- API key. Scoped keys need
routes:read. - Rate limit
- 100 requests per second (the default)
For each route (1 to 3), whether we have a registered public test line for its destination (or for number's destination on an A-Z rate sheet). When there is none, check the route with mode: ring_me and your own number. Says yes or no only.
Parameters
routeIdsrequiredquery · object
Comma-separated route ids (1 to 3)numberquery · string
Optional dial code or number, to ask about one destination of an A-Z rate sheet
Response 200
datarequiredobject[]
routeIdrequiredstring (uuid) · data[].routeId
testLinerequiredboolean · data[].testLine
Errors
- 400
VALIDATION_ERROR,INVALID_INPUTorBAD_REQUEST. ForVALIDATION_ERROR,error.detailsis an array of{ path, message }. - 401
UNAUTHORIZED: missing, invalid, expired or revoked credential. - 403
FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only. - 429
RATE_LIMITED: slow down and retry after theRetry-Afterseconds. - 500
INTERNAL_ERROR: unexpected failure. QuoteX-Request-Idto support.
Get a route check's results
GET/
- Access
- API key. Scoped keys need
routes:read. - Rate limit
- 100 requests per second (the default)
Per-route verdicts, in your order. message is the sentence to show a person. Routes are named without seller details.
Parameters
idrequiredpath · string (uuid)
Response 200
datarequiredobject
idrequiredstring (uuid) · data.id
statusrequiredstring · data.status
Poll GET /routes/check/{id} until done (usually under 40 seconds)One ofrunning,donemoderequiredstring · data.mode
sms = a test message (POST /routes/check/sms)One ofnetwork,ring_me,smssimulatedrequiredboolean · data.simulated
True for a test key: no call was placed and nothing was chargednumberrequiredstring | null · data.number
The number or dial code you checked for (+digits)createdAtrequiredstring (date-time) · data.createdAt
ISO-8601 timestamp (UTC)completedAtrequiredstring (date-time) | null · data.completedAt
ISO-8601 timestamp (UTC)totalCostrequiredmoney · data.totalCost
USD as a decimal string with exactly 6 places, e.g. "0.012500".routesrequiredobject[] · data.routes
positionrequiredinteger · data.routes[].position
0 = your first choice (primary), then backupsrolerequiredstring · data.routes[].role
One ofprimary,backuprouteIdrequiredstring (uuid) · data.routes[].routeId
routeNamerequiredstring · data.routes[].routeName
Cleaned of seller names and contact detailscountryrequiredstring · data.routes[].country
ownRouterequiredboolean · data.routes[].ownRoute
A listing you sell yourself (checked free)resultrequiredstring · data.routes[].result
pending/checking = in progress. working = the call was answered: the route delivers. no_capacity = the route refused the call or did not respond. not_delivered = the route signalled ringing but the call never reached the number. false_answer = the route answered faster than a real line can be reached (under 1.5 s from our INVITE, or under 2.5 s with no ringing): it almost certainly answered the call itself. Not working, and not charged. inconclusive = no verdict (our test lines were busy, the number was reported invalid, or the check was interrupted); nothing counted against the route. accepts = the lighter check for a destination without a full check yet: the route accepts calls. Test SMS only: accepted = the route took the message and no carrier receipt has arrived yet (on a route that returns none it stays accepted); delivered = a carrier receipt confirmed delivery to the phone; refused = the route refused the message, or the carrier receipt said it failed (see errorCode). A refused message is not charged.One ofpending,checking,working,no_capacity,not_delivered,false_answer,inconclusive,accepts,accepted,delivered,refusedmessagerequiredstring · data.routes[].message
The plain-English verdict to show, e.g. "This route is working for your needs."checkTyperequiredstring | null · data.routes[].checkType
full = a call to one of our test lines; light = acceptance only; ring_me = your own number; sms = a test message to your own mobile; simulated = test keyOne offull,light,ring_me,sms,simulateddestinationrequiredstring | null · data.routes[].destination
The country the check call went tolineTyperequiredstring | null · data.routes[].lineType
Line type of the test line used (full checks)One offixed,mobilerangrequiredboolean | null · data.routes[].rang
answeredrequiredboolean | null · data.routes[].answered
pddMsrequiredinteger | null · data.routes[].pddMs
Post-dial delay: dial to first ring (or answer)sipCoderequiredinteger | null · data.routes[].sipCode
Final SIP response from the route, when one came backbillableSecondsrequiredinteger · data.routes[].billableSeconds
costrequiredmoney · data.routes[].cost
What this leg cost you (route rate for the connected seconds, plus the platform fee) USD as a decimal string with exactly 6 places, e.g. "0.012500".paidFromrequiredstring | null · data.routes[].paidFrom
Which wallet paid: test credit is used first, then your balance. Null when nothing was chargedOne oftest_credit,balance,mixedanswerMsrequiredinteger | null · data.routes[].answerMs
Milliseconds from our INVITE to the answer, when it answered (the false-answer test)completedAtrequiredstring (date-time) | null · data.routes[].completedAt
ISO-8601 timestamp (UTC)messageRefrequiredstring | null · data.routes[].messageRef
Test SMS: the 4-character reference printed at the end of the message, so you can find it on your phonesenderrequiredstring | null · data.routes[].sender
Test SMS: the sender the platform used (set from the route's sender rules; you cannot choose it)errorCoderequiredstring | null · data.routes[].errorCode
Test SMS refused: SELLER_REJECTED = the route refused the message; NO_ENDPOINT = the route has no delivery endpoint; UNDELIVERABLE, EXPIRED, REJECTED = the carrier receipt said it failed. The same codes as GET /comms/sms/{id}One ofSELLER_REJECTED,NO_ENDPOINT,UNDELIVERABLE,EXPIRED,REJECTEDcarrierStatusrequiredstring | null · data.routes[].carrierStatus
Test SMS: the carrier receipt's own stat value (DELIVRD, UNDELIV, ...), when a receipt arrivedcarrierErrorrequiredstring | null · data.routes[].carrierError
Test SMS: the carrier receipt's own err value, when it carried oneacceptedAtrequiredstring (date-time) | null · data.routes[].acceptedAt
Test SMS: when the route accepted the messagereceiptAtrequiredstring (date-time) | null · data.routes[].receiptAt
Test SMS: when the carrier receipt arrivedrouteReturnsReceiptsrequiredboolean | null · data.routes[].routeReturnsReceipts
Test SMS still accepted: whether this route has returned any carrier receipt in the last 30 days. false = a confirmation may never come; check your phoneworkingrequiredstring (uuid)[] · data.working
Route ids that passed (working or accepts; delivered for a test SMS), in your order
Errors
- 400
VALIDATION_ERROR,INVALID_INPUTorBAD_REQUEST. ForVALIDATION_ERROR,error.detailsis an array of{ path, message }. - 401
UNAUTHORIZED: missing, invalid, expired or revoked credential. - 403
FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only. - 404
NOT_FOUND: no such resource on your account. - 429
RATE_LIMITED: slow down and retry after theRetry-Afterseconds. - 500
INTERNAL_ERROR: unexpected failure. QuoteX-Request-Idto support.
List your recent route checks
GET/
- Access
- API key. Scoped keys need
routes:read. - Rate limit
- 100 requests per second (the default)
Parameters
limitquery · integer
Default 20
Response 200
datarequiredobject[]
Same fields as RouteCheck, shown earlier on this page.
Errors
- 400
VALIDATION_ERROR,INVALID_INPUTorBAD_REQUEST. ForVALIDATION_ERROR,error.detailsis an array of{ path, message }. - 401
UNAUTHORIZED: missing, invalid, expired or revoked credential. - 403
FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only. - 429
RATE_LIMITED: slow down and retry after theRetry-Afterseconds. - 500
INTERNAL_ERROR: unexpected failure. QuoteX-Request-Idto support.
Buy the routes that passed a check and set the routing order
POST/
- Access
- API key. Scoped keys need
purchases:write. - Rate limit
- 100 requests per second (the default)
Buys every route in the check that came back working, in your order, and puts them at the top of your routing order: the first is the primary, the rest its backups (your other ranked routes keep their relative order below them). Routes you already bought are reused. A route that cannot be bought (for example email not verified, a private route, or a US route that needs compliance review) is reported in purchases[].error and does not stop the others. Needs a live key.
Parameters
idrequiredpath · string (uuid)
Response 200
datarequiredobject
purchasesrequiredobject[] · data.purchases
routeIdrequiredstring (uuid) · data.purchases[].routeId
routeNamerequiredstring · data.purchases[].routeName
purchaseIdrequiredstring (uuid) | null · data.purchases[].purchaseId
statusrequiredstring | null · data.purchases[].status
The purchase status (active, or pending_review for a route that needs review)alreadyOwnedrequiredboolean · data.purchases[].alreadyOwned
errorrequiredstring | null · data.purchases[].error
routingOrderrequiredobject[] · data.routingOrder
positionrequiredinteger · data.routingOrder[].position
1 = primaryrolerequiredstring · data.routingOrder[].role
One ofprimary,backuppurchaseIdrequiredstring (uuid) · data.routingOrder[].purchaseId
routeIdrequiredstring (uuid) · data.routingOrder[].routeId
routeNamerequiredstring · data.routingOrder[].routeName
Errors
- 400
VALIDATION_ERROR,INVALID_INPUTorBAD_REQUEST. ForVALIDATION_ERROR,error.detailsis an array of{ path, message }. - 401
UNAUTHORIZED: missing, invalid, expired or revoked credential. - 403
FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only. - 404
NOT_FOUND: no such resource on your account. - 409
CONFLICT(or a code-specific 409): the change clashes with existing state. - 429
RATE_LIMITED: slow down and retry after theRetry-Afterseconds. - 500
INTERNAL_ERROR: unexpected failure. QuoteX-Request-Idto support.
Check health of a route you sell
GET/
- Access
- API key. Scoped keys need
routes:read. - Rate limit
- 100 requests per second (the default)
For your own listing: the last 24 hours of full route checks (working vs failed), the recent checks, and any suspension made by checks with its reason and evidence. A listing whose checks fail 10 or more times in 24 hours with none working is confirmed once more and then suspended from the marketplace; run POST /routes/check with its id (free for your own listing) after fixing it, and a working result puts it back. A call answered under 1.5 s after our INVITE (or under 2.5 s with no ringing) is a false answer and counts as a failure; answerMs is the evidence. Your own checks, checks to a buyer's own number (ring_me) and lighter checks never count. On an SMS listing the window counts buyers' test messages instead: delivered is working, refused is a failure, a message still awaiting a receipt does not count, and an SMS listing is never suspended automatically.
Parameters
idrequiredpath · string (uuid)
Response 200
datarequiredobject
windowrequiredobject · data.window
hoursrequiredinteger · data.window.hours
workingrequiredinteger · data.window.working
failedrequiredinteger · data.window.failed
totalrequiredinteger · data.window.total
suspendAfterrequiredinteger · data.window.suspendAfter
Failures (with none working) that trigger the confirmation checksuspensionrequiredobject | null · data.suspension
statusrequiredstring · data.suspension.status
notice = an A-Z rate sheet warned for one country; nothing was suspendedOne ofsuspended,noticesincerequiredstring (date-time) · data.suspension.since
ISO-8601 timestamp (UTC)reasonrequiredstring · data.suspension.reason
destinationrequiredstring | null · data.suspension.destination
evidencerequiredobject · data.suspension.evidence
Counts, SIP codes, causes and times of the failed checkslastReinstatedAtrequiredstring (date-time) | null · data.lastReinstatedAt
ISO-8601 timestamp (UTC)recentrequiredobject[] · data.recent
atrequiredstring (date-time) | null · data.recent[].at
ISO-8601 timestamp (UTC)resultrequiredstring · data.recent[].result
pending/checking = in progress. working = the call was answered: the route delivers. no_capacity = the route refused the call or did not respond. not_delivered = the route signalled ringing but the call never reached the number. false_answer = the route answered faster than a real line can be reached (under 1.5 s from our INVITE, or under 2.5 s with no ringing): it almost certainly answered the call itself. Not working, and not charged. inconclusive = no verdict (our test lines were busy, the number was reported invalid, or the check was interrupted); nothing counted against the route. accepts = the lighter check for a destination without a full check yet: the route accepts calls. Test SMS only: accepted = the route took the message and no carrier receipt has arrived yet (on a route that returns none it stays accepted); delivered = a carrier receipt confirmed delivery to the phone; refused = the route refused the message, or the carrier receipt said it failed (see errorCode). A refused message is not charged.One ofpending,checking,working,no_capacity,not_delivered,false_answer,inconclusive,accepts,accepted,delivered,refusedcheckTyperequiredstring · data.recent[].checkType
sms = a test message on an SMS listingOne offull,light,smserrorCoderequiredstring | null · data.recent[].errorCode
A test message's refusal code; null on callssipCoderequiredinteger | null · data.recent[].sipCode
causerequiredstring | null · data.recent[].cause
destinationrequiredstring | null · data.recent[].destination
byYourequiredboolean · data.recent[].byYou
runByrequiredstring · data.recent[].runBy
Who ran it: you, a buyer (never named), or the platform (confirmation / new test line)One ofyou,buyer,platformanswerMsrequiredinteger | null · data.recent[].answerMs
Milliseconds from our INVITE to the answerrangrequiredboolean | null · data.recent[].rang
Errors
- 400
VALIDATION_ERROR,INVALID_INPUTorBAD_REQUEST. ForVALIDATION_ERROR,error.detailsis an array of{ path, message }. - 401
UNAUTHORIZED: missing, invalid, expired or revoked credential. - 403
FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only. - 404
NOT_FOUND: no such resource on your account. - 429
RATE_LIMITED: slow down and retry after theRetry-Afterseconds. - 500
INTERNAL_ERROR: unexpected failure. QuoteX-Request-Idto support.