ResellerStack API
Everything the dashboard can do, your code can do. Check availability, register domains at wholesale, manage customers and invoices, and watch your wallet, all over a predictable JSON API. Money is always in minor units with an explicit currency.
This call runs against the live API. Any rsk_-prefixed key works in the sandbox.
curl -H "Authorization: Bearer rsk_test_2a9x…" \
"https://resellerstack-production.up.railway.app/api/v1/domains/check?q=example"Getting started
The API lives under a single versioned base URL. Responses are JSON with a data envelope; list endpoints add a meta object with counts.
https://resellerstack-production.up.railway.app/api/v1curl https://resellerstack-production.up.railway.app/api/v1{
"data": {
"name": "ResellerStack API",
"version": "v1",
"docs": "/docs",
"endpoints": ["GET /api/v1/domains/check", "GET /api/v1/tlds", "…"]
}
}Authentication
Authenticate every request with a bearer API key. Create and rotate keys in Settings → API keys.
curl -H "Authorization: Bearer rsk_live_7f3k…" \
https://resellerstack-production.up.railway.app/api/v1/domainsrsk_test_ keys hit the sandbox, nothing provisions, nothing is billed. rsk_live_ keys act on your real account and wallet.
Create a second key, deploy it, then revoke the old one, both stay valid during the overlap, so rotation is zero-downtime.
| Scope | Grants |
|---|---|
| domains:read | Check availability, list domains and DNS |
| domains:write | Register, renew and update domains |
| orders:read | Read orders, margins and timelines |
| orders:write | Create and cancel orders |
| customers:read | List and read customers |
| customers:write | Create and update customers |
| wallet:read | Read balance and ledger |
| webhooks:manage | Configure webhook endpoints |
Errors
Errors use conventional HTTP status codes and a consistent envelope: an error object with a stable machine-readable code and a human message.
| Code | Status | Meaning |
|---|---|---|
| unauthorized | 401 | Missing or malformed API key |
| insufficient_funds | 402 | Wallet balance cannot cover the wholesale cost |
| forbidden | 403 | Key lacks the required scope |
| not_found | 404 | No resource with that id |
| validation_error | 422 | Request body or query failed validation |
| rate_limited | 429 | Too many requests, back off and retry |
{
"error": {
"code": "unauthorized",
"message": "Provide an API key: Authorization: Bearer rsk_live_…"
}
}Rate limits
Each key may make 300 requests per minute with bursts of up to 50 requests. Watch the response headers and back off when you approach zero.
X-RateLimit-Limit: 300
X-RateLimit-Remaining: 287
X-RateLimit-Reset: 1754467200
// When exhausted → 429
{
"error": {
"code": "rate_limited",
"message": "Too many requests. Retry after the X-RateLimit-Reset time."
}
}Webhooks
Push instead of poll: subscribe an HTTPS endpoint to events and ResellerStack delivers a signed JSON payload within seconds of the event.
| Event | Fires when |
|---|---|
| order.created | An order was created (any action) |
| order.provisioned | Registry confirmed provisioning |
| order.renewed | A renewal completed |
| order.failed | Provisioning or renewal failed |
| domain.expiring_30d | Domain enters the 30-day expiry window |
| domain.expiring_7d | Domain enters the 7-day expiry window |
| transfer.initiated | Inbound transfer submitted to the registry |
| transfer.completed | Inbound transfer completed |
| invoice.paid | A customer invoice was paid |
| wallet.low_balance | Balance fell below your alert threshold |
| wallet.auto_topup | An automatic top-up ran |
POST https://api.hurra.com/webhooks/resellerstack
X-RS-Signature: t=1754467201,v1=5f8a1c0e9b2d…
Content-Type: application/json
{
"id": "evt_9f2ka01",
"type": "order.provisioned",
"createdAt": "2026-08-06T09:14:02Z",
"data": {
"orderId": "ord_1006",
"domain": "kolkatacreative.in",
"customerId": "cus_08",
"status": "active"
}
}Every delivery carries an X-RS-Signature header: an HMAC-SHA256 of {timestamp}.{raw body} using your endpoint secret. Recompute it, compare in constant time, and reject anything older than five minutes to prevent replays.
Domains
Availability checks, the domain portfolio, and registration.
/v1/domains/checkCheck availability. Pass domain for a single exact check, or q to sweep every supported TLD. Availability is deterministic per name, and prices come straight from the live price book.
| Parameter | Type | Required | Description |
|---|---|---|---|
| domain | string | No | Exact domain to check, e.g. acme.dev |
| q | string | No | Bare name to check across all supported TLDs |
curl -H "Authorization: Bearer rsk_live_7f3k…" \
"https://resellerstack-production.up.railway.app/api/v1/domains/check?domain=acme.dev"{
"data": [
{
"domain": "acme.dev",
"tld": ".dev",
"supported": true,
"available": true,
"wholesale": { "amount": 1100, "currency": "USD" },
"suggestedRetail": { "amount": 1599, "currency": "USD" }
}
],
"meta": { "query": "acme.dev", "count": 1 }
}/v1/domainsList all domain orders in your account with status, expiry and auto-renew state.
curl -H "Authorization: Bearer rsk_live_7f3k…" \
https://resellerstack-production.up.railway.app/api/v1/domains{
"data": [
{
"id": "ord_1001",
"domain": "nordlicht.studio",
"status": "active",
"customerId": "cus_01",
"expiresAt": "2026-11-02",
"autoRenew": true
},
{
"id": "ord_1002",
"domain": "brightpath.dev",
"status": "expiring",
"customerId": "cus_02",
"expiresAt": "2026-08-21",
"autoRenew": false
}
],
"meta": { "count": 10 }
}/v1/domains/{id}Retrieve a single domain order, including nameservers, DNS records and WHOIS contacts when the domain is provisioned.
| Parameter | Type | Required | Description |
|---|---|---|---|
| id | string (path) | Yes | Domain order id, e.g. ord_1001 |
curl -H "Authorization: Bearer rsk_live_7f3k…" \
https://resellerstack-production.up.railway.app/api/v1/domains/ord_1001{
"data": {
"id": "ord_1001",
"domain": "nordlicht.studio",
"status": "active",
"customerId": "cus_01",
"expiresAt": "2026-11-02",
"autoRenew": true,
"nameservers": ["ns1.resellerstack.net", "ns2.resellerstack.net"],
"dnssec": true,
"privacyProtection": true,
"transferLock": true,
"dnsRecords": [
{ "id": "r1", "type": "A", "host": "@", "value": "76.76.21.21", "ttl": 3600 },
{ "id": "r3", "type": "MX", "host": "@", "value": "mx1.titan.email", "ttl": 3600, "priority": 10 }
]
}
}/v1/domainsRegister a domain. The wholesale cost is drawn from your wallet; the order provisions asynchronously, poll the order or subscribe to order.provisioned.
| Parameter | Type | Required | Description |
|---|---|---|---|
| domain | string | Yes | Full domain to register, e.g. acme.dev |
| years | integer | No | Registration term, 1–10 (default 1) |
| customerId | string | No | Attach the order to an existing customer |
curl -X POST -H "Authorization: Bearer rsk_live_7f3k…" \
-H "Content-Type: application/json" \
-d '{"domain": "acme.dev", "years": 2, "customerId": "cus_02"}' \
https://resellerstack-production.up.railway.app/api/v1/domains{
"data": {
"orderId": "ord_new_acme-dev",
"status": "processing",
"domain": "acme.dev",
"years": 2,
"customerId": "cus_02",
"autoRenew": true
}
}TLDs & pricing
The wholesale price book that drives every quote.
/v1/tldsThe full price book: wholesale register/renew/transfer/restore cost, suggested retail (SRP), and any live promo per TLD. All amounts are minor units (cents), per year.
curl -H "Authorization: Bearer rsk_live_7f3k…" \
https://resellerstack-production.up.railway.app/api/v1/tlds{
"data": [
{
"tld": ".ai",
"category": "new",
"trend": "rising",
"wholesale": {
"register": { "amount": 6200, "currency": "USD" },
"renew": { "amount": 6500, "currency": "USD" },
"transfer": { "amount": 6200, "currency": "USD" },
"restore": { "amount": 18500, "currency": "USD" }
},
"srp": {
"register": { "amount": 8999, "currency": "USD" },
"renew": { "amount": 9499, "currency": "USD" },
"transfer": { "amount": 8999, "currency": "USD" }
},
"promo": {
"register": { "amount": 7999, "currency": "USD" },
"endsAt": "2026-08-31",
"label": "AI summer promo"
}
}
],
"meta": { "count": 15 }
}Orders
Orders across every product, with cost, price and margin.
/v1/ordersList every order, all product categories, with wholesale cost, retail price and your margin.
curl -H "Authorization: Bearer rsk_live_7f3k…" \
https://resellerstack-production.up.railway.app/api/v1/orders{
"data": [
{
"id": "ord_1010",
"customerId": "cus_02",
"productCategory": "domain",
"productLabel": "schweier.ai",
"action": "register",
"status": "pending",
"createdAt": "2026-08-03",
"autoRenew": true,
"cost": { "amount": 6200, "currency": "USD" },
"price": { "amount": 8999, "currency": "USD" },
"margin": { "amount": 2799, "currency": "USD" }
}
],
"meta": { "count": 10 }
}/v1/orders/{id}Retrieve one order with its full event timeline.
| Parameter | Type | Required | Description |
|---|---|---|---|
| id | string (path) | Yes | Order id, e.g. ord_1009 |
curl -H "Authorization: Bearer rsk_live_7f3k…" \
https://resellerstack-production.up.railway.app/api/v1/orders/ord_1009{
"data": {
"id": "ord_1009",
"customerId": "cus_07",
"productLabel": "lyyde.com",
"action": "renew",
"status": "active",
"expiresAt": "2027-06-30",
"cost": { "amount": 950, "currency": "USD" },
"price": { "amount": 1499, "currency": "USD" },
"margin": { "amount": 549, "currency": "USD" },
"timeline": [
{
"at": "2026-06-30T08:00:00Z",
"type": "renewed",
"summary": "Auto-renewed for 1 year",
"actor": "system"
}
]
}
}Customers
The people you sell to.
/v1/customersList your customers with lifetime spend, domain count and open orders.
curl -H "Authorization: Bearer rsk_live_7f3k…" \
https://resellerstack-production.up.railway.app/api/v1/customers{
"data": [
{
"id": "cus_01",
"name": "Evgenii Voitishek",
"company": "Nordlicht Studio",
"email": "evgenii@nordlicht.studio",
"country": "DE",
"status": "active",
"totalSpend": { "amount": 184500, "currency": "USD" },
"domains": 1,
"openOrders": 0,
"tags": ["agency", "priority"]
}
],
"meta": { "count": 10 }
}/v1/customersCreate a customer. New customers start in the invited state until they accept your storefront invite.
| Parameter | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | Full name |
| string | Yes | Unique email address | |
| company | string | No | Company name |
| country | string | No | ISO 3166-1 alpha-2, e.g. US |
curl -X POST -H "Authorization: Bearer rsk_live_7f3k…" \
-H "Content-Type: application/json" \
-d '{"name": "Jane Cooper", "email": "jane@coopers.co", "country": "US"}' \
https://resellerstack-production.up.railway.app/api/v1/customers{
"data": {
"id": "cus_new_jane",
"name": "Jane Cooper",
"email": "jane@coopers.co",
"country": "US",
"status": "invited",
"totalSpend": { "amount": 0, "currency": "USD" },
"domains": 0
}
}/v1/customers/{id}Retrieve one customer, including a compact list of their orders.
| Parameter | Type | Required | Description |
|---|---|---|---|
| id | string (path) | Yes | Customer id, e.g. cus_02 |
curl -H "Authorization: Bearer rsk_live_7f3k…" \
https://resellerstack-production.up.railway.app/api/v1/customers/cus_02{
"data": {
"id": "cus_02",
"name": "Sean Schweier",
"company": "Brightpath Web",
"email": "sean@brightpath.dev",
"country": "US",
"status": "active",
"totalSpend": { "amount": 96200, "currency": "USD" },
"orders": [
{ "id": "ord_1002", "productLabel": "brightpath.dev", "status": "expiring" },
{ "id": "ord_1010", "productLabel": "schweier.ai", "status": "pending" }
]
}
}Invoices
Per-order invoices you issue to customers.
/v1/invoicesList customer invoices. Filter by status to build dunning flows.
| Parameter | Type | Required | Description |
|---|---|---|---|
| status | string | No | paid | due | overdue | refunded | void |
curl -H "Authorization: Bearer rsk_live_7f3k…" \
"https://resellerstack-production.up.railway.app/api/v1/invoices?status=due"{
"data": [
{
"id": "INV-2026-0158",
"orderId": "ord_1003",
"customerId": "cus_04",
"issuedAt": "2026-07-30",
"dueAt": "2026-08-13",
"status": "due",
"method": "payment-link",
"lineItems": [
{
"label": "lagosdigital.ng transfer + 1 yr extension",
"amount": { "amount": 2999, "currency": "USD" }
}
],
"total": { "amount": 2999, "currency": "USD" }
}
],
"meta": { "count": 3, "status": "due" }
}Wallet
Your prepaid balance funds every wholesale purchase.
/v1/walletCurrent balance plus a computed estimate of the wholesale draw from renewals due in the next 30 days, wire this into your treasury alerts.
curl -H "Authorization: Bearer rsk_live_7f3k…" \
https://resellerstack-production.up.railway.app/api/v1/wallet{
"data": {
"balance": { "amount": 201180, "currency": "USD" },
"autoTopup": { "enabled": false },
"upcomingRenewals": {
"windowDays": 30,
"count": 1,
"estimatedDraw": { "amount": 1200, "currency": "USD" },
"items": [
{
"orderId": "ord_1002",
"domain": "brightpath.dev",
"expiresAt": "2026-08-21",
"autoRenew": false,
"wholesaleRenew": { "amount": 1200, "currency": "USD" }
}
]
}
}
}/v1/wallet/transactionsThe wallet ledger, top-ups, order debits, refunds and promo credits, newest first. Amounts are signed; positive is a credit.
curl -H "Authorization: Bearer rsk_live_7f3k…" \
https://resellerstack-production.up.railway.app/api/v1/wallet/transactions{
"data": [
{
"id": "txn_898",
"at": "2026-07-28T09:12:00Z",
"type": "topup",
"description": "Wallet top-up via Stripe",
"amount": { "amount": 50000, "currency": "USD" },
"balanceAfter": { "amount": 210780, "currency": "USD" },
"status": "completed"
}
],
"meta": { "count": 8 }
}Migrations
Bulk transfer-in jobs from other registrars.
/v1/migrationsList transfer-in migration jobs. Auto-mode jobs schedule themselves for 15 days before expiry and chase EPP codes for you.
curl -H "Authorization: Bearer rsk_live_7f3k…" \
https://resellerstack-production.up.railway.app/api/v1/migrations{
"data": [
{
"id": "mig_02",
"domain": "brightpath.co",
"providerId": "namecheap",
"customerId": "cus_02",
"expiresAt": "2026-08-30",
"transferWindowAt": "2026-08-15",
"status": "awaiting-auth",
"autoMode": true,
"events": [
{ "at": "2026-08-02T09:00:00Z", "summary": "Auth-code request emailed to sean@brightpath.dev" }
]
}
],
"meta": { "count": 4 }
}Webhook config
Manage the endpoints that receive event deliveries.
/v1/webhooksList configured webhook endpoints and their delivery health.
curl -H "Authorization: Bearer rsk_live_7f3k…" \
https://resellerstack-production.up.railway.app/api/v1/webhooks{
"data": [
{
"id": "wh_01",
"url": "https://api.hurra.com/webhooks/resellerstack",
"events": ["order.provisioned", "order.renewed", "transfer.completed"],
"active": true,
"lastDeliveryStatus": "ok"
}
],
"meta": { "count": 1 }
}/v1/webhooksCreate a webhook endpoint. The signing secret is returned once, store it and verify every delivery.
| Parameter | Type | Required | Description |
|---|---|---|---|
| url | string | Yes | HTTPS endpoint that receives deliveries |
| events | string[] | Yes | Events to subscribe to (see the event catalog) |
curl -X POST -H "Authorization: Bearer rsk_live_7f3k…" \
-H "Content-Type: application/json" \
-d '{"url": "https://api.example.com/hooks/rs", "events": ["order.provisioned", "invoice.paid"]}' \
https://resellerstack-production.up.railway.app/api/v1/webhooks{
"data": {
"id": "wh_new_8fk2ma",
"url": "https://api.example.com/hooks/rs",
"events": ["order.provisioned", "invoice.paid"],
"active": true,
"secret": "whsec_XXXXXXXXXXXXXXXXXXXXXXXX"
}
}