DocsIntroduction
REST API (v1)
JSON over HTTPS with bearer keys, one error format with stable codes, idempotency keys for safe retries, cursor pagination, batch orders and signed webhooks.
Requests
The base URL is https://orbismm.com/api/v1. Send request bodies as JSON with Content-Type: application/json. Every answer is JSON.
Objects carry an object field (order, service, refill, account, webhook_endpoint) and most carry livemode, which is false for sandbox data. Money is a USD string with four decimals; times are ISO 8601 in UTC.
Authentication
Send your key as a bearer token on every request. Create keys in the panel under API & webhooks; see Get an API key.
Request
curl https://orbismm.com/api/v1/me \
-H "Authorization: Bearer orb_live_…"A missing or wrong key gets 401 invalid_api_key. A key used from an address outside its IP allowlist gets 403 ip_not_allowed.
Scopes
Each key has one or more scopes. A request outside them gets 403 missing_scope.
| Scope | Endpoints |
|---|---|
read | GET /v1/me, POST /v1/sandbox/reset, GET on services, orders and refills |
orders | POST /v1/orders, /v1/orders/batch, /cancel and /refill |
webhooks | Everything under /v1/webhooks |
Errors
Every error has the same shape: an HTTP status and an error object with a stable, machine-readable code and a message in English. Validation errors add fields, with the problems for each field.
Request
curl https://orbismm.com/api/v1/orders \
-H "Authorization: Bearer $ORBISMM_KEY" \
-H "Content-Type: application/json" \
-d '{"link":"https://www.instagram.com/yourbrand"}'
Error · 422 Unprocessable Content
{
"error": {
"code": "invalid_request",
"message": "The service field is required.",
"fields": {
"service": [
"The service field is required."
],
"quantity": [
"The quantity field is required."
]
}
}
}Branch on code; messages may be reworded.
| Status | Code | When |
|---|---|---|
| 401 | invalid_api_key | Missing, wrong, revoked or rolled key. |
| 402 | not_enough_funds | Your balance doesn’t cover the order. |
| 403 | ip_not_allowed | The key’s IP allowlist doesn’t include this address. |
| 403 | missing_scope | The key lacks the scope this endpoint needs. |
| 403 | account_suspended | The account is suspended. |
| 403 | sandbox_only | A live key called POST /v1/sandbox/reset. |
| 404 | not_found | No such order, service, refill, endpoint or URL. Objects from the other environment (live or sandbox) are not found either. |
| 409 | idempotency_conflict | The Idempotency-Key was used for a different request. |
| 409 | order_closed | Cancel on an order that is already closed. |
| 409 | refill_not_available | The order hasn’t completed yet, or the supplier can’t take a refill right now. |
| 409 | refill_window_ended | The refill window for the order has passed. |
| 409 | refill_in_progress | A refill for the order is still running. |
| 422 | invalid_request | A field is missing or has the wrong type. See fields. |
| 422 | incorrect_service | No such service, or it is paused. |
| 422 | incorrect_link | The link is empty or longer than 1,000 characters. |
| 422 | quantity_out_of_range | Quantity outside the service’s minimum and maximum. |
| 422 | dripfeed_not_supported | runs sent for a service without drip-feed. |
| 422 | cancel_not_supported | The service can’t be canceled. |
| 422 | refill_not_supported | The service has no refill. |
| 422 | invalid_url | A webhook URL that isn’t public HTTPS. |
| 422 | limit_reached | Already 10 webhook endpoints in this environment. |
| 429 | rate_limited | Too many requests. Wait for Retry-After seconds. |
Any other HTTP error, such as a wrong method on a known URL, comes back with the code http_error.
Rate limits
Each key can make 60 requests per second, unless we have set a different limit for your account. The budget is per key and separate from API v2. Responses carry X-RateLimit-Limit and X-RateLimit-Remaining; over the limit you get 429 rate_limited with a Retry-After header in seconds. Requests sent without a key share one budget per IP address.
For many new orders at once, one batch call with up to 100 orders is kinder to your budget than 100 single calls. For status, webhooks save polling altogether.
Idempotency
Networks fail; a request can time out after we placed the order. Send an Idempotency-Key header (1 to 64 characters, a UUID works well) on POST /v1/orders, and a retry with the same key can never place a second order.
- First request: the order is placed,
201 Created. - Same key, same request: you get the first order back with
200 OKand the headerIdempotent-Replayed: true. Nothing is charged again. - Same key, different request (another service, link, quantity,
runsorinterval, or live instead of sandbox):409 idempotency_conflict. - Two identical requests racing each other still produce one order.
A key stays tied to the order it created, so use a new key for every new order. In a batch, put an idempotency_key on each item instead of the header.
Request
curl -i https://orbismm.com/api/v1/orders \
-H "Authorization: Bearer $ORBISMM_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 3f6c2a9e-8d41-4b7a-9e0c-5d2f1b7a4c88" \
-d '{"service":1001,"link":"https://www.instagram.com/yourbrand","quantity":1000}'
# First call: HTTP/1.1 201 Created
# Retry: HTTP/1.1 200 OK
# Idempotent-Replayed: true
# (same order ID, no second charge)Pagination
GET /v1/orders pages with a cursor, newest orders first. Ask for up to 100 with limit (default 50). When has_more is true, pass next_cursor as starting_after to get the next page. Other lists (services, webhook endpoints) return everything in one answer.
Request
curl "https://orbismm.com/api/v1/orders?limit=50" \
-H "Authorization: Bearer $ORBISMM_KEY"
Response · 200 OK
{
"data": [
"…50 orders…"
],
"has_more": true,
"next_cursor": 58164
}
curl "https://orbismm.com/api/v1/orders?limit=50&starting_after=58164" \
-H "Authorization: Bearer $ORBISMM_KEY"Live and sandbox
Live keys (orb_live_…) and test keys (orb_test_…) use the same URLs but never see each other’s data: orders, refills, balance and webhook endpoints are kept apart. Everything a test key touches haslivemode: false. See Sandbox.
All endpoints
| Endpoint | Scope | Does |
|---|---|---|
GET /v1/me | read | Your account and balance |
POST /v1/sandbox/reset | read | Reset the sandbox balance (test keys) |
GET /v1/services | read | List services |
GET /v1/services/{id} | read | Get a service |
POST /v1/orders | orders | Place an order |
POST /v1/orders/batch | orders | Place up to 100 orders |
GET /v1/orders | read | List orders |
GET /v1/orders/{id} | read | Get an order |
POST /v1/orders/{id}/cancel | orders | Cancel an order |
POST /v1/orders/{id}/refill | orders | Request a refill |
GET /v1/refills/{id} | read | Get a refill |
GET /v1/webhooks | webhooks | List webhook endpoints |
POST /v1/webhooks | webhooks | Add an endpoint |
GET /v1/webhooks/{id} | webhooks | Get an endpoint and its deliveries |
PATCH /v1/webhooks/{id} | webhooks | Change an endpoint |
DELETE /v1/webhooks/{id} | webhooks | Delete an endpoint |
POST /v1/webhooks/{id}/test | webhooks | Send a test event |
POST /v1/webhooks/{id}/rotate-secret | webhooks | Replace the signing secret |
The same API is described in OpenAPI 3.1 at https://orbismm.com/api/v1/openapi.json. Import it into Postman or Insomnia, or generate a client from it.