Skip to content

API reference

Marketplace routes

Browse, resolve, list and manage voice and SMS termination routes.

43 operationsBase URL https://packetexchange.io/api/v1Postman collection
BrowseMarketplace routes

Browse the route marketplace

GET/api/v1/routes

Access
Key optional. A key or token personalises the answer.
Rate limit
100 requests per second (the default)

Public. Every row is anonymous: no seller name, id or endpoint. Signed-in callers get the full stats block; anonymous callers get counts only. Money fields are 6-decimal USD strings. Each row carries measured (ASR, ACD, NER and PDD measured from real calls, or null) beside the seller-stated expectedAsr/expectedAcd/expectedPdd; anonymous callers get the attempt count as a band and no buyer count. Sort by measured quality with sort=measured_asr_desc|measured_asr_asc|measured_acd_desc|measured_acd_asc|ner_desc|ner_asc, or quality_desc (measured NER then ASR where measured, else stated ASR): listings with measured figures come first.

Parameters

  • type

    query · string

    One of voice, sms
  • country

    query · string

  • countryCode

    query · string

  • cliType

    query · string

    One of full_cli, local_cli, mixed_cli, ncli, partial_cli
  • routeType

    query · string

    One of direct, premium, standard, ncli
  • minPrice

    query · string

  • maxPrice

    query · string

  • minAsr

    query · string

  • minAcd

    query · string

  • maxPdd

    query · string

  • minScore

    query · integer

  • minCapacity

    query · integer

  • billing

    query · string

    One of per_second, per_minute
  • wholesale

    query · string

    One of true, false
  • callcenter

    query · string

    One of true, false
  • retail

    query · string

    One of true, false
  • otp

    query · string

    One of true, false
  • openRtp

    query · string

    One of true, false
  • dialer

    query · string

    One of true, false
  • a2p

    query · string

    One of true, false
  • bundlesOnly

    query · string

    One of true, false
  • search

    query · string

  • sort

    query · string

    One of price_asc, price_desc, asr_desc, asr_asc, acd_desc, acd_asc, pdd_asc, pdd_desc, capacity_desc, created_desc, country_asc, score_desc, score_asc, measured_asr_desc, measured_asr_asc, measured_acd_desc, measured_acd_asc, ner_desc, ner_asc, quality_desc
  • cursor

    query · string (uuid)

  • limit

    query · integer

    Default 25

Response 200

  • datarequired

    object[]

  • idrequired

    string (uuid) · data[].id

  • kindrequired

    string · data[].kind

    One of single, blend
  • typerequired

    string · data[].type

    One of voice, sms
  • countryrequired

    string · data[].country

  • countryCoderequired

    string · data[].countryCode

    E.164 country calling code, digits only
  • prefixrequired

    string[] · data[].prefix

    Dial prefixes the route covers
  • destinationNamerequired

    string · data[].destinationName

    The listing name. For anyone but the seller it is GENERATED by the platform from its own data, never the seller's text: "<Country> <Operator?> <Mobile|Fixed|All Networks>" for one destination (e.g. "Niger Mobile", "Kenya Safaricom Mobile"), "A-Z Voice · <tier> · <CLI> · Ref XXXX" or "A-Z SMS · <quality> · Ref XXXX" for an A-Z bundle. The seller sees the name they gave it.
  • cliTyperequired

    string · data[].cliType

    One of full_cli, ncli, partial_cli, local_cli, mixed_cli
  • routeTyperequired

    string · data[].routeType

    Quality tierOne of direct, premium, standard, ncli
  • pricePerUnitrequired

    money · data[].pricePerUnit

    USD per minute (voice) or per message segment (SMS). On an A-Z deck (rateCount > 0) the per-destination rates apply instead. USD as a decimal string with exactly 6 places, e.g. "0.012500".
  • billingIncrementrequired

    string | null · data[].billingIncrement

    First/subsequent increment in seconds, e.g. "60/60"
  • capacityrequired

    integer · data[].capacity

    Channels (voice) or messages per second (SMS)
  • expectedAsrrequired

    string | null · data[].expectedAsr

    Seller-stated ASR %. The measured figure is in measured.asr
  • expectedAcdrequired

    string | null · data[].expectedAcd

    Seller-stated ACD in seconds
  • expectedPddrequired

    string | null · data[].expectedPdd

    Seller-stated PDD in seconds
  • minAcdrequired

    integer | null · data[].minAcd

  • minAsrrequired

    string | null · data[].minAsr

    Decimal as a string, e.g. "92.50"
  • visibilityrequired

    string · data[].visibility

    One of public, private
  • statusrequired

    string · data[].status

    One of active, paused, suspended, pending_review
  • wholesaleCompatiblerequired

    boolean · data[].wholesaleCompatible

  • callcenterCompatiblerequired

    boolean · data[].callcenterCompatible

  • dialerCompatiblerequired

    boolean · data[].dialerCompatible

  • retailCompatiblerequired

    boolean · data[].retailCompatible

  • otpCompatiblerequired

    boolean · data[].otpCompatible

  • notesrequired

    string | null · data[].notes

  • smsType

    string | null · data[].smsType

    One of a2p, p2p, both
  • exchangeScorerequired

    integer | null · data[].exchangeScore

    Exchange Score 1-100, null until the route has carried real traffic. Uses the measured ASR, NER, ACD and PDD in place of the stated ones when the listing has recent measured figures
  • lastQcAtrequired

    string (date-time) | null · data[].lastQcAt

    ISO-8601 timestamp (UTC)
  • measured

    object | null · data[].measured

    Measured quality from real calls; null until the listing has enough traffic from enough buyers
  • windowrequired

    string · data[].measured.window

    Evidence window: the last 7 days if enough, else the last 30, else last = the most recent 30-day stretch that had enoughOne of 7d, 30d, last
  • fromrequired

    string · data[].measured.from

    First UTC day of the evidence, YYYY-MM-DD
  • torequired

    string · data[].measured.to

    Last UTC day of the evidence, YYYY-MM-DD
  • sessionsrequired

    integer · data[].measured.sessions

    Call attempts on this listing the figures are built from (at least 50). For anonymous callers, floored to a band (50, 100, 250, 500, 1000, 5000, ...) with sessionsBanded: true
  • sessionsBanded

    boolean · data[].measured.sessionsBanded

    True when sessions is a band floor (anonymous callers)
  • buyersrequired

    integer | null · data[].measured.buyers

    Distinct buying accounts behind the figures (at least 2). Null for anonymous callers
  • asrrequired

    number | null · data[].measured.asr

    Answer-seizure ratio %: answered attempts / attempts
  • acdrequired

    number | null · data[].measured.acd

    Average call duration of answered attempts, seconds of talk time
  • nerrequired

    number | null · data[].measured.ner

    Network effectiveness ratio %: attempts the network delivered to the handset (answered, user busy, no answer, callee rejected) / attempts
  • pddMsrequired

    integer | null · data[].measured.pddMs

    Median post-dial delay in milliseconds (to the nearest 100 ms); null when not captured
  • routeChecks

    object | null · data[].routeChecks

    Route checks on this listing in the last 7 days. Null when there were none.
  • totalrequired

    integer · data[].routeChecks.total

    Route checks in the last 7 days that count towards the listing's health (calls to registered test lines)
  • answeredrequired

    integer · data[].routeChecks.answered

    Of those, how many the test line answered through this route
  • lastAtrequired

    string (date-time) | null · data[].routeChecks.lastAt

    When the last check completed
  • lastResultrequired

    string | null · data[].routeChecks.lastResult

    The last check's verdict: working, no_capacity or not_delivered
  • createdAtrequired

    string (date-time) · data[].createdAt

    ISO-8601 timestamp (UTC)
  • updatedAtrequired

    string (date-time) · data[].updatedAt

    ISO-8601 timestamp (UTC)
  • isOwnrequired

    boolean · data[].isOwn

    True only on your own listings
  • listingRef

    string · data[].listingRef

    Anonymous short reference of the listing (4 characters, e.g. "7K2Q"): stable for the life of the listing, unique enough to tell two same-named listings apart, and derived from the listing alone (it says nothing about the seller). Absent on your own listings.
  • sellerProfilerequired

    object | null · data[].sellerProfile

    Trust signals only. The marketplace never names the seller behind a listing.
  • verifiedrequired

    boolean · data[].sellerProfile.verified

    Seller identity verified
  • sellerScorerequired

    integer | null · data[].sellerProfile.sellerScore

    Average Exchange Score across the seller's trafficked routes
  • rateCountrequired

    integer · data[].rateCount

    Active per-destination deck rows; > 0 means an A-Z deck
  • priceTrend

    object | null · data[].priceTrend

    Real 24h price movement from the price history; null when the route has not repriced
  • changePctrequired

    number · data[].priceTrend.changePct

  • pointsrequired

    number[] · data[].priceTrend.points

  • nextCursor

    string | null

  • hasMore

    boolean

  • total

    integer

    Routes matching the filters across all pages
  • stats

    object

  • totalrequired

    integer · stats.total

  • voiceCountrequired

    integer · stats.voiceCount

  • smsCountrequired

    integer · stats.smsCount

  • destinationsrequired

    integer · stats.destinations

  • avgPrice

    number | null · stats.avgPrice

    Signed-in callers only. Average list price (display figure)
  • avgAsr

    number | null · stats.avgAsr

    Signed-in only. Average seller-stated ASR %
  • measuredAsr

    number | null · stats.measuredAsr

    Signed-in only. Measured ASR % over 30 days of real calls
  • avgScore

    integer | null · stats.avgScore

    Signed-in only
  • totalCapacity

    integer · stats.totalCapacity

    Signed-in only

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 401UNAUTHORIZED: missing, invalid, expired or revoked credential.
  • 403FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

List a new route for sale

POST/api/v1/routes

Access
API key. Scoped keys need routes:write.
Rate limit
30 requests per minute

Request body (application/json)

  • typerequired

    string

    One of voice, sms
  • countryrequired

    string

    max 100 chars
  • countryCoderequired

    string

  • prefixrequired

    string[]

  • destinationNamerequired

    string

    max 255 chars
  • pricePerUnitrequired

    string

  • cliTyperequired

    string

    One of full_cli, local_cli, mixed_cli, ncli, partial_cli
  • capacityrequired

    integer

    0 to 1000000
  • expectedAsr

    string

  • expectedAcd

    string

  • expectedPdd

    string

  • minAsr

    string

  • minAcd

    integer

    min 0
  • billingIncrementrequired

    string

  • routeTyperequired

    string

    One of direct, premium, standard, ncli
  • wholesaleCompatible

    boolean

    default true
  • callcenterCompatible

    boolean

    default true
  • dialerCompatible

    boolean

    default true
  • retailCompatible

    boolean

    default true
  • otpCompatible

    boolean

    default true
  • openRtp

    boolean

    default false
  • visibility

    string

    default "public"One of public, private
  • jingleEnabled

    boolean

    default false
  • jingleApiUrl

    string (uri) | null

  • smsDeliveryUrl

    string (uri) | null

  • smsDeliveryMethod

    string

    One of http, smpp
  • smppHost

    string | null

  • smppPort

    integer | null

    1 to 65535
  • smppSystemId

    string | null

  • smppPassword

    string | null

    max 64 chars
  • smppBindType

    string | null

    One of transceiver, transmitter
  • smppSystemType

    string | null

    max 13 chars
  • smppTps

    integer | null

    1 to 1000
  • smppSourceTon

    integer | null

    0 to 6
  • smppSourceNpi

    integer | null

    0 to 18
  • smppDestTon

    integer | null

    0 to 6
  • smppDestNpi

    integer | null

    0 to 18
  • jingleSipIp

    string | null

  • sipPort

    integer | null

    1 to 65535
  • sipAuthUsername

    string | null

    max 128 chars
  • sipAuthPassword

    string | null

    max 128 chars
  • techPrefix

    string | null

  • numberFormat

    object | null

  • mode

    string · numberFormat.mode

    One of custom
  • nationalPrefix

    string · numberFormat.nationalPrefix

  • strip

    integer · numberFormat.strip

    0 to 10
  • add

    string · numberFormat.add

  • t38Support

    boolean

    default false
  • supportedCodecs

    string[]

  • maxCallDuration

    integer

    min 0
  • smsType

    string

    One of a2p, p2p, both
  • smsDlrSupport

    boolean

  • smsConcatSupport

    boolean

  • smsSenderIdType

    string

    One of alphanumeric, numeric, preregistered
  • smsContentRestrictions

    string

  • smsRouteQuality

    string | null

    One of hq, direct, aggregator, sim
  • smsSenderIdBehavior

    string | null

    One of alphanumeric_preserved, numeric_long, overwritten, not_guaranteed
  • smsDlrLevel

    string | null

    One of real_operator, intermediate, submit_only, none
  • smsDlrPercent

    string | null

  • smsUnicodeSupport

    boolean | null

  • smsAcceptedTraffic

    string[] | null

    One of wholesale, transactional, otp, marketing, promo_shortcode
  • timeOfDayPricing

    object

  • notes

    string

    max 2000 chars

Response 201

  • datarequired

    object

    A route you listed, as only you (the seller) see it. Passwords are never returned.
  • idrequired

    string (uuid) · data.id

  • kindrequired

    string · data.kind

    One of single, blend
  • typerequired

    string · data.type

    One of voice, sms
  • countryrequired

    string · data.country

  • countryCoderequired

    string · data.countryCode

    E.164 country calling code, digits only
  • prefixrequired

    string[] · data.prefix

    Dial prefixes the route covers
  • destinationNamerequired

    string · data.destinationName

    The listing name. For anyone but the seller it is GENERATED by the platform from its own data, never the seller's text: "<Country> <Operator?> <Mobile|Fixed|All Networks>" for one destination (e.g. "Niger Mobile", "Kenya Safaricom Mobile"), "A-Z Voice · <tier> · <CLI> · Ref XXXX" or "A-Z SMS · <quality> · Ref XXXX" for an A-Z bundle. The seller sees the name they gave it.
  • cliTyperequired

    string · data.cliType

    One of full_cli, ncli, partial_cli, local_cli, mixed_cli
  • routeTyperequired

    string · data.routeType

    Quality tierOne of direct, premium, standard, ncli
  • pricePerUnitrequired

    money · data.pricePerUnit

    USD per minute (voice) or per message segment (SMS). On an A-Z deck (rateCount > 0) the per-destination rates apply instead. USD as a decimal string with exactly 6 places, e.g. "0.012500".
  • billingIncrementrequired

    string | null · data.billingIncrement

    First/subsequent increment in seconds, e.g. "60/60"
  • capacityrequired

    integer · data.capacity

    Channels (voice) or messages per second (SMS)
  • expectedAsrrequired

    string | null · data.expectedAsr

    Seller-stated ASR %. The measured figure is in measured.asr
  • expectedAcdrequired

    string | null · data.expectedAcd

    Seller-stated ACD in seconds
  • expectedPddrequired

    string | null · data.expectedPdd

    Seller-stated PDD in seconds
  • minAcdrequired

    integer | null · data.minAcd

  • minAsrrequired

    string | null · data.minAsr

    Decimal as a string, e.g. "92.50"
  • visibilityrequired

    string · data.visibility

    One of public, private
  • statusrequired

    string · data.status

    One of active, paused, suspended, pending_review
  • wholesaleCompatiblerequired

    boolean · data.wholesaleCompatible

  • callcenterCompatiblerequired

    boolean · data.callcenterCompatible

  • dialerCompatiblerequired

    boolean · data.dialerCompatible

  • retailCompatiblerequired

    boolean · data.retailCompatible

  • otpCompatiblerequired

    boolean · data.otpCompatible

  • notesrequired

    string | null · data.notes

  • smsType

    string | null · data.smsType

    One of a2p, p2p, both
  • exchangeScorerequired

    integer | null · data.exchangeScore

    Exchange Score 1-100, null until the route has carried real traffic. Uses the measured ASR, NER, ACD and PDD in place of the stated ones when the listing has recent measured figures
  • lastQcAtrequired

    string (date-time) | null · data.lastQcAt

    ISO-8601 timestamp (UTC)
  • measured

    object | null · data.measured

    Measured quality from real calls; null until the listing has enough traffic from enough buyersSame fields as MeasuredRouteQuality, shown earlier on this page.
  • routeChecks

    object | null · data.routeChecks

    Route checks on this listing in the last 7 days. Null when there were none.Same fields as RouteCheckRecord, shown earlier on this page.
  • createdAtrequired

    string (date-time) · data.createdAt

    ISO-8601 timestamp (UTC)
  • updatedAtrequired

    string (date-time) · data.updatedAt

    ISO-8601 timestamp (UTC)
  • sellerIdrequired

    string (uuid) · data.sellerId

    Your own account id
  • isOwner

    boolean · data.isOwner

    One of true
  • parentRouteIdrequired

    string (uuid) | null · data.parentRouteId

  • isBundlerequired

    boolean · data.isBundle

  • jingleSipIprequired

    string | null · data.jingleSipIp

    Your SIP endpoint
  • sipPortrequired

    integer | null · data.sipPort

  • techPrefixrequired

    string | null · data.techPrefix

  • sipAuthUsernamerequired

    string | null · data.sipAuthUsername

  • sipAuthPasswordSetrequired

    boolean · data.sipAuthPasswordSet

    A SIP digest password is stored (never returned)
  • smsDeliveryMethod

    string | null · data.smsDeliveryMethod

    One of http, smpp
  • smsDeliveryUrlrequired

    string | null · data.smsDeliveryUrl

  • smppHostrequired

    string | null · data.smppHost

  • smppPortrequired

    integer | null · data.smppPort

  • smppSystemIdrequired

    string | null · data.smppSystemId

  • smppPasswordSetrequired

    boolean · data.smppPasswordSet

    An SMPP password is stored (never returned)
  • endpointReachablerequired

    boolean | null · data.endpointReachable

  • endpointCheckedAtrequired

    string (date-time) | null · data.endpointCheckedAt

    ISO-8601 timestamp (UTC)
  • sellerProfile

    object | null · data.sellerProfile

    Trust signals only. The marketplace never names the seller behind a listing.Same fields as MarketplaceSellerProfile, shown earlier on this page.
  • rateCount

    integer · data.rateCount

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 401UNAUTHORIZED: missing, invalid, expired or revoked credential.
  • 403FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only.
  • 409CONFLICT (or a code-specific 409): the change clashes with existing state.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

Get marketplace totals for a filter

GET/api/v1/routes/stats

Access
Key optional. A key or token personalises the answer.
Rate limit
100 requests per second (the default)

Same filters as the listing. Anonymous callers get counts only; price, ASR, score and capacity figures need a signed-in caller.

Parameters

  • type

    query · string

    One of voice, sms
  • country

    query · string

  • countryCode

    query · string

  • cliType

    query · string

    One of full_cli, local_cli, mixed_cli, ncli, partial_cli
  • routeType

    query · string

    One of direct, premium, standard, ncli
  • minPrice

    query · string

  • maxPrice

    query · string

  • minAsr

    query · string

  • minAcd

    query · string

  • maxPdd

    query · string

  • minScore

    query · integer

  • minCapacity

    query · integer

  • billing

    query · string

    One of per_second, per_minute
  • wholesale

    query · string

    One of true, false
  • callcenter

    query · string

    One of true, false
  • retail

    query · string

    One of true, false
  • otp

    query · string

    One of true, false
  • openRtp

    query · string

    One of true, false
  • dialer

    query · string

    One of true, false
  • a2p

    query · string

    One of true, false
  • bundlesOnly

    query · string

    One of true, false
  • search

    query · string

  • sort

    query · string

    One of price_asc, price_desc, asr_desc, asr_asc, acd_desc, acd_asc, pdd_asc, pdd_desc, capacity_desc, created_desc, country_asc, score_desc, score_asc, measured_asr_desc, measured_asr_asc, measured_acd_desc, measured_acd_asc, ner_desc, ner_asc, quality_desc
  • cursor

    query · string (uuid)

  • limit

    query · integer

    Default 25

Response 200

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 401UNAUTHORIZED: missing, invalid, expired or revoked credential.
  • 403FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

Price a phone number across the marketplace

GET/api/v1/routes/price-number

Access
Key optional. A key or token personalises the answer.
Rate limit
30 requests per minute

Every buyer-visible route that serves the number, at the rate it would actually charge for it, cheapest first. A route with a rate sheet is priced by its longest matching active prefix (if that row is blocked the route does not serve the number); a single-price route serves it when a listed prefix, or failing that its country code, starts the number. This is the public list price: negotiated prices and private grants are not applied. SMS prices are by destination network on routes that price a country per mobile network: network says which network rate is for and countryRate is the price for other or unknown networks. The network is determined from the number's range (ported numbers may be priced at the network the range belongs to). The number is normalised to digits (a leading 00 is dropped). At most 100 routes are returned; total counts all of them. An embargoed destination returns no routes and notice: "sanctioned". Seller identities are never included.

Parameters

  • numberrequired

    query · string

    A full number or dial code, any formatting
  • type

    query · string

    One of voice, smsDefault "voice"

Response 200

  • datarequired

    object

  • numberrequired

    string · data.number

    The number as priced: digits only
  • typerequired

    string · data.type

    One of voice, sms
  • unitrequired

    string · data.unit

    What rate is per: a minute (voice) or a message (SMS)One of min, msg
  • totalrequired

    integer · data.total

    Routes that serve the number, before the 100-row cap
  • routesrequired

    object[] · data.routes

    Cheapest first
  • idrequired

    string (uuid) · data.routes[].id

  • typerequired

    string · data.routes[].type

    One of voice, sms
  • namerequired

    string · data.routes[].name

    The listing name as a buyer reads it: generated by the platform, never the seller's text, and ending in the listing reference (e.g. "Niger Mobile · Ref 7K2Q", "A-Z Voice · Premium · Full CLI · Ref 3MX9"). Your own listings keep the name you gave them.
  • listingRef

    string · data.routes[].listingRef

    Anonymous short reference of the listing (4 characters, e.g. "7K2Q"): stable for the life of the listing, unique enough to tell two same-named listings apart, and derived from the listing alone (it says nothing about the seller). Absent on your own listings.
  • countryrequired

    string · data.routes[].country

  • countryCoderequired

    string · data.routes[].countryCode

    E.164 country calling code, digits only
  • matchedPrefixrequired

    string · data.routes[].matchedPrefix

    The dial prefix the number matched on this route (the longest one, on a deck)
  • destinationrequired

    string · data.routes[].destination

    The destination that prefix belongs to, e.g. "United Kingdom-Mobile"; the country for a flat-priced listing
  • raterequired

    money · data.routes[].rate

    What this route charges for THIS number: USD per minute (voice) or per message (SMS) USD as a decimal string with exactly 6 places, e.g. "0.012500".
  • billingIncrementrequired

    string | null · data.routes[].billingIncrement

    e.g. "60/60" or "1/1"; null when the listing does not state one
  • pricedByrequired

    string · data.routes[].pricedBy

    deck = priced by the matching rate-sheet row; flat = the listing's single priceOne of deck, flat
  • expectedAsrrequired

    string | null · data.routes[].expectedAsr

    Seller-stated ASR %. The measured figure is in measured.asr
  • expectedAcdrequired

    string | null · data.routes[].expectedAcd

    Seller-stated ACD in seconds
  • cliTyperequired

    string · data.routes[].cliType

  • routeTyperequired

    string · data.routes[].routeType

    Quality tier
  • capacityrequired

    integer · data.routes[].capacity

    Channels (voice) or messages per second (SMS)
  • exchangeScorerequired

    integer | null · data.routes[].exchangeScore

    Exchange Score 1-100; null ("New") until the route has carried traffic
  • measuredrequired

    object | null · data.routes[].measured

    Measured quality of the listing from real calls; null until it has enough traffic from enough buyersSame fields as MeasuredRouteQuality, shown earlier on this page.
  • routeChecksrequired

    object | null · data.routes[].routeChecks

    Route checks on this listing in the last 7 days. Null when there were none.Same fields as RouteCheckRecord, shown earlier on this page.
  • isOwnrequired

    boolean · data.routes[].isOwn

    True only on your own listing (signed-in callers), so you are not offered your own route
  • network

    object | null · data.routes[].network

    SMS routes that price the country per mobile network: which network rate is for. Absent otherwise
  • mccMncrequired

    string | null · data.routes[].network.mccMnc

    Mobile network code (MCC-MNC) rate is for, e.g. "234-10"; null when unknown
  • operatorrequired

    string | null · data.routes[].network.operator

    Network name from public number-range data, e.g. "O2"
  • sourcerequired

    string · data.routes[].network.source

    range = number-range data; none = not determinedOne of range, hlr, none
  • rateBasisrequired

    string · data.routes[].network.rateBasis

    network = that network's own rate; all_operators = the route's rate for networks it does not list separately; country = the price for other or unknown networksOne of network, all_operators, country
  • countryRate

    money | null · data.routes[].countryRate

    SMS routes that price per network: the price for other or unknown networks USD as a decimal string with exactly 6 places, e.g. "0.012500".
  • noticerequired

    string | null · data.notice

    Why the list is empty when it is empty for a reason other than "no route covers it"One of sanctioned

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 401UNAUTHORIZED: missing, invalid, expired or revoked credential.
  • 403FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

List destinations on the marketplace

GET/api/v1/routes/countries

Access
Public. No key needed.
Rate limit
100 requests per second (the default)

Every country with at least one live public route, with its route count, A to Z.

Response 200

  • datarequired

    object[]

  • countryrequired

    string · data[].country

  • countryCoderequired

    string · data[].countryCode

  • countrequired

    integer · data[].count

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

Get a route

GET/api/v1/routes/{id}

Access
Key optional. A key or token personalises the answer.
Rate limit
100 requests per second (the default)

Public for live public routes. The seller gets the full owner view; a granted buyer sees a private route; any other signed-in caller gets an access stub for a private route. Carries measured (quality measured from real calls, or null) and routeChecks (the last 7 days of route checks, or null).

Parameters

  • idrequired

    path · string

Response 200

  • datarequired

    object

  • id

    string (uuid) · data.id

  • kind

    string · data.kind

    One of single, blend
  • type

    string · data.type

    One of voice, sms
  • country

    string · data.country

  • countryCode

    string · data.countryCode

  • prefix

    string[] · data.prefix

    Dial prefixes the route covers
  • destinationName

    string · data.destinationName

    The listing name. For anyone but the seller it is GENERATED by the platform from its own data, never the seller's text: "<Country> <Operator?> <Mobile|Fixed|All Networks>" for one destination (e.g. "Niger Mobile", "Kenya Safaricom Mobile"), "A-Z Voice · <tier> · <CLI> · Ref XXXX" or "A-Z SMS · <quality> · Ref XXXX" for an A-Z bundle. The seller sees the name they gave it.
  • cliType

    string · data.cliType

    One of full_cli, ncli, partial_cli, local_cli, mixed_cli
  • routeType

    string · data.routeType

    Quality tierOne of direct, premium, standard, ncli
  • pricePerUnit

    money · data.pricePerUnit

    USD per minute (voice) or per message segment (SMS). On an A-Z deck (rateCount > 0) the per-destination rates apply instead. USD as a decimal string with exactly 6 places, e.g. "0.012500".
  • billingIncrement

    string | null · data.billingIncrement

    First/subsequent increment in seconds, e.g. "60/60"
  • capacity

    integer · data.capacity

    Channels (voice) or messages per second (SMS)
  • expectedAsr

    string | null · data.expectedAsr

    Seller-stated ASR %. The measured figure is in measured.asr
  • expectedAcd

    string | null · data.expectedAcd

    Seller-stated ACD in seconds
  • expectedPdd

    string | null · data.expectedPdd

    Seller-stated PDD in seconds
  • minAcd

    integer | null · data.minAcd

  • minAsr

    string | null · data.minAsr

    Decimal as a string, e.g. "92.50"
  • visibility

    string · data.visibility

    One of private
  • status

    string · data.status

    One of active, paused, suspended, pending_review
  • wholesaleCompatible

    boolean · data.wholesaleCompatible

  • callcenterCompatible

    boolean · data.callcenterCompatible

  • dialerCompatible

    boolean · data.dialerCompatible

  • retailCompatible

    boolean · data.retailCompatible

  • otpCompatible

    boolean · data.otpCompatible

  • notes

    string | null · data.notes

  • smsType

    string | null · data.smsType

    One of a2p, p2p, both
  • exchangeScore

    integer | null · data.exchangeScore

    Exchange Score 1-100, null until the route has carried real traffic. Uses the measured ASR, NER, ACD and PDD in place of the stated ones when the listing has recent measured figures
  • lastQcAt

    string (date-time) | null · data.lastQcAt

    ISO-8601 timestamp (UTC)
  • measured

    object | null · data.measured

    Measured quality from real calls; null until the listing has enough traffic from enough buyersSame fields as MeasuredRouteQuality, shown earlier on this page.
  • routeChecks

    object | null · data.routeChecks

    Route checks on this listing in the last 7 days. Null when there were none.Same fields as RouteCheckRecord, shown earlier on this page.
  • createdAt

    string (date-time) · data.createdAt

    ISO-8601 timestamp (UTC)
  • updatedAt

    string (date-time) · data.updatedAt

    ISO-8601 timestamp (UTC)
  • isOwn

    boolean · data.isOwn

    True only on your own listings
  • listingRef

    string · data.listingRef

    Anonymous short reference of the listing (4 characters, e.g. "7K2Q"): stable for the life of the listing, unique enough to tell two same-named listings apart, and derived from the listing alone (it says nothing about the seller). Absent on your own listings.
  • sellerProfile

    object | null · data.sellerProfile

    Trust signals only. The marketplace never names the seller behind a listing.Same fields as MarketplaceSellerProfile, shown earlier on this page.
  • rateCount

    integer · data.rateCount

  • priceTrend

    object | null · data.priceTrend

    Real 24h price movement from the price history; null when the route has not repriced
  • changePctrequired

    number · data.priceTrend.changePct

  • pointsrequired

    number[] · data.priceTrend.points

  • sellerId

    string (uuid) · data.sellerId

    Your own account id
  • isOwner

    boolean · data.isOwner

    One of true
  • parentRouteId

    string (uuid) | null · data.parentRouteId

  • isBundle

    boolean · data.isBundle

  • jingleSipIp

    string | null · data.jingleSipIp

    Your SIP endpoint
  • sipPort

    integer | null · data.sipPort

  • techPrefix

    string | null · data.techPrefix

  • sipAuthUsername

    string | null · data.sipAuthUsername

  • sipAuthPasswordSet

    boolean · data.sipAuthPasswordSet

    A SIP digest password is stored (never returned)
  • smsDeliveryMethod

    string | null · data.smsDeliveryMethod

    One of http, smpp
  • smsDeliveryUrl

    string | null · data.smsDeliveryUrl

  • smppHost

    string | null · data.smppHost

  • smppPort

    integer | null · data.smppPort

  • smppSystemId

    string | null · data.smppSystemId

  • smppPasswordSet

    boolean · data.smppPasswordSet

    An SMPP password is stored (never returned)
  • endpointReachable

    boolean | null · data.endpointReachable

  • endpointCheckedAt

    string (date-time) | null · data.endpointCheckedAt

    ISO-8601 timestamp (UTC)
  • accessRequired

    boolean · data.accessRequired

    One of true
  • accessRequestPending

    boolean · data.accessRequestPending

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 401UNAUTHORIZED: missing, invalid, expired or revoked credential.
  • 403FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only.
  • 404NOT_FOUND: no such resource on your account.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

Update a route you listed

PUT/api/v1/routes/{id}

Access
API key. Scoped keys need routes:write.
Rate limit
100 requests per second (the default)

The price of an ACTIVE route cannot change in place (400 VALIDATION_ERROR): schedule the change with POST /routes/{id}/rate-changes/flat, or pause the route first. On a paused route a price increase pauses buyers who pay the list rate until they accept it (see POST /purchases/{id}/accept-rate).

Parameters

  • idrequired

    path · string

Request body (application/json)

  • type

    string

    One of voice, sms
  • country

    string

    max 100 chars
  • countryCode

    string

  • prefix

    string[]

  • destinationName

    string

    max 255 chars
  • pricePerUnit

    string

  • cliType

    string

    One of full_cli, local_cli, mixed_cli, ncli, partial_cli
  • capacity

    integer

    0 to 1000000
  • expectedAsr

    string

  • expectedAcd

    string

  • expectedPdd

    string

  • minAsr

    string

  • minAcd

    integer

    min 0
  • billingIncrement

    string

  • routeType

    string

    One of direct, premium, standard, ncli
  • wholesaleCompatible

    boolean

    default true
  • callcenterCompatible

    boolean

    default true
  • dialerCompatible

    boolean

    default true
  • retailCompatible

    boolean

    default true
  • otpCompatible

    boolean

    default true
  • openRtp

    boolean

    default false
  • visibility

    string

    default "public"One of public, private
  • jingleEnabled

    boolean

    default false
  • jingleApiUrl

    string (uri) | null

  • smsDeliveryUrl

    string (uri) | null

  • smsDeliveryMethod

    string

    One of http, smpp
  • smppHost

    string | null

  • smppPort

    integer | null

    1 to 65535
  • smppSystemId

    string | null

  • smppPassword

    string | null

    max 64 chars
  • smppBindType

    string | null

    One of transceiver, transmitter
  • smppSystemType

    string | null

    max 13 chars
  • smppTps

    integer | null

    1 to 1000
  • smppSourceTon

    integer | null

    0 to 6
  • smppSourceNpi

    integer | null

    0 to 18
  • smppDestTon

    integer | null

    0 to 6
  • smppDestNpi

    integer | null

    0 to 18
  • jingleSipIp

    string | null

  • sipPort

    integer | null

    1 to 65535
  • sipAuthUsername

    string | null

    max 128 chars
  • sipAuthPassword

    string | null

    max 128 chars
  • techPrefix

    string | null

  • numberFormat

    object | null

  • mode

    string · numberFormat.mode

    One of custom
  • nationalPrefix

    string · numberFormat.nationalPrefix

  • strip

    integer · numberFormat.strip

    0 to 10
  • add

    string · numberFormat.add

  • t38Support

    boolean

    default false
  • supportedCodecs

    string[]

  • maxCallDuration

    integer

    min 0
  • smsType

    string

    One of a2p, p2p, both
  • smsDlrSupport

    boolean

  • smsConcatSupport

    boolean

  • smsSenderIdType

    string

    One of alphanumeric, numeric, preregistered
  • smsContentRestrictions

    string

  • smsRouteQuality

    string | null

    One of hq, direct, aggregator, sim
  • smsSenderIdBehavior

    string | null

    One of alphanumeric_preserved, numeric_long, overwritten, not_guaranteed
  • smsDlrLevel

    string | null

    One of real_operator, intermediate, submit_only, none
  • smsDlrPercent

    string | null

  • smsUnicodeSupport

    boolean | null

  • smsAcceptedTraffic

    string[] | null

    One of wholesale, transactional, otp, marketing, promo_shortcode
  • timeOfDayPricing

    object

  • notes

    string

    max 2000 chars
  • status

    string

    One of active, paused

Response 200

  • datarequired

    object

    A route you listed, as only you (the seller) see it. Passwords are never returned.Same fields as OwnRoute, shown earlier on this page.

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 401UNAUTHORIZED: missing, invalid, expired or revoked credential.
  • 403FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only.
  • 404NOT_FOUND: no such resource on your account.
  • 409CONFLICT (or a code-specific 409): the change clashes with existing state.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

Delete a route you listed

DELETE/api/v1/routes/{id}

Access
API key. Scoped keys need routes:write.
Rate limit
100 requests per second (the default)

Restorable for restoreWindowDays via POST /routes/{id}/restore.

Parameters

  • idrequired

    path · string

Response 200

  • datarequired

    object

  • messagerequired

    string · data.message

  • restorablerequired

    boolean · data.restorable

    One of true
  • restoreWindowDaysrequired

    integer · data.restoreWindowDays

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 401UNAUTHORIZED: missing, invalid, expired or revoked credential.
  • 403FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only.
  • 404NOT_FOUND: no such resource on your account.
  • 409CONFLICT (or a code-specific 409): the change clashes with existing state.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

Draft a listing from a rate sheet

POST/api/v1/routes/autopilot/draft

Access
API key. Scoped keys need routes:write.
Rate limit
10 requests per minute

Upload a CSV or Excel sheet (multipart field file, optional note). Returns a proposed listing and the questions a sheet cannot answer. Writes nothing.

Request body (multipart/form-data)

  • filerequired

    string

    CSV or Excel rate sheet (binary)
  • note

    string

    max 500 chars

Response 200

  • datarequired

    object

    A proposed listing form plus open questions

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 401UNAUTHORIZED: missing, invalid, expired or revoked credential.
  • 403FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only.
  • 409CONFLICT (or a code-specific 409): the change clashes with existing state.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

Test an endpoint before listing a route

POST/api/v1/routes/probe-endpoint

Access
API key. Full-access keys only; not reachable by scoped keys.
Rate limit
20 requests per minute

Sends a real SIP probe (voice), SMPP bind (SMS over SMPP) or URL check (SMS over HTTP) to the details you enter. Nothing is stored.

Request body (application/json)

  • typerequired

    string

    One of voice, sms
  • jingleSipIp

    string | null

    max 255 chars
  • sipPort

    integer | null

    1 to 65535
  • techPrefix

    string | null

    max 24 chars
  • smsDeliveryUrl

    string | null

    max 2048 chars
  • smsDeliveryMethod

    string | null

    One of http, smpp
  • smppHost

    string | null

    max 255 chars
  • smppPort

    integer | null

    1 to 65535
  • smppSystemId

    string | null

    Short account code your SMS supplier issued (max 16 chars). An email address is rejected.max 16 chars
  • smppPassword

    string | null

    Used for one bind attempt, never storedmax 64 chars
  • smppBindType

    string | null

    One of transceiver, transmitter
  • smppSystemType

    string | null

    max 13 chars

Response 200

  • datarequired

    object

  • passrequired

    boolean · data.pass

    True when the endpoint answered from every one of our media addresses
  • barred

    boolean · data.barred

    Reachable but refusing our calls
  • degraded

    boolean · data.degraded

    Refusing some of our source addresses
  • checksrequired

    object[] · data.checks

  • labelrequired

    string · data.checks[].label

  • valuerequired

    string · data.checks[].value

  • okrequired

    boolean · data.checks[].ok

  • egressAddressesrequired

    string · data.egressAddresses

    The addresses our traffic comes from; whitelist these
  • gatewayIprequired

    string · data.gatewayIp

    Deprecated alias of egressAddresses
  • diagnostics

    object · data.diagnostics

  • messagerequired

    string · data.message

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 401UNAUTHORIZED: missing, invalid, expired or revoked credential.
  • 403FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only.
  • 409CONFLICT (or a code-specific 409): the change clashes with existing state.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

List your call-centre routes and their call screening

GET/api/v1/routes/callguard

Access
API key. Scoped keys need routes:read.
Rate limit
100 requests per second (the default)

Response 200

  • datarequired

    object[]

  • routeIdrequired

    string (uuid) · data[].routeId

  • namerequired

    string · data[].name

  • countryrequired

    string · data[].country

  • enabledrequired

    boolean · data[].enabled

  • consentAtrequired

    string (date-time) | null · data[].consentAt

    ISO-8601 timestamp (UTC)
  • statusrequired

    string · data[].status

    One of active, paused, suspended, pending_review

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 401UNAUTHORIZED: missing, invalid, expired or revoked credential.
  • 403FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

Get call screening settings, stats and flagged calls

GET/api/v1/routes/{id}/screening

Access
API key. Scoped keys need routes:read.
Rate limit
100 requests per second (the default)

Parameters

  • idrequired

    path · string

Response 200

  • datarequired

    object

    Screening config, statistics and the flagged calls

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 401UNAUTHORIZED: missing, invalid, expired or revoked credential.
  • 403FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only.
  • 404NOT_FOUND: no such resource on your account.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

Turn call screening on or off for a route

PATCH/api/v1/routes/{id}/screening

Access
API key. Scoped keys need routes:write.
Rate limit
100 requests per second (the default)

Only for call-centre voice routes. Turning it on records your recording consent.

Parameters

  • idrequired

    path · string

Request body (application/json)

  • enabledrequired

    boolean

Response 200

  • datarequired

    object

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 401UNAUTHORIZED: missing, invalid, expired or revoked credential.
  • 403FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only.
  • 404NOT_FOUND: no such resource on your account.
  • 409CONFLICT (or a code-specific 409): the change clashes with existing state.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

Classify a sample transcript with call screening

POST/api/v1/routes/{id}/screening/test

Access
API key. Scoped keys need routes:write.
Rate limit
20 requests per minute

Parameters

  • idrequired

    path · string

Request body (application/json)

  • transcriptrequired

    string

    max 20000 chars

Response 200

  • datarequired

    object

    The classification the transcript would receive

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 401UNAUTHORIZED: missing, invalid, expired or revoked credential.
  • 403FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only.
  • 404NOT_FOUND: no such resource on your account.
  • 409CONFLICT (or a code-specific 409): the change clashes with existing state.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

List your saved listing presets

GET/api/v1/routes/listing-presets

Access
API key. Scoped keys need routes:read.
Rate limit
100 requests per second (the default)

Response 200

  • datarequired

    object

  • presetsrequired

    object[] · data.presets

  • namerequired

    string · data.presets[].name

  • valuesrequired

    object · data.presets[].values

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 401UNAUTHORIZED: missing, invalid, expired or revoked credential.
  • 403FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

Save a listing preset

PUT/api/v1/routes/listing-presets

Access
API key. Scoped keys need routes:write.
Rate limit
100 requests per second (the default)

Upserts by name; keeps your 12 most recent presets.

Request body (application/json)

  • namerequired

    string

    max 60 chars
  • valuesrequired

    object

Response 200

  • datarequired

    object

  • presetsrequired

    object[] · data.presets

  • namerequired

    string · data.presets[].name

  • valuesrequired

    object · data.presets[].values

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 401UNAUTHORIZED: missing, invalid, expired or revoked credential.
  • 403FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only.
  • 409CONFLICT (or a code-specific 409): the change clashes with existing state.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

Delete a listing preset

DELETE/api/v1/routes/listing-presets/{name}

Access
API key. Scoped keys need routes:write.
Rate limit
100 requests per second (the default)

Parameters

  • namerequired

    path · string

Response 200

  • datarequired

    object

  • presetsrequired

    object[] · data.presets

  • namerequired

    string · data.presets[].name

  • valuesrequired

    object · data.presets[].values

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 401UNAUTHORIZED: missing, invalid, expired or revoked credential.
  • 403FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only.
  • 404NOT_FOUND: no such resource on your account.
  • 409CONFLICT (or a code-specific 409): the change clashes with existing state.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

Preview the listings publishing a deck will create

GET/api/v1/routes/{id}/split-preview

Access
API key. Scoped keys need routes:read.
Rate limit
100 requests per second (the default)

Parameters

  • idrequired

    path · string

Response 200

  • datarequired

    object

    Per-country listings that publishing would produce

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 401UNAUTHORIZED: missing, invalid, expired or revoked credential.
  • 403FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only.
  • 404NOT_FOUND: no such resource on your account.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

List your recently deleted routes

GET/api/v1/routes/deleted

Access
API key. Scoped keys need routes:read.
Rate limit
100 requests per second (the default)

Response 200

  • datarequired

    object

  • routesrequired

    object[] · data.routes

  • id

    string (uuid) · data.routes[].id

  • kind

    string · data.routes[].kind

    One of single, blend
  • type

    string · data.routes[].type

    One of voice, sms
  • country

    string · data.routes[].country

  • countryCode

    string · data.routes[].countryCode

    E.164 country calling code, digits only
  • prefix

    string[] · data.routes[].prefix

    Dial prefixes the route covers
  • destinationName

    string · data.routes[].destinationName

    The listing name. For anyone but the seller it is GENERATED by the platform from its own data, never the seller's text: "<Country> <Operator?> <Mobile|Fixed|All Networks>" for one destination (e.g. "Niger Mobile", "Kenya Safaricom Mobile"), "A-Z Voice · <tier> · <CLI> · Ref XXXX" or "A-Z SMS · <quality> · Ref XXXX" for an A-Z bundle. The seller sees the name they gave it.
  • cliType

    string · data.routes[].cliType

    One of full_cli, ncli, partial_cli, local_cli, mixed_cli
  • routeType

    string · data.routes[].routeType

    Quality tierOne of direct, premium, standard, ncli
  • pricePerUnit

    money · data.routes[].pricePerUnit

    USD per minute (voice) or per message segment (SMS). On an A-Z deck (rateCount > 0) the per-destination rates apply instead. USD as a decimal string with exactly 6 places, e.g. "0.012500".
  • billingIncrement

    string | null · data.routes[].billingIncrement

    First/subsequent increment in seconds, e.g. "60/60"
  • capacity

    integer · data.routes[].capacity

    Channels (voice) or messages per second (SMS)
  • expectedAsr

    string | null · data.routes[].expectedAsr

    Seller-stated ASR %. The measured figure is in measured.asr
  • expectedAcd

    string | null · data.routes[].expectedAcd

    Seller-stated ACD in seconds
  • expectedPdd

    string | null · data.routes[].expectedPdd

    Seller-stated PDD in seconds
  • minAcd

    integer | null · data.routes[].minAcd

  • minAsr

    string | null · data.routes[].minAsr

    Decimal as a string, e.g. "92.50"
  • visibility

    string · data.routes[].visibility

    One of public, private
  • status

    string · data.routes[].status

    One of active, paused, suspended, pending_review
  • wholesaleCompatible

    boolean · data.routes[].wholesaleCompatible

  • callcenterCompatible

    boolean · data.routes[].callcenterCompatible

  • dialerCompatible

    boolean · data.routes[].dialerCompatible

  • retailCompatible

    boolean · data.routes[].retailCompatible

  • otpCompatible

    boolean · data.routes[].otpCompatible

  • notes

    string | null · data.routes[].notes

  • smsType

    string | null · data.routes[].smsType

    One of a2p, p2p, both
  • exchangeScore

    integer | null · data.routes[].exchangeScore

    Exchange Score 1-100, null until the route has carried real traffic. Uses the measured ASR, NER, ACD and PDD in place of the stated ones when the listing has recent measured figures
  • lastQcAt

    string (date-time) | null · data.routes[].lastQcAt

    ISO-8601 timestamp (UTC)
  • measured

    object | null · data.routes[].measured

    Measured quality from real calls; null until the listing has enough traffic from enough buyersSame fields as MeasuredRouteQuality, shown earlier on this page.
  • routeChecks

    object | null · data.routes[].routeChecks

    Route checks on this listing in the last 7 days. Null when there were none.Same fields as RouteCheckRecord, shown earlier on this page.
  • createdAt

    string (date-time) · data.routes[].createdAt

    ISO-8601 timestamp (UTC)
  • updatedAt

    string (date-time) · data.routes[].updatedAt

    ISO-8601 timestamp (UTC)
  • sellerId

    string (uuid) · data.routes[].sellerId

    Your own account id
  • isOwner

    boolean · data.routes[].isOwner

    One of true
  • parentRouteId

    string (uuid) | null · data.routes[].parentRouteId

  • isBundle

    boolean · data.routes[].isBundle

  • jingleSipIp

    string | null · data.routes[].jingleSipIp

    Your SIP endpoint
  • sipPort

    integer | null · data.routes[].sipPort

  • techPrefix

    string | null · data.routes[].techPrefix

  • sipAuthUsername

    string | null · data.routes[].sipAuthUsername

  • sipAuthPasswordSet

    boolean · data.routes[].sipAuthPasswordSet

    A SIP digest password is stored (never returned)
  • smsDeliveryMethod

    string | null · data.routes[].smsDeliveryMethod

    One of http, smpp
  • smsDeliveryUrl

    string | null · data.routes[].smsDeliveryUrl

  • smppHost

    string | null · data.routes[].smppHost

  • smppPort

    integer | null · data.routes[].smppPort

  • smppSystemId

    string | null · data.routes[].smppSystemId

  • smppPasswordSet

    boolean · data.routes[].smppPasswordSet

    An SMPP password is stored (never returned)
  • endpointReachable

    boolean | null · data.routes[].endpointReachable

  • endpointCheckedAt

    string (date-time) | null · data.routes[].endpointCheckedAt

    ISO-8601 timestamp (UTC)
  • sellerProfile

    object | null · data.routes[].sellerProfile

    Trust signals only. The marketplace never names the seller behind a listing.Same fields as MarketplaceSellerProfile, shown earlier on this page.
  • rateCount

    integer · data.routes[].rateCount

  • restoreWindowDaysrequired

    integer · data.restoreWindowDays

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 401UNAUTHORIZED: missing, invalid, expired or revoked credential.
  • 403FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

Restore a deleted route

POST/api/v1/routes/{id}/restore

Access
API key. Scoped keys need routes:write.
Rate limit
100 requests per second (the default)

The route comes back paused and private; publish it again when ready.

Parameters

  • idrequired

    path · string

Response 200

  • datarequired

    object

  • messagerequired

    string · data.message

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 401UNAUTHORIZED: missing, invalid, expired or revoked credential.
  • 403FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only.
  • 404NOT_FOUND: no such resource on your account.
  • 409CONFLICT (or a code-specific 409): the change clashes with existing state.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

List your saved SIP endpoints

GET/api/v1/routes/my-endpoints

Access
API key. Scoped keys need routes:read.
Rate limit
100 requests per second (the default)

Response 200

  • datarequired

    object[]

  • id

    string (uuid) | null · data[].id

  • iprequired

    string · data[].ip

  • label

    string | null · data[].label

  • routeCount

    integer · data[].routeCount

    How many of your routes use this IP
  • usedBy

    string | null · data[].usedBy

    Name of the newest route using this IP

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 401UNAUTHORIZED: missing, invalid, expired or revoked credential.
  • 403FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

Save a SIP endpoint

POST/api/v1/routes/my-endpoints

Access
API key. Scoped keys need routes:write.
Rate limit
100 requests per second (the default)

Request body (application/json)

  • iprequired

    string

  • label

    string | null

    max 60 chars

Response 200

  • datarequired

    object

  • id

    string (uuid) | null · data.id

  • iprequired

    string · data.ip

  • label

    string | null · data.label

  • routeCount

    integer · data.routeCount

    How many of your routes use this IP
  • usedBy

    string | null · data.usedBy

    Name of the newest route using this IP

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 401UNAUTHORIZED: missing, invalid, expired or revoked credential.
  • 403FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only.
  • 409CONFLICT (or a code-specific 409): the change clashes with existing state.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

Label a saved SIP endpoint

PATCH/api/v1/routes/my-endpoints/{id}

Access
API key. Scoped keys need routes:write.
Rate limit
60 requests per minute

Sets the label shown next to the IP in "My IPs" and in the SIP endpoint pickers, so a seller with several switches can tell them apart. The label is trimmed, control and bidirectional-override characters are removed, and it is cut to 60 characters; an empty string or null clears it. Only saved endpoints (those with an id in GET /routes/my-endpoints) can be labelled; an unknown id, or someone else's, answers 404.

Parameters

  • idrequired

    path · string (uuid)

Request body (application/json)

  • labelrequired

    string | null

    The new label; "" or null clears itmax 60 chars

Response 200

  • datarequired

    object

  • idrequired

    string (uuid) · data.id

  • iprequired

    string · data.ip

  • labelrequired

    string | null · data.label

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 401UNAUTHORIZED: missing, invalid, expired or revoked credential.
  • 403FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only.
  • 404NOT_FOUND: no such resource on your account.
  • 409CONFLICT (or a code-specific 409): the change clashes with existing state.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

Remove a saved SIP endpoint

DELETE/api/v1/routes/my-endpoints/{id}

Access
API key. Scoped keys need routes:write.
Rate limit
100 requests per second (the default)

Parameters

  • idrequired

    path · string

Response 200

  • datarequired

    object

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 401UNAUTHORIZED: missing, invalid, expired or revoked credential.
  • 403FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only.
  • 404NOT_FOUND: no such resource on your account.
  • 409CONFLICT (or a code-specific 409): the change clashes with existing state.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

Preview which route would carry a destination

GET/api/v1/routes/resolve

Access
API key. Scoped keys need routes:read.
Rate limit
100 requests per second (the default)

Resolves as your account (including private routes you bought). price is a 6-decimal USD string.

Parameters

  • torequired

    query · string

    Destination number or prefix
  • type

    query · string

    One of voice, smsDefault "voice"
  • strategy

    query · string

    One of cheapest, best_quality, balancedDefault "balanced"

Response 200

  • datarequired

    object

  • strategyrequired

    string · data.strategy

    One of cheapest, best_quality, balanced
  • selectedrequired

    object | null · data.selected

  • idrequired

    string (uuid) · data.selected.id

  • destinationNamerequired

    string · data.selected.destinationName

    The listing name as a buyer reads it: generated by the platform, never the seller's text, and ending in the listing reference (e.g. "Niger Mobile · Ref 7K2Q", "A-Z Voice · Premium · Full CLI · Ref 3MX9"). Your own listings keep the name you gave them.
  • countryrequired

    string · data.selected.country

  • countryCoderequired

    string · data.selected.countryCode

  • typerequired

    string · data.selected.type

    One of voice, sms
  • cliTyperequired

    string | null · data.selected.cliType

  • pricerequired

    money · data.selected.price

    Rate for this destination: USD per minute or message, 6-decimal string USD as a decimal string with exactly 6 places, e.g. "0.012500".
  • asrrequired

    number | null · data.selected.asr

  • acdrequired

    number | null · data.selected.acd

  • matchedPrefixrequired

    string | null · data.selected.matchedPrefix

  • alternativesrequired

    object[] · data.alternatives

    Same fields as ResolvedRoute, shown earlier on this page.
  • countrequired

    integer · data.count

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 401UNAUTHORIZED: missing, invalid, expired or revoked credential.
  • 403FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

Test connectivity to your route endpoint

POST/api/v1/routes/{id}/test

Access
API key. Scoped keys need routes:write.
Rate limit
100 requests per second (the default)
Real traffic
Places a real test call over the route.

Sends a real SIP probe to the route endpoint from every one of our media addresses.

Parameters

  • idrequired

    path · string

Response 200

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 401UNAUTHORIZED: missing, invalid, expired or revoked credential.
  • 403FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only.
  • 404NOT_FOUND: no such resource on your account.
  • 409CONFLICT (or a code-specific 409): the change clashes with existing state.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

Capture a SIP trace of a test call on a route

POST/api/v1/routes/{id}/sip-trace

Access
API key. Full-access keys only; not reachable by scoped keys.
Rate limit
10 requests per minute
Real traffic
Places a real test call over the route.

For the seller or an active buyer. Optionally dials a real number. Buyers receive the trace with seller addresses masked.

Parameters

  • idrequired

    path · string

Request body (application/json)

  • number

    string

Response 200

  • datarequired

    object

    The SIP ladder: messages, timings and the final response

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 401UNAUTHORIZED: missing, invalid, expired or revoked credential.
  • 403FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only.
  • 404NOT_FOUND: no such resource on your account.
  • 409CONFLICT (or a code-specific 409): the change clashes with existing state.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

Get a route's price history

GET/api/v1/routes/{id}/price-history

Access
API key. Scoped keys need routes:read.
Rate limit
100 requests per second (the default)

For the seller and buyers of the route. Newest first.

Parameters

  • idrequired

    path · string

Response 200

  • datarequired

    object[]

  • idrequired

    string (uuid) · data[].id

  • routeIdrequired

    string (uuid) · data[].routeId

  • oldPricerequired

    money | null · data[].oldPrice

    US dollars as a decimal string with exactly 6 decimal places, e.g. "0.012500". Do money arithmetic with a decimal type, not floating point. USD as a decimal string with exactly 6 places, e.g. "0.012500".
  • newPricerequired

    money · data[].newPrice

    USD as a decimal string with exactly 6 places, e.g. "0.012500".
  • changedAtrequired

    string (date-time) · data[].changedAt

    ISO-8601 timestamp (UTC)

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 401UNAUTHORIZED: missing, invalid, expired or revoked credential.
  • 403FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only.
  • 404NOT_FOUND: no such resource on your account.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

Get traffic and revenue stats for your route

GET/api/v1/routes/{id}/stats

Access
API key. Scoped keys need routes:read.
Rate limit
100 requests per second (the default)

Parameters

  • idrequired

    path · string

Response 200

  • datarequired

    object

  • activePurchasesrequired

    integer · data.activePurchases

  • volumerequired

    object · data.volume

    Keyed 24h, 7d, 30d. revenue is USD (display figure, 2 decimals)
  • measuredAsrrequired

    number | null · data.measuredAsr

  • measuredAcdrequired

    number | null · data.measuredAcd

  • recentOffersrequired

    object[] · data.recentOffers

  • idrequired

    string (uuid) · data.recentOffers[].id

  • proposedPricerequired

    money · data.recentOffers[].proposedPrice

    USD as a decimal string with exactly 6 places, e.g. "0.012500".
  • agreedPricerequired

    money | null · data.recentOffers[].agreedPrice

    US dollars as a decimal string with exactly 6 decimal places, e.g. "0.012500". Do money arithmetic with a decimal type, not floating point. USD as a decimal string with exactly 6 places, e.g. "0.012500".
  • statusrequired

    string · data.recentOffers[].status

  • lastActorrequired

    string · data.recentOffers[].lastActor

  • createdAtrequired

    string (date-time) · data.recentOffers[].createdAt

    ISO-8601 timestamp (UTC)
  • updatedAtrequired

    string (date-time) · data.recentOffers[].updatedAt

    ISO-8601 timestamp (UTC)

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 401UNAUTHORIZED: missing, invalid, expired or revoked credential.
  • 403FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only.
  • 404NOT_FOUND: no such resource on your account.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

List the routes you sell

GET/api/v1/routes/my/list

Access
API key. Scoped keys need routes:read.
Rate limit
100 requests per second (the default)

Two modes. Cursor mode (only cursor, limit, includeChildren): newest first, A-Z deck children hidden unless includeChildren=true. Paged mode (any of offset, search, type, status, visibility, live, hiddenReason, scope, endpoint, deck, sort, dir): up to 200 rows a page, with total, and each row carries origin (its endpoint, your label for it, and the deck and rate sheet it came from). scope=listings lists every row a buyer could see as a listing (single routes and deck children); hiddenReason lists exactly the routes counted under that reason by GET /routes/my/listing-health. search matches the route name, country, endpoint IP or host, your IP label, the deck name and a route id prefix; a number such as +44 is a dial code (country code or coverage prefix). endpoint and deck take a group key from GET /routes/my/groups.

Parameters

  • cursor

    query · string (uuid)

  • limit

    query · integer

    Cursor mode: default 25, max 100. Paged mode: default 50, max 200.
  • includeChildren

    query · string

    Include the per-country children of A-Z decksOne of true, false, 1, 0
  • search

    query · string

  • type

    query · string

    One of voice, sms
  • status

    query · string

    One of active, paused, pending_review, suspended
  • visibility

    query · string

    One of public, private
  • live

    query · boolean | string

  • hiddenReason

    query · string

    One of sms_no_delivery, voice_no_endpoint
  • scope

    query · string

    One of listings, decks
  • endpoint

    query · string

  • deck

    query · string (uuid) | string

  • offset

    query · integer

  • sort

    query · string

    One of created, name, country, type, price, status
  • dir

    query · string

    One of asc, desc

Response 200

  • datarequired

    object[]

  • idrequired

    string (uuid) · data[].id

  • kindrequired

    string · data[].kind

    One of single, blend
  • typerequired

    string · data[].type

    One of voice, sms
  • countryrequired

    string · data[].country

  • countryCoderequired

    string · data[].countryCode

    E.164 country calling code, digits only
  • prefixrequired

    string[] · data[].prefix

    Dial prefixes the route covers
  • destinationNamerequired

    string · data[].destinationName

    The listing name. For anyone but the seller it is GENERATED by the platform from its own data, never the seller's text: "<Country> <Operator?> <Mobile|Fixed|All Networks>" for one destination (e.g. "Niger Mobile", "Kenya Safaricom Mobile"), "A-Z Voice · <tier> · <CLI> · Ref XXXX" or "A-Z SMS · <quality> · Ref XXXX" for an A-Z bundle. The seller sees the name they gave it.
  • cliTyperequired

    string · data[].cliType

    One of full_cli, ncli, partial_cli, local_cli, mixed_cli
  • routeTyperequired

    string · data[].routeType

    Quality tierOne of direct, premium, standard, ncli
  • pricePerUnitrequired

    money · data[].pricePerUnit

    USD per minute (voice) or per message segment (SMS). On an A-Z deck (rateCount > 0) the per-destination rates apply instead. USD as a decimal string with exactly 6 places, e.g. "0.012500".
  • billingIncrementrequired

    string | null · data[].billingIncrement

    First/subsequent increment in seconds, e.g. "60/60"
  • capacityrequired

    integer · data[].capacity

    Channels (voice) or messages per second (SMS)
  • expectedAsrrequired

    string | null · data[].expectedAsr

    Seller-stated ASR %. The measured figure is in measured.asr
  • expectedAcdrequired

    string | null · data[].expectedAcd

    Seller-stated ACD in seconds
  • expectedPddrequired

    string | null · data[].expectedPdd

    Seller-stated PDD in seconds
  • minAcdrequired

    integer | null · data[].minAcd

  • minAsrrequired

    string | null · data[].minAsr

    Decimal as a string, e.g. "92.50"
  • visibilityrequired

    string · data[].visibility

    One of public, private
  • statusrequired

    string · data[].status

    One of active, paused, suspended, pending_review
  • wholesaleCompatiblerequired

    boolean · data[].wholesaleCompatible

  • callcenterCompatiblerequired

    boolean · data[].callcenterCompatible

  • dialerCompatiblerequired

    boolean · data[].dialerCompatible

  • retailCompatiblerequired

    boolean · data[].retailCompatible

  • otpCompatiblerequired

    boolean · data[].otpCompatible

  • notesrequired

    string | null · data[].notes

  • smsType

    string | null · data[].smsType

    One of a2p, p2p, both
  • exchangeScorerequired

    integer | null · data[].exchangeScore

    Exchange Score 1-100, null until the route has carried real traffic. Uses the measured ASR, NER, ACD and PDD in place of the stated ones when the listing has recent measured figures
  • lastQcAtrequired

    string (date-time) | null · data[].lastQcAt

    ISO-8601 timestamp (UTC)
  • measured

    object | null · data[].measured

    Measured quality from real calls; null until the listing has enough traffic from enough buyersSame fields as MeasuredRouteQuality, shown earlier on this page.
  • routeChecks

    object | null · data[].routeChecks

    Route checks on this listing in the last 7 days. Null when there were none.Same fields as RouteCheckRecord, shown earlier on this page.
  • createdAtrequired

    string (date-time) · data[].createdAt

    ISO-8601 timestamp (UTC)
  • updatedAtrequired

    string (date-time) · data[].updatedAt

    ISO-8601 timestamp (UTC)
  • sellerIdrequired

    string (uuid) · data[].sellerId

    Your own account id
  • isOwner

    boolean · data[].isOwner

    One of true
  • parentRouteIdrequired

    string (uuid) | null · data[].parentRouteId

  • isBundlerequired

    boolean · data[].isBundle

  • jingleSipIprequired

    string | null · data[].jingleSipIp

    Your SIP endpoint
  • sipPortrequired

    integer | null · data[].sipPort

  • techPrefixrequired

    string | null · data[].techPrefix

  • sipAuthUsernamerequired

    string | null · data[].sipAuthUsername

  • sipAuthPasswordSetrequired

    boolean · data[].sipAuthPasswordSet

    A SIP digest password is stored (never returned)
  • smsDeliveryMethod

    string | null · data[].smsDeliveryMethod

    One of http, smpp
  • smsDeliveryUrlrequired

    string | null · data[].smsDeliveryUrl

  • smppHostrequired

    string | null · data[].smppHost

  • smppPortrequired

    integer | null · data[].smppPort

  • smppSystemIdrequired

    string | null · data[].smppSystemId

  • smppPasswordSetrequired

    boolean · data[].smppPasswordSet

    An SMPP password is stored (never returned)
  • endpointReachablerequired

    boolean | null · data[].endpointReachable

  • endpointCheckedAtrequired

    string (date-time) | null · data[].endpointCheckedAt

    ISO-8601 timestamp (UTC)
  • sellerProfile

    object | null · data[].sellerProfile

    Trust signals only. The marketplace never names the seller behind a listing.Same fields as MarketplaceSellerProfile, shown earlier on this page.
  • rateCount

    integer · data[].rateCount

  • revenue30drequired

    number · data[].revenue30d

    USD seller credit over 30 days (display figure, 2 decimals)
  • liveChannelsrequired

    integer · data[].liveChannels

  • childCountrequired

    integer · data[].childCount

    Per-country child listings created from this deck
  • origin

    object · data[].origin

    Paged mode only: where the route terminates and where it came from
  • endpointKeyrequired

    string · data[].origin.endpointKey

    The endpoint group key: the host, "~none" (no endpoint) or "~blend". Pass it as ?endpoint= to list every route on it
  • kindrequired

    string · data[].origin.kind

    sip = voice SIP endpoint, smpp = SMSC bind, http = delivery URL, blend = terminates via its members, none = no endpoint yetOne of sip, smpp, http, blend, none
  • hostrequired

    string | null · data[].origin.host

    The SIP IP, the SMSC host, or the delivery URL's host
  • portrequired

    integer | null · data[].origin.port

    SIP port (default 5060) or SMPP port (default 2775)
  • systemIdrequired

    string | null · data[].origin.systemId

    SMPP only: the System ID bound with
  • labelrequired

    string | null · data[].origin.label

    Your own label for this IP (see GET /routes/my-endpoints), voice only
  • deckIdrequired

    string (uuid) | null · data[].origin.deckId

    The A-Z deck this route was split out of, when it was
  • deckNamerequired

    string | null · data[].origin.deckName

  • sheetNamerequired

    string | null · data[].origin.sheetName

    File name of the latest applied rate sheet behind the deck (or behind the route itself)
  • nextCursorrequired

    string | null

    Cursor mode only; always null in paged mode
  • hasMorerequired

    boolean

  • total

    integer

    Paged mode only: rows matching the filters across all pages
  • offset

    integer

    Paged mode only
  • limit

    integer

    Paged mode only (max 200)

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 401UNAUTHORIZED: missing, invalid, expired or revoked credential.
  • 403FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

Count your SMS routes hidden for lack of an endpoint

GET/api/v1/routes/sms-endpoint-gap

Access
API key. Scoped keys need routes:read.
Rate limit
100 requests per second (the default)

Response 200

  • datarequired

    object

  • countrequired

    integer · data.count

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 401UNAUTHORIZED: missing, invalid, expired or revoked credential.
  • 403FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

Set one delivery endpoint on all your endpoint-less SMS routes

POST/api/v1/routes/sms-endpoint/bulk

Access
API key. Scoped keys need routes:write.
Rate limit
6 requests per minute

An SMPP method runs a real bind first; if it fails nothing changes and error.details carries the reason and the addresses to whitelist.

Request body (application/json)

  • methodrequired

    string

    One of http, smpp
  • smsDeliveryUrl

    string

  • smppHost

    string

  • smppPort

    integer

  • smppSystemId

    string

  • smppPassword

    string

  • smppBindType

    string

    One of transceiver, transmitter
  • smppSystemType

    string

  • routeIds

    string (uuid)[]

    Narrow to these routes; never widens the set

Response 200

  • datarequired

    object

  • updatedrequired

    integer · data.updated

  • methodrequired

    string · data.method

    One of http, smpp
  • bind

    string · data.bind

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 401UNAUTHORIZED: missing, invalid, expired or revoked credential.
  • 403FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only.
  • 409CONFLICT (or a code-specific 409): the change clashes with existing state.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

Count your listed routes that are live, and why the rest are hidden

GET/api/v1/routes/my/listing-health

Access
API key. Scoped keys need routes:read.
Rate limit
100 requests per second (the default)

Answers "why does my route count differ from the marketplace?". listed counts your active, public routes (A-Z deck parents excluded); live counts the ones buyers can see, using the marketplace's own filters, so the two numbers cannot disagree with the board. Each reason carries a count, a label and the fix. The routes behind sms_no_delivery and voice_no_endpoint can be listed with GET /routes/my/list?hiddenReason=<key> and fixed in one call with POST /routes/my/bulk-sms-delivery or /routes/my/bulk-sip-endpoint.

Response 200

  • datarequired

    object

  • listedrequired

    integer · data.listed

    Your routes that are active, public and not an A-Z deck parent: what you have put on sale
  • liverequired

    integer · data.live

    How many of those buyers can actually see on the marketplace (counted with the marketplace's own filters)
  • hiddenrequired

    integer · data.hidden

    listed - live
  • reasonsrequired

    object[] · data.reasons

    Why the hidden routes are hidden, in the order to fix them. Only reasons with a non-zero count are present.
  • keyrequired

    string · data.reasons[].key

    sms_no_delivery and voice_no_endpoint can be listed with GET /routes/my/list?hiddenReason=<key> and fixed in bulk; restricted = a destination the exchange does not carryOne of sms_no_delivery, voice_no_endpoint, restricted
  • countrequired

    integer · data.reasons[].count

  • labelrequired

    string · data.reasons[].label

    The reason in plain words
  • fixrequired

    string · data.reasons[].fix

    What to do about it

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 401UNAUTHORIZED: missing, invalid, expired or revoked credential.
  • 403FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

Set one SMS delivery method on many of your SMS routes

POST/api/v1/routes/my/bulk-sms-delivery

Access
API key. Scoped keys need routes:write.
Rate limit
10 requests per minute

Applies one delivery method (SMPP or HTTP) to a selection of your SMS routes: an explicit routeIds list, or every route matching filter (at most 5,000). Only your own live routes are touched; each route that is not eligible is returned in skipped with a reason. Send dryRun: true first to see how many would change: nothing is probed or written. On a real run the endpoint is checked ONCE for the whole batch: SMPP gets a real bind (no message is sent) and HTTP gets a URL check. If the bind is refused NO route is changed and the call answers 400 VALIDATION_ERROR with error.details = { kind: "smpp_bind_failed", host, port, systemId, bindType, reason, whitelistIps, failoverIps }: whitelistIps is the one SMS source address your SMSC must allow (every bind and message leaves from it); failoverIps are used only while that address is down, so allowing them is optional. A field that fails validation answers 400 with one { path, message } per field. All routes change in one transaction.

Request body (application/json)

  • routeIds

    string (uuid)[]

    An explicit selection of your route ids (max 5000). Send this OR filter, not both.
  • filter

    object

    "Every route matching this filter", re-derived on the server with the same rules as GET /routes/my/list (scope defaults to listings). Refused when it matches more than 5,000 routes.
  • search

    string · filter.search

    max 100 chars
  • type

    string · filter.type

    One of voice, sms
  • status

    string · filter.status

    One of active, paused, pending_review, suspended
  • visibility

    string · filter.visibility

    One of public, private
  • live

    boolean | string · filter.live

  • hiddenReason

    string · filter.hiddenReason

    One of sms_no_delivery, voice_no_endpoint
  • scope

    string · filter.scope

    One of listings, decks
  • endpoint

    string · filter.endpoint

    max 255 chars
  • deck

    string (uuid) | string · filter.deck

  • dryRun

    boolean

    Count and classify only: nothing is probed or written, and the answer carries wouldUpdate
  • deliveryrequired

    object

    The SMS delivery method to set, validated exactly as PUT /routes/{id} validates it. It must be complete: smsDeliveryMethod "smpp" needs smppHost and smppSystemId; "http" needs smsDeliveryUrl. A blank smppPassword keeps each route's stored one; null clears it.
  • smsDeliveryMethod

    string · delivery.smsDeliveryMethod

    One of http, smpp
  • smsDeliveryUrl

    string (uri) | null · delivery.smsDeliveryUrl

  • smppHost

    string | null · delivery.smppHost

  • smppPort

    integer | null · delivery.smppPort

    1 to 65535
  • smppSystemId

    string | null · delivery.smppSystemId

  • smppPassword

    string | null · delivery.smppPassword

    max 64 chars
  • smppBindType

    string | null · delivery.smppBindType

    One of transceiver, transmitter
  • smppSystemType

    string | null · delivery.smppSystemType

    max 13 chars

Response 200

  • datarequired

    object

  • updatedrequired

    integer · data.updated

    Routes changed. Always 0 on a dry run.
  • wouldUpdate

    integer · data.wouldUpdate

    Dry run (or nothing eligible): how many routes the call would change
  • skippedrequired

    object[] · data.skipped

    Routes left untouched, each with the reason
  • idrequired

    string (uuid) · data.skipped[].id

  • reasonrequired

    string · data.skipped[].reason

    not_found: not one of your live routes. not_sms / not_voice: wrong route type for this action. deck_parent: set it on the deck's own Edit page. blend: a blend has no endpoint of its own. duplicate_listing (SIP only): another of your routes already lists this country and prefixes on that IP and tech prefix.One of not_found, not_sms, not_voice, deck_parent, blend, duplicate_listing
  • check

    object · data.check

    The one endpoint check run for the whole batch (an SMPP bind, a URL check or a SIP probe). pass is false only when confirmUnreachable applied a SIP endpoint anyway.
  • passrequired

    boolean · data.check.pass

  • messagerequired

    string · data.check.message

  • dryRun

    boolean · data.dryRun

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 401UNAUTHORIZED: missing, invalid, expired or revoked credential.
  • 403FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only.
  • 409CONFLICT (or a code-specific 409): the change clashes with existing state.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

Set one SIP endpoint on many of your voice routes

POST/api/v1/routes/my/bulk-sip-endpoint

Access
API key. Scoped keys need routes:write.
Rate limit
10 requests per minute

Applies one SIP endpoint (IP or host, port, technical prefix and optional digest credentials) to a selection of your voice routes: an explicit routeIds list, or every route matching filter (at most 5,000). Only your own live routes are touched; routes that are not eligible, or that would duplicate another of your listings on the same IP and tech prefix (same country and prefixes), are returned in skipped. Send dryRun: true first to see how many would change. An invalid, private or reserved address, or one of our own addresses, is refused outright (400, on jingleSipIp). Otherwise one SIP probe is sent to the endpoint; if it gets no answer the call answers 400 VALIDATION_ERROR with error.details = { kind: "sip_probe_failed", message, checks } and nothing changes. Repeat with confirmUnreachable: true to apply anyway (a single-route edit never probes, so bulk is never stricter). The IP is also added to your saved endpoints. All routes change in one transaction.

Request body (application/json)

  • routeIds

    string (uuid)[]

    An explicit selection of your route ids (max 5000). Send this OR filter, not both.
  • filter

    object

    "Every route matching this filter", re-derived on the server with the same rules as GET /routes/my/list (scope defaults to listings). Refused when it matches more than 5,000 routes.
  • search

    string · filter.search

    max 100 chars
  • type

    string · filter.type

    One of voice, sms
  • status

    string · filter.status

    One of active, paused, pending_review, suspended
  • visibility

    string · filter.visibility

    One of public, private
  • live

    boolean | string · filter.live

  • hiddenReason

    string · filter.hiddenReason

    One of sms_no_delivery, voice_no_endpoint
  • scope

    string · filter.scope

    One of listings, decks
  • endpoint

    string · filter.endpoint

    max 255 chars
  • deck

    string (uuid) | string · filter.deck

  • dryRun

    boolean

    Count and classify only: nothing is probed or written, and the answer carries wouldUpdate
  • deliveryrequired

    object

    The SIP endpoint to set, validated exactly as PUT /routes/{id} validates it. jingleSipIp is required. A blank sipAuthPassword keeps each route's stored one; null clears it.
  • jingleSipIp

    string | null · delivery.jingleSipIp

  • sipPort

    integer | null · delivery.sipPort

    1 to 65535
  • techPrefix

    string | null · delivery.techPrefix

  • sipAuthUsername

    string | null · delivery.sipAuthUsername

    max 128 chars
  • sipAuthPassword

    string | null · delivery.sipAuthPassword

    max 128 chars
  • confirmUnreachable

    boolean

    Apply even though the SIP probe got no answer (the first attempt is refused with the probe's diagnosis in error.details)

Response 200

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 401UNAUTHORIZED: missing, invalid, expired or revoked credential.
  • 403FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only.
  • 409CONFLICT (or a code-specific 409): the change clashes with existing state.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

Group the routes you sell by endpoint or by A-Z deck

GET/api/v1/routes/my/groups

Access
API key. Scoped keys need routes:read.
Rate limit
100 requests per second (the default)

Your routes matching the same filters as GET /routes/my/list (paged mode), grouped by by=endpoint (the SIP IP, SMSC host or delivery URL host, with your label for the IP) or by=deck (the A-Z deck a route was split out of, with the rate sheet behind it). Each group has total, live and hidden counts. List a group's routes with GET /routes/my/list?endpoint=<key> or ?deck=<key>; the bulk actions accept the same keys in filter. Only your own routes are counted.

Parameters

  • search

    query · string

  • type

    query · string

    One of voice, sms
  • status

    query · string

    One of active, paused, pending_review, suspended
  • visibility

    query · string

    One of public, private
  • live

    query · boolean | string

  • hiddenReason

    query · string

    One of sms_no_delivery, voice_no_endpoint
  • scope

    query · string

    One of listings, decks
  • endpoint

    query · string

  • deck

    query · string (uuid) | string

  • byrequired

    query · string

    One of endpoint, deck

Response 200

  • datarequired

    object

  • byrequired

    string · data.by

    One of endpoint, deck
  • groupsrequired

    object[] · data.groups

    Largest group first, at most 500
  • keyrequired

    string · data.groups[].key

    Pass back as ?endpoint= (by=endpoint) or ?deck= (by=deck) on GET /routes/my/list to page this group's routes. Sentinels: "~none", "~blend", "~single"
  • kindrequired

    string · data.groups[].kind

    by=endpoint: how routes on this host are handed over (mixed when a host serves more than one kind). by=deck: deck, or single for routes listed on their ownOne of sip, smpp, http, mixed, blend, none, deck, single
  • hostrequired

    string | null · data.groups[].host

  • labelrequired

    string | null · data.groups[].label

    Your label for this IP
  • portrequired

    integer | null · data.groups[].port

    The port when every route in the group uses the same one
  • systemIdrequired

    string | null · data.groups[].systemId

    SMPP: the System ID when every route in the group uses the same one
  • deckIdrequired

    string (uuid) | null · data.groups[].deckId

  • deckNamerequired

    string | null · data.groups[].deckName

  • sheetNamerequired

    string | null · data.groups[].sheetName

    File name of the deck's latest applied rate sheet
  • totalrequired

    integer · data.groups[].total

  • liverequired

    integer · data.groups[].live

    Visible to buyers, by the marketplace's own filters
  • hiddenrequired

    integer · data.groups[].hidden

    total - live
  • totalrequired

    integer · data.total

    Routes across the returned groups
  • truncatedrequired

    boolean · data.truncated

    More than 500 groups matched; narrow the filter

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 401UNAUTHORIZED: missing, invalid, expired or revoked credential.
  • 403FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

Check whether your switches are refusing our calls

GET/api/v1/routes/my/endpoint-status

Access
API key. Scoped keys need routes:read.
Rate limit
100 requests per second (the default)

One entry per SIP endpoint (IP or host) used by your active voice routes. refusing is true when we have evidence your switch is turning our calls away: calls we sent it in the last 6 hours answered with SIP 401, 403 or 407 (at least 3 of them, and at least half of the calls that got an answer), or our own test call to it was barred or refused from some of our addresses (partial, with the refused addresses in refusedIps when known). evidence is that finding in one sentence, routeId is a route on the endpoint you can test from, and since is when the current incident was first seen. allow lists the addresses to allow on your switch: every one of egressIps, for SIP on sipPort (UDP and TCP) and RTP media on the UDP rtpPortRange, the same values GET /sip/network-info publishes. Only your own endpoints and your own calls are counted.

Response 200

  • datarequired

    object

  • endpointsrequired

    object[] · data.endpoints

  • endpointKeyrequired

    string · data.endpoints[].endpointKey

  • hostrequired

    string · data.endpoints[].host

  • endpointrequired

    string · data.endpoints[].endpoint

  • kindrequired

    string · data.endpoints[].kind

    One of voice
  • routeCountrequired

    integer · data.endpoints[].routeCount

  • routeIdrequired

    string (uuid) · data.endpoints[].routeId

  • refusingrequired

    boolean · data.endpoints[].refusing

  • partialrequired

    boolean · data.endpoints[].partial

  • refusedIpsrequired

    string[] · data.endpoints[].refusedIps

  • evidencerequired

    string | null · data.endpoints[].evidence

  • sourcerequired

    string | null · data.endpoints[].source

    One of traffic, probe
  • sincerequired

    string (date-time) | null · data.endpoints[].since

    ISO-8601 timestamp (UTC)
  • allowrequired

    object · data.allow

  • egressIpsrequired

    string[] · data.allow.egressIps

  • sipPortrequired

    integer · data.allow.sipPort

  • rtpPortRangerequired

    string · data.allow.rtpPortRange

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 401UNAUTHORIZED: missing, invalid, expired or revoked credential.
  • 403FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

List the buyers of your route

GET/api/v1/routes/{id}/buyers

Access
API key. Scoped keys need routes:read.
Rate limit
100 requests per second (the default)

Owner only: anyone other than the route's seller gets 403 FORBIDDEN. One row per buyer, identified only by a pseudonym scoped to this route (the same "Buyer #3F2A" that appears on offers for the route), so it cannot be matched to an account or across your other routes. No account id, name, company, email, IP or dialled number is returned. Figures cover the last 30 days; for an A-Z deck they include its per-country listings. status is the buyer's current relationship (ended = cancelled; ended buyers with no traffic in the window are left out). asr30d and calls30d are voice only, counted per call attempt group, and null until a call has been measured. Sorted by revenue.

Parameters

  • idrequired

    path · string (uuid)

Response 200

  • datarequired

    object

  • windowDaysrequired

    integer · data.windowDays

  • unitrequired

    string · data.unit

    One of minutes, messages
  • buyersrequired

    object[] · data.buyers

  • buyerrequired

    string · data.buyers[].buyer

    Pseudonym, stable per route
  • statusrequired

    string · data.buyers[].status

    One of active, paused, pending_review, ended
  • volume30drequired

    number · data.buyers[].volume30d

  • revenue30drequired

    number · data.buyers[].revenue30d

    USD (display figure, 2 decimals)
  • asr30drequired

    number | null · data.buyers[].asr30d

  • calls30drequired

    integer | null · data.buyers[].calls30d

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 401UNAUTHORIZED: missing, invalid, expired or revoked credential.
  • 403FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only.
  • 404NOT_FOUND: no such resource on your account.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

Show the billing increments your rate sheet sets

GET/api/v1/routes/{id}/rate-increments

Access
API key. Scoped keys need routes:read.
Rate limit
100 requests per second (the default)

Owner only: anyone other than the route's seller gets 403 FORBIDDEN. Groups the route's active rate rows by billing increment (e.g. 1/1 on some destinations, 60/60 on others). Rows with a null increment inherit fallback, the route-level increment.

Parameters

  • idrequired

    path · string (uuid)

Response 200

  • datarequired

    object

  • mixrequired

    object[] · data.mix

  • incrementrequired

    string | null · data.mix[].increment

    e.g. "60/60"; null = the row uses the route fallback
  • destinationsrequired

    integer · data.mix[].destinations

    Active rate rows with this increment
  • fallbackrequired

    string | null · data.fallback

    The route-level billing increment

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 401UNAUTHORIZED: missing, invalid, expired or revoked credential.
  • 403FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only.
  • 404NOT_FOUND: no such resource on your account.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

Read a rate sheet into a draft listing (no account needed)

POST/api/v1/public/listings/parse

Access
Public. No key needed.
Rate limit
6 requests per minute

Multipart upload (field file, optional note). Returns the proposed listing and parsed rates; stores nothing.

Request body (multipart/form-data)

  • filerequired

    string

    CSV or Excel rate sheet (binary)
  • note

    string

    max 500 chars

Response 200

  • datarequired

    object

    Proposed listing, parsed rates and truncated

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 409CONFLICT (or a code-specific 409): the change clashes with existing state.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

Save a draft listing to claim after sign-up

POST/api/v1/public/listings

Access
Public. No key needed.
Rate limit
10 requests per 10 minutes

Returns a token; the listing is created only when a signed-in account claims it.

Request body (application/json)

  • payload

    any

  • rates

    object[]

  • destinationName

    string · rates[].destinationName

  • operator

    string | null · rates[].operator

  • prefixrequired

    string · rates[].prefix

  • ratePerUnitrequired

    string · rates[].ratePerUnit

  • billingIncrement

    string | null · rates[].billingIncrement

  • minDuration

    number | null · rates[].minDuration

  • sourceFilename

    string

    max 512 chars
  • contactEmail

    string (email)

    max 255 chars
  • contactCompany

    string

    max 255 chars

Response 200

  • datarequired

    object

  • tokenrequired

    string · data.token

  • expiresAtrequired

    string (date-time) · data.expiresAt

    ISO-8601 timestamp (UTC)
  • rateCountrequired

    integer · data.rateCount

  • destinationNamerequired

    string · data.destinationName

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 409CONFLICT (or a code-specific 409): the change clashes with existing state.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

Look at a saved draft listing

GET/api/v1/public/listings/{token}

Access
Public. No key needed.
Rate limit
30 requests per minute

Parameters

  • tokenrequired

    path · string

Response 200

  • datarequired

    object

  • alreadyClaimedrequired

    boolean · data.alreadyClaimed

  • routeId

    string (uuid) | null · data.routeId

  • destinationName

    string · data.destinationName

  • type

    string · data.type

    One of voice, sms
  • country

    string · data.country

  • rateCount

    integer · data.rateCount

  • sourceFilename

    string | null · data.sourceFilename

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 404NOT_FOUND: no such resource on your account.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

Create a route from a saved draft listing

POST/api/v1/listings/{token}/claim

Access
API key. Full-access keys only; not reachable by scoped keys.
Rate limit
20 requests per minute

Idempotent per token: claiming twice returns the route already created.

Parameters

  • tokenrequired

    path · string

Response 200

  • datarequired

    object

  • routeIdrequired

    string (uuid) | null · data.routeId

  • rateCountrequired

    integer · data.rateCount

  • alreadyClaimedrequired

    boolean · data.alreadyClaimed

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 401UNAUTHORIZED: missing, invalid, expired or revoked credential.
  • 403FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only.
  • 404NOT_FOUND: no such resource on your account.
  • 409CONFLICT (or a code-specific 409): the change clashes with existing state.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.