Overview
Authenticate, paginate, and handle errors against the Arcalotl public REST API.
The Arcalotl public API gives your own systems programmatic access to the same subscriptions, plans, members, and analytics your dashboard shows: read resources, check entitlements, cancel a subscription, generate a checkout link, and subscribe to webhooks for the events that matter to you.
Base URL
https://api.arcalotl.com/v1Every resource is scoped to the community that owns the API key used to call
it. An id that belongs to another community answers 404, never 403, so
responses cannot be used to probe another community's data.
Authentication
Every request needs a bearer API key:
Authorization: Bearer arclt_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxCreate and revoke keys from the dashboard: Developers -> API Keys. The
full key is shown exactly once at creation time; only a display prefix
(arclt_live_xxxxxxxx) is stored and shown afterward. Treat a key like a
password: do not commit it, and rotate it if it leaks.
Scopes
A key carries one or more scopes chosen at creation time. A request without
the scope a route requires gets a 403 with code missing_scope.
| Scope | Grants |
|---|---|
subscriptions:read | List and get subscriptions |
subscriptions:write | Cancel a subscription |
plans:read | List and get plan tiers |
members:read | List members, look up by platform identity, read entitlements |
purchases:read | List and get one-time purchases |
analytics:read | Read the analytics summary |
events:read | Poll the events feed |
checkout:write | Create a hosted checkout link |
webhooks:read | List webhook endpoints and their deliveries |
webhooks:write | Create, update, delete, rotate, redeliver, and test webhook endpoints |
Endpoints
| Method | Path | Scope | Notes |
|---|---|---|---|
| GET | /v1/subscriptions | subscriptions:read | Filters: status, plan_id, tier_id, member_id. Cursor-paginated. |
| GET | /v1/subscriptions/{id} | subscriptions:read | |
| POST | /v1/subscriptions/{id}/cancel | subscriptions:write | Schedules cancellation at period end. Idempotent; supports Idempotency-Key. |
| GET | /v1/plans | plans:read | Plan tiers with nested billing plans. |
| GET | /v1/plans/{tierId} | plans:read | |
| GET | /v1/members | members:read | Cursor-paginated. |
| GET | /v1/members/{id} | members:read | Includes platform identities. |
| GET | /v1/members/lookup | members:read | ?platform=discord&platform_uid=... |
| GET | /v1/members/{id}/entitlements | members:read | Active subscriptions and unexpired purchases resolved to tiers. |
| GET | /v1/entitlements/check | members:read | ?platform=&platform_uid=&tier_id=. The primitive for gating access from a game server or external tool. |
| GET | /v1/purchases | purchases:read | Cursor-paginated. |
| GET | /v1/purchases/{id} | purchases:read | |
| GET | /v1/analytics/summary | analytics:read | MRR, active subscribers, recent signups and cancels. |
| POST | /v1/checkout-links | checkout:write | Creates a hosted checkout session. Supports Idempotency-Key. See Checkout links. |
| GET | /v1/events | events:read | Filters: type, after_id. Cursor-paginated. See Events. |
| GET | /v1/events/{id} | events:read | |
| GET | /v1/webhooks/event-types | any valid key | Machine-readable event catalog. See Webhooks. |
| GET, POST | /v1/webhooks/endpoints | webhooks:read / webhooks:write | POST returns the whsec_ signing secret once. |
| GET, PATCH, DELETE | /v1/webhooks/endpoints/{id} | webhooks:read / webhooks:write | PATCH accepts url, description, event_types, enabled. |
| POST | /v1/webhooks/endpoints/{id}/rotate-secret | webhooks:write | Returns a new whsec_ secret once. |
| GET | /v1/webhooks/endpoints/{id}/deliveries | webhooks:read | Cursor-paginated attempt log. |
| POST | /v1/webhooks/endpoints/{id}/deliveries/{deliveryId}/redeliver | webhooks:write | Requeues a delivery for retry. |
| POST | /v1/webhooks/endpoints/{id}/test | webhooks:write | Sends a signed ping envelope synchronously. Rate-limited to 10/min per endpoint. |
Pagination
List endpoints take an opaque cursor and a limit (max 100, default 25) and
return a next_cursor:
{
"data": [ ... ],
"next_cursor": "eyJjcmVhdGVkX2F0IjoiMjAyNi0wNy0wMVQxMjowMDowMFoiLCJpZCI6IjEyMyJ9"
}next_cursor is null (or omitted) on the last page. Pass it back as
cursor to fetch the next page; do not construct or parse cursor values
yourself, since their internal shape is not part of the contract.
Errors
Errors are RFC 9457 application/problem+json
bodies with a stable code extension member for programmatic handling:
{
"type": "https://docs.arcalotl.com/api/errors#not_found",
"title": "Not Found",
"status": 404,
"detail": "The requested resource was not found.",
"code": "not_found"
}Match on code, not on title or detail, which may change wording without
notice.
| Code | Status | Meaning |
|---|---|---|
unauthorized | 401 | Missing, malformed, unknown, or revoked API key. One uniform response for all four so a response cannot be used to guess key state. |
missing_scope | 403 | The key does not carry the scope the route requires. |
not_found | 404 | The resource does not exist, or belongs to another community. |
invalid_request | 400 or 422 | Malformed input: a bad query parameter, an unknown platform, or a body that fails validation. |
conflict | 409 | The resource is not in a state that allows the requested action, or checkout eligibility fails. |
payment_config_inactive | 409 | The community has no active payment provider configuration. |
plan_required | 422 | The tier has more than one active plan; plan_id is required. |
platform_not_connected | 422 | The community has no configuration for the requested platform. |
not_eligible | 409 | The buyer is not eligible for checkout on this tier (already subscribed, already purchased, or a plan switch is required instead). |
idempotency_key_reuse | 422 | The Idempotency-Key was already used for a request with a different body. |
request_in_flight | 409 | A request with the same Idempotency-Key is still being processed. |
endpoint_limit | 422 | The community already has the maximum of 5 webhook endpoints. |
rate_limited | 429 | Rate limit exceeded. See Rate limits. |
service_unavailable | 503 | An optional subsystem (webhook management) is not configured on this deployment. |
internal_error | 500 | Unexpected server error. |
Rate limits
The API is rate-limited per key, in addition to a lighter pre-authentication limit per client IP:
| Limiter | Key | Default |
|---|---|---|
| Authenticated | API key | 300 requests/min, burst 60 |
| Unauthenticated | Client IP | 20 requests/min, burst 10 |
| Webhook test-send | Endpoint | 10 requests/min |
Every response carries rate limit headers:
RateLimit-Limit: 300
RateLimit-Remaining: 299
RateLimit-Reset: 12A 429 additionally carries Retry-After (seconds). Back off and retry after
that interval rather than polling faster.
Idempotency
POST /v1/subscriptions/{id}/cancel and POST /v1/checkout-links accept an
Idempotency-Key header so a network retry cannot double-cancel a
subscription or double-create a checkout session:
Idempotency-Key: a-client-generated-unique-string- The same key with the same request body within 24 hours replays the
original response and adds
Idempotent-Replayed: true. - The same key with a different request body returns
422 idempotency_key_reuse. - The same key while the first request is still being processed returns
409 request_in_flight. - Keys are scoped per community and per endpoint, and expire after 24 hours.
Use a fresh key per logical operation (for example a UUID you generate once per cancel button click), not a constant value.
Versioning
The API and the webhook event envelope share one version string, currently
2026-07. Within a version, changes are additive only: new fields, new
optional request parameters, new event types, and new endpoints. Existing
fields and endpoints do not change shape or meaning without a new version.
Ignore fields you do not recognize so additive changes never break your
integration.
OpenAPI spec
The full request and response contract is published as an OpenAPI 3.1 document: arcalotl-public-api.yaml.
Next steps
- Webhooks: event envelope, the full event catalog, and signature verification.
- Events: polling
GET /v1/eventsfor reconciliation. - Checkout links: sell a plan from your own systems.
- MCP: connect an AI agent to the same API.