Partner API ยท v1 openapi.yaml

Partner API

Search, register, renew and manage domains through one API. Names ending in .bd go to get.bd; every other ending goes to OrderBox.

Overview

The base URL is your registry host followed by /api/v1.

https://domains.pagejar.com/api/v1

Quick start: search a name, then register it.

curl -s "https://domains.pagejar.com/api/v1/domains/check?name=example&tlds[]=com&tlds[]=com.bd" \
  -H "Authorization: Bearer $TOKEN" -H "Accept: application/json"

Authentication

Create a token in the admin under Partners. It is shown once, so store it in a secret manager. Send it as a bearer token:

Authorization: Bearer <token>

Keep the token on your server. Never put it in browser code or a mobile app. If one leaks, delete it in Partners and create a new one.

ResponseMeaning
401No token, or the token is wrong or deleted.
403The token is valid but its partner is disabled.

Requests and responses

Errors

Errors are JSON with a message. Validation errors add an errors object keyed by field.

{
  "message": "example.com is already in the registry.",
  "errors": { "name": ["example.com is already in the registry."] }
}
StatusWhenWhat to do
401Bad or missing tokenCheck the header and the token.
403Partner disabledContact the registry owner.
404Unknown domain, or it belongs to another partnerThe two cases look the same on purpose.
409Wrong state, for example renewing a domain that is not activeRead the domain and check its status.
422Validation failedFix the fields in errors. Do not retry unchanged.
429Rate limit hitWait Retry-After seconds.
502The registrar refused or failedRead retryable: true means try again later, false means change the request.
5xxOur side failedRetry with backoff.
{ "message": "Invalid nameserver", "retryable": false }

Rate limits

Over the limit you get 429 with a Retry-After header. Responses carry X-RateLimit-Limit and X-RateLimit-Remaining. Search up to 30 names per call rather than one call per name.

Check availability

GET/domains/check30 per minute

Send either a label and the endings to try, or full names. Each name goes to the registrar for its ending.

ParameterDescription
nameA label without an ending, for example example. Needed unless domains is sent.
tlds[]Endings to try with name. Up to 30. Without it the registry's default list is used.
domains[]Full names, up to 30. Needed unless name is sent.
curl -s "https://domains.pagejar.com/api/v1/domains/check?domains[]=example.com&domains[]=example.com.bd" \
  -H "Authorization: Bearer $TOKEN" -H "Accept: application/json"
{
  "data": [
    { "domain": "example.com",    "provider": "orderbox", "in_registry": false, "available": true,  "premium": false },
    { "domain": "example.com.bd", "provider": "get_bd",   "in_registry": false, "available": false, "premium": false },
    { "domain": "example.xyz",    "provider": "orderbox", "in_registry": false, "available": null,  "error": "No answer for example.xyz" }
  ]
}
FieldDescription
availabletrue, false, or null when the registrar could not answer. Never offer a null name for sale; ask again later.
in_registrytrue when a partner already holds the name here. Then available is always false.
premiumPremium names are priced differently by the registrar.
price, currencyOnly some registrars return a price.
errorWhy available is null, for example an invalid name for that ending.
Clean answers are cached for 5 minutes, so a name you just registered elsewhere can show as available for a short time. Registrars sometimes answer "unknown" for a name at random; a second call usually fixes it.

Register a domain

POST/domainsreturns 202

Queues the registration. Read Get a domain until status is active or failed. With import: true nothing is bought; the domain is only recorded as active so the registry can track it.

FieldDescription
namerequiredFull name, up to 253 characters.
years1 to 10. Default 1.
nameserversUp to 13. get.bd uses the first 3. OrderBox needs at least 2.
external_refYour own id for this domain, up to 191 characters. Returned on every read.
providerOverride the registrar: get_bd, orderbox or dynadot. Normally leave it out.
importtrue to record an existing domain without buying it.
registrantThe owner's details, see below. Stored encrypted and never returned.

Registrant

FieldDescription
name, organizationUp to 255 characters.
emailA valid email address.
phone_cc, phoneCountry code without + (up to 5 characters) and the number (up to 30).
address1, address2, city, state, postcodePostal address.
countryTwo letters, ISO 3166-1, for example BD.
nidNational ID, for .bd.

What each registrar needs:

curl -s -X POST "https://domains.pagejar.com/api/v1/domains" \
  -H "Authorization: Bearer $TOKEN" -H "Accept: application/json" -H "Content-Type: application/json" \
  -d '{
    "name": "example.com.bd",
    "years": 1,
    "nameservers": ["ns1.procloudify.com", "ns2.procloudify.com"],
    "external_ref": "whmcs-domain-1234",
    "registrant": {
      "name": "Rahim Uddin", "email": "rahim@example.com",
      "phone_cc": "880", "phone": "01712345678",
      "address1": "House 1, Road 2", "city": "Dhaka", "state": "Dhaka",
      "postcode": "1207", "country": "BD", "nid": "1234567890"
    }
  }'

Response 202 is the domain object. A failed domain of yours can be posted again to retry with new details. A name held by anyone else returns 422.

List domains

GET/domains
ParameterDescription
statusOne of the statuses.
qPart of a domain name.
pagePage number.
per_page1 to 200. Default 50.
updated_sinceA date or date and time, for example 2026-11-12T10:00:00Z. Only domains changed at or after it. For a sync, remember the time your last sync started and send it next time, and keep reading pages until the last one.
curl -s "https://domains.pagejar.com/api/v1/domains?status=active&q=example" \
  -H "Authorization: Bearer $TOKEN" -H "Accept: application/json"

Get a domain

GET/domains/{name}
{
  "id": 12,
  "partner_id": 2,
  "name": "example.com.bd",
  "tld": "com.bd",
  "provider": "get_bd",
  "status": "active",
  "years": 1,
  "nameservers": ["ns1.procloudify.com", "ns2.procloudify.com"],
  "provider_order_id": "ord_123",
  "external_ref": "whmcs-domain-1234",
  "registered_at": "2026-11-12T10:00:00.000000Z",
  "expires_at": "2027-11-12T00:00:00.000000Z",
  "synced_at": "2026-11-12T10:01:00.000000Z",
  "last_error": null,
  "kind": "register",
  "transfer_status": null,
  "created_at": "2026-11-12T09:59:30.000000Z",
  "updated_at": "2026-11-12T10:01:00.000000Z"
}

Poll every 5 to 10 seconds for the first minute, then every few minutes. get.bd orders waiting on documents can take hours, so stop polling and check once a day instead. last_error explains a failed status or a failed renewal. kind is register or transfer; transfer_status is the registrar's own words while a transfer is in progress.

Renew a domain

POST/domains/{name}/renewreturns 202
FieldDescription
years1 to 10. Default 1.
curl -s -X POST "https://domains.pagejar.com/api/v1/domains/example.com/renew" \
  -H "Authorization: Bearer $TOKEN" -H "Accept: application/json" -H "Content-Type: application/json" \
  -d '{"years": 1}'
{ "message": "Renewal queued.", "domain": { "name": "example.com", "status": "active", "...": "..." } }

Only active or expired domains can be renewed; others return 409. A second renewal request for the same domain inside 10 minutes also returns 409, so a retry cannot pay twice. The renewal is tried once. Compare expires_at before and after, and check last_error if it did not move.

Change nameservers

PUT/domains/{name}/nameservers
FieldDescription
nameserversrequired2 to 13 hostnames.
curl -s -X PUT "https://domains.pagejar.com/api/v1/domains/example.com/nameservers" \
  -H "Authorization: Bearer $TOKEN" -H "Accept: application/json" -H "Content-Type: application/json" \
  -d '{"nameservers": ["ns1.example.net", "ns2.example.net"]}'

Only active domains can change nameservers; others return 409. This runs at the registrar before the response returns, so it can take a few seconds. It returns the updated domain, or 502 with the registrar's message.

Sync from the registrar

POST/domains/{name}/sync

Reads status, expiry and nameservers from the registrar now and returns the domain. The registry also refreshes every domain about once a day, so you only need this right after a change made outside the API.

Check a transfer

GET/transfers/check30 per minute

Asks the registrar that would take the domain whether it can be transferred in. Only OrderBox and Dynadot take transfers; a .bd name is refused with 422.

ParameterDescription
namerequiredFull name, for example example.com.
providerorderbox or dynadot. Normally leave it out.
curl -s "https://domains.pagejar.com/api/v1/transfers/check?name=example.com" \
  -H "Authorization: Bearer $TOKEN" -H "Accept: application/json"
{ "name": "example.com", "provider": "orderbox", "transferable": true, "message": null }

transferable is true, false (see message, for example a name that is not registered at all), or null when the registrar cannot tell before the order is placed (Dynadot).

Transfer a domain in

POST/transfersreturns 202

Moves a domain from another registrar to yours. The order is paid and includes one year of renewal. Before you call it, unlock the domain at the current registrar and get its auth (EPP) code. The order is placed on the queue.

FieldDescription
namerequiredFull name.
auth_coderequiredThe auth / EPP code. Stored encrypted only until the registrar has it, never returned and never logged.
nameserversUp to 13. Applied when the transfer completes.
providerorderbox or dynadot. Default from the registry's routing.
external_refYour own id for this domain.
registrantOptional owner details, same fields as registration.
curl -s -X POST "https://domains.pagejar.com/api/v1/transfers" \
  -H "Authorization: Bearer $TOKEN" -H "Accept: application/json" -H "Content-Type: application/json" \
  -d '{ "name": "example.com", "auth_code": "Abc123!xyz", "nameservers": ["ns1.a.com", "ns2.a.com"], "external_ref": "pagejar-77" }'

Follow it

Read Get a domain. kind is transfer and status goes pending, then transferring while the old registrar and the owner approve, then active (or failed). transfer_status shows the registrar's own words, for example "Waiting for Domain-Secret" or "Validating domain transfer", and last_error says what to fix. Check every few hours, not every few seconds.

A wrong auth code does not fail the transfer: the order waits and last_error asks for the right one. Send it with Send an auth code. A failed transfer can be started again by posting the name again with a fresh code.

Send an auth code

PUT/transfers/{name}/auth-code20 per minute

Gives a waiting transfer a new auth code. Returns the domain.

curl -s -X PUT "https://domains.pagejar.com/api/v1/transfers/example.com/auth-code" \
  -H "Authorization: Bearer $TOKEN" -H "Accept: application/json" -H "Content-Type: application/json" \
  -d '{ "auth_code": "NewCode1!" }'
StatusMeaning
200The registrar accepted the code.
409No transfer for this domain is waiting for a code.
502The registrar refused the code. message says why.

Domain statuses

StatusMeaning
pendingQueued. Nothing sent to the registrar yet.
registeringSent. The registrar has not confirmed. Settles on its own.
pending_documentsget.bd is reviewing documents. The registry tries again every 10 minutes.
transferringAn inbound transfer was ordered and is waiting for the old registrar or the owner. Often 1 to 7 days. See Transfer a domain in.
activeRegistered and working.
expiredPast its end date. Can still be renewed.
failedSee last_error. Post the name again with corrected details to retry.
cancelledClosed. It is no longer managed here.

Registrars and endings

EndingsRegistrarNotes
.bd, .com.bd, .net.bd, .org.bd, .edu.bd, .co.bd, .info.bd, .tv.bdget.bdRegistrant needs a national ID. Documents may be reviewed.
everything elseOrderBoxSome endings answer "unknown" at times. The registry retries before giving up.

The routing table is managed in the admin under TLD routing.

Going live