Dashboard
APISubscription Bot API Reference | BotSubscription

The BotSubscription API

This REST API provides endpoints for managing projects, users, subscriptions, payments, and related resources. All endpoints require authentication unless explicitly specified otherwise.

Quick reference

Authentication

Include your project API key in the Authorization header:

Authorization: Bearer YOUR_API_KEY

This REST API reference is for project API keys. Each key can access only its own project. Restricted keys need the scope listed on the endpoint page. Unrestricted keys can use supported endpoints without individual scope grants; endpoint-specific restrictions still apply.

Language Selection

Specify the language for translated messages by sending an Accept-Language header:

Accept-Language: bg

If the header is omitted, English (en) is used.

Common Response Format

Successful responses with a body use this envelope. A 204 No Content response has no body; message and pagination fields are included only when applicable.

Endpoint examples use fictional IDs, names, dates, amounts and URLs in the response's wire format. Optional fields may be omitted; nullable fields may be null. The endpoint's response examples show conditional variants where applicable. Treat metadata described as opaque as an arbitrary JSON object, not a fixed set of example keys.

{
  "ok": true,
  "request_id": "44444444-4444-4444-8444-444444444444",
  "method": "GET",
  "path": "/v2/projects/11111111-1111-4111-8111-111111111111/users",
  "code": 200,
  "message": "Users retrieved successfully",
  "total": 0,
  "data": []
}

UTC ISO response dates

Date and time fields defined in REST response bodies use UTC ISO strings with milliseconds: YYYY-MM-DDTHH:mm:ss.sssZ, for example "2030-01-01T00:00:00.000Z". Nullable dates remain null, and optional dates remain omitted when unset, according to each field's contract.

Counts and durations remain numeric. Arbitrary settings values, custom metadata, and opaque provider JSON keep their original values and types. Declared dates follow their documented response format regardless of where their values originated.

Decimal amounts

Send plan prices, coupon values and checkout amounts as decimal strings, such as "29.99". For these inputs, strings must be nonnegative plain decimals with at most 18 fractional digits. Signs, leading zeroes such as "01", and exponent strings such as "1e-7" are rejected. Each endpoint can impose additional bounds.

JSON numbers are also accepted, but their parsed value must be no greater than 9007199254740991, must be reproducible with 15 significant digits, and must fit the decimal range. For example, numeric 0.30000000000000004 is rejected with 422 VALIDATION_ERROR; send the intended exact amount as a string. A JSON parser can already have rounded a numeric value before validation, so use strings whenever every digit matters.

Plan prices also follow the currency's decimal limit: USD permits 2 places, JPY permits 0, BTC permits 8, and ETH permits 18. Trailing zeroes do not add precision: "10.000" is valid for USD, while "10.006" is rejected.

Non-null monetary amounts returned by the API are strings. Use decimal arithmetic rather than converting response amounts to floating-point numbers.

Revenue totals, including renewal-calendar totals, follow the currency's precision. Do not assume every currency uses two decimal places.

Error Responses

Business and authentication failures can use a singular error:

{
  "ok": false,
  "request_id": "44444444-4444-4444-8444-444444444444",
  "method": "GET",
  "path": "/v2/projects/11111111-1111-4111-8111-111111111111/users",
  "code": 401,
  "error": {
    "error_code": "UNAUTHORIZED",
    "message": "Invalid or expired authentication token."
  }
}

Request-schema validation can return multiple failures in errors, even when only one field fails:

{
  "ok": false,
  "request_id": "44444444-4444-4444-8444-444444444444",
  "method": "GET",
  "path": "/v2/projects/11111111-1111-4111-8111-111111111111/access-tokens/eligibility",
  "code": 422,
  "errors": [
    {
      "message": "query: count is too big; maximum allowed is 100",
      "error_code": "VALIDATION_ERROR"
    }
  ]
}

Handle both error and errors; use error_code and HTTP status for branching rather than matching message text.

The singular error.message may be omitted. Entries in errors require error_code and message; an optional string field may identify the invalid field. Do not require every validation failure to include a field path.

Error Codes

CodeDescription
400Bad Request - Invalid input parameters
401Unauthorized - Missing or invalid authentication
403Forbidden - Credential or project access is not permitted
404Not Found - Resource not found in the project
409Conflict - State or idempotency conflict
422Validation Error - Invalid data format
429Too Many Requests - Wait for the indicated retry delay
500Server Error - Internal server error
503Service Unavailable - Temporary project or service unavailability

Temporary project unavailability

Project requests can return 503 SERVICE_UNAVAILABLE, including during updates or restores. A Retry-After header and error.retry_after_seconds can indicate how many seconds to wait. Retry reads after that delay.

For writes, follow the endpoint recovery guidance and preserve the original body and Idempotency-Key when retrying. A 503 does not establish that no write occurred. Do not switch keys to bypass recovery.

Idempotency for authenticated writes

Idempotency-Key is an optional HTTP header supported across authenticated POST, PUT, PATCH, and DELETE endpoints in this reference. It is not a body field, query parameter, or additional scope. The playground exposes it under Headers on every supported write endpoint.

Choose one key per logical action. Reuse it with the same API key and unchanged request after a network failure. Changing the method, route, resource, query, or body can cause a mismatch. Do not generate a new key for every retry. UUID-shaped keys are case-normalized; other nonempty keys are case-sensitive. Blank values are treated as absent.

Default replay

Unless an endpoint lists an exception below, a repeated key and request replays the original status and body with Idempotent-Replayed: true. A 204 still has no body. Successful responses are normally retained for 24 hours; caller errors other than 409 and 429 are retained for one hour. Handler 5xx, 409, and 429 results can execute again on a later retry.

This is retry suppression within finite windows, not an exactly-once guarantee. Do not assume every original response header will be replayed. A response-formatting 5xx after a write does not establish that the write failed; reconcile resource state before starting a new action.

Endpoint-specific recovery

EndpointsBehavior
Create Payment Request; Redeem for MemberThe shared header binds the key to the request without providing the default response replay or concurrency guarantee. Follow the endpoint's recovery guidance.
Prepare Tokens; Create Webhook; Install Merchant Account; Verify Provider WebhookSave the first successful response. A completed keyed success cannot be replayed and is not re-executed under the completed record.

Payment creation has its own duplicate-submit handling, with a successful rich-response window normally lasting ten minutes. Redemption recovers by the same code and recipient. Neither is a promise of the shared 24-hour response cache.

Idempotency errors

Status and errorRecovery
422 IDEMPOTENCY_KEY_MISMATCHThe key is bound to a different request. Reconcile the original action; use a new key only for a new intent.
409 IDEMPOTENCY_KEY_IN_PROGRESSThe first attempt is still running. Wait for Retry-After and retry unchanged.
409 IDEMPOTENCY_RESPONSE_NOT_REPLAYABLERead resource state or follow endpoint recovery instructions. This does not prove completion and does not justify a duplicate action with a new key.
503 IDEMPOTENCY_UNAVAILABLEWait for Retry-After and retry the same key and request.
429 IDEMPOTENCY_KEY_LIMIT_EXCEEDEDWait for the key window to reset, as indicated by Retry-After. The request was not executed.

Nonreplayable results can also follow a response that exceeds replay storage limits or an operation that outlives its admission lease. Preserve the original request while resolving an uncertain result.

Default new-key budgets are 20,000 per caller per 24 hours for replay/nonreplayable routes, with a 100,000 admission threshold for guard-only routes using the same counter. Defaults are configurable. Response replay is also bounded by 512 KiB per response and 8 MiB retained response bytes per caller/window. These limits are separate from request rate limits.

Pagination

List endpoints support pagination using the following query parameters:

ParameterDescription
limitNumber of items per page (default varies by endpoint)
offsetNumber of items to skip (default: 0)

Outbound Webhooks (Real-Time Events)

For server-to-server integrations, BotSubscription supports outbound webhooks. You can register HTTPS POST endpoints per project to receive real-time notifications for payment completion and other platform events.

To get started, see our comprehensive Webhooks Overview or explore active events like payment-request.completed.

Health Check

  • GET /ping
  • No authentication required
  • Returns: { "ok": true }
Last updated: