Your customers and their credits

Add your customers, keep their credit accounts, top up, charge and adjust their credits, block a customer, and set what an operation costs in credits.

A customer here is a customer of your own product, named by the id your system gives them. Slen keeps credit accounts for your customers, takes credits from them when a flow runs for them, and refuses a run they cannot pay for. The operations of this page add and remove customers, set up their accounts, move their credits, block a customer and set what an operation costs in credits. The console shows the same customers on Customers.

Customers and accounts

  • A customer is named by external_user_id, the same id a request that runs a flow sends in context.user_id. It is an opaque id of your own, not an e-mail address or a name.

  • PUT /v1/customers/{externalUserId} adds a customer without credits and without an account. It answers 201 when it created the customer and 200 when the customer was already there, so a repeat needs no key.

  • An account belongs to one customer and one credit type. A credit type is a name of your own, and without one it is default. A customer with two credit types has two accounts.

  • An account is created by the first top-up of its credit type or by its settings. A charge and an adjustment create nothing.

  • An account carries balance, reserved and available. reserved is what running calls hold, and available is balance minus reserved.

  • A customer the project has never seen answers 404 with the code customer_not_found. A customer without accounts answers with an empty accounts.

Reading takes customers:read, and every change takes customers:write, except setting a price, which takes management:write. A key of your application with gateway:write and customers:write runs flows and keeps its customers, and changes nothing else.

The settings of an account

PUT /v1/customers/{externalUserId}/accounts/{creditType} sets both settings of an account at once. It creates the customer and the account when they are missing and answers 201, and otherwise it changes the settings and answers 200.

  • allow_negative lets the account go below zero. It is off by default, and then a hold or a charge the account cannot cover is refused with insufficient_credits. It can be switched off while the balance is below zero: the guard holds from the next movement.

  • low_balance_threshold sets the level of the customer.balance_low webhook event. The event is sent when a movement takes available from that level or above it to below it. Zero, the default, switches the event off.

  • A top-up and an adjustment do not change the settings: a body that names either field is refused with 422.

How a run spends credits

A run spends credits when it names a customer in context.user_id and the project has a credit price for its operation. context.credit_type names the credit type, and without it the type is default. The credit type decides which account pays and which price applies.

  • An operation without a price for that credit type, or with a price of zero, takes no credits.

  • Each model call of the run holds the price on the account before the model is called. When the call is settled, the hold becomes spend, and a call that failed gives it back.

  • An account that cannot cover the price refuses the call with the code insufficient_credits. A customer who has no account of the credit type is refused the same way.

  • A customer the project does not know is refused with the code customer_not_found.

  • A blocked customer is refused with the code customer_blocked — Block a customer.

A price is set for an operation code and a credit type, and the next hold uses it. Setting a price again replaces it, and a hold already taken keeps the price it was taken at.

Move credits

Three operations move credits. Each requires an Idempotency-Key header of at most 190 characters, and a request without it answers 400 with the code idempotency_key_required.

  • A top-up adds credits. It creates the customer and the account when they are missing.

  • A charge takes credits for something your application sells by itself — an export, a seat. The statement shows it as a charge. A customer the project does not know answers 404 with the code customer_not_found, and a customer without an account of the credit type answers 402 with the code insufficient_credits.

  • An adjustment corrects a balance. Its credits is signed, and zero is refused. An account that does not exist answers 404 with the code customer_not_found.

What the three share:

  • credits has at most four digits after the point. A fifth digit is refused with 422, not rounded.

  • note, up to 255 characters, is written on the entry and shown in the statement: an invoice number, a reason.

  • A charge or an adjustment cannot take the balance below what the account holds, unless the account allows a negative balance. Such a request answers 402 with the code insufficient_credits. A top-up is never refused this way, also on an account below zero.

  • A blocked customer can be topped up, charged and adjusted.

  • A charge is not spend: the margin report sets the credits of a call against what the call cost, and no call stands behind a charge.

A repeat under the key moves nothing.

  • Repeating the same request under its key answers 200. For 24 hours, unless the service is set up otherwise, the answer is the first one, with the balance of that moment. After that it is the account as it is now.

  • A key that already names another top-up, charge or adjustment of the project answers 409 with the code idempotency_conflict. For those 24 hours any other body under the key is another request, another note too. After that another customer, another credit type, another kind of movement or another amount is another movement. A new movement needs a new key.

  • A refused movement is not kept: the same request may be sent again under its key.

Block a customer

POST /v1/customers/{externalUserId}/block blocks a customer, and POST /v1/customers/{externalUserId}/unblock lets them in again.

  • A new run of a blocked customer is refused with 403 and the code customer_blocked before anything is created.

  • A run of theirs that is already under way — queued, or waiting for an approval — is refused at the next hold of credits of a model call. The model node leaves through Deny, and without a branch there the execution ends rejected with customer_blocked. A run of an operation without a credit price holds no credits and runs to its end.

  • A repeat of a request under a key it was sent with before the block is answered with that execution.

  • Credits still move, the settings still change and the statement still reads, so you can settle with a blocked customer.

  • blocked_at is the moment of the first block. Blocking again keeps it and replaces block_reason only when a reason is sent. Unblocking clears both.

Delete a customer

DELETE /v1/customers/{externalUserId} removes a customer and their accounts only when nothing ever happened to them: every account is at zero with nothing held, and the statement has no entry. Otherwise the customer stays, and the answer explains why.

409 Conflict
{
  "error": {
    "code": "customer_has_history",
    "message": "The customer has credits or a credit history and cannot be deleted; block it instead",
    "request_id": "5d8a3f1c-2b6e-4c9a-8f17-3e0b9d4c6a25"
  }
}

The statement explains the balance, so it is kept. Block such a customer instead. A delete and a movement of the same customer never pass each other: a delete that meets a top-up under way waits and then refuses, and a top-up that meets a delete under way waits and then creates the customer again.

Read customers and statements

  • The list is paged, newest customer first, and each customer comes with all their accounts. status keeps the active or the blocked customers, q the customers whose external_user_id contains it, and credit_type those with an account of that credit type.

  • low_balance is a number and not a flag: it keeps the customers with an account whose available is below it — an account of credit_type when both are sent. The filters choose customers and never shorten the list of their accounts.

  • The statement of a customer lists every movement of their credits, newest first. An entry carries the account as the movement left it, in balance_after and available_after, and the note of the request. entry_type keeps one kind of movement, and credit_type the movements of one account. A customer without accounts has an empty statement.

entry_typeWhat movedcredits
topupA top-upPositive
chargeA charge of your applicationNegative
adjustAn adjustmentEither
holdA model call held its price from availableNegative
commitThe call was settled, and the held price left balanceNegative
releaseThe hold went back to availablePositive

Do not add credits up to get what a customer spent. A call that spent credits has two negative entries of the same price, its hold and its commit, and only the commit entries are spend.

Operations

End customers with their credit accounts

GET /v1/customers

  • Scope: customers:read
  • Available in the SDK for PHP and Node.js

One cursor page of the project's end customers, newest first, each with every credit account it holds (accounts, by credit_type; empty for a customer created by PUT /v1/customers/{externalUserId} that holds none yet). The filters choose customers: credit_type — those holding an account of that type; low_balance — those holding an account with fewer credits still spendable (balance - reserved) than the threshold, of credit_type when it is given too; status, q. The nested list is never narrowed: a customer that matches comes with all its accounts.

Parameters

ParameterDescription
cursor optional

querystring

The meta.next_cursor of the previous page.

view optional

querystring

customers, the only value and what an absent view answers too. Kept for the clients that send it; any other value is 422.

  • One of: customers
  • Default: customers
limit optional

queryinteger

Page size.

  • Minimum: 1
  • Maximum: 100
  • Default: 50
status optional

queryCustomerStatus

Only customers in this status.

  • One of: active, blocked
credit_type optional

querystring

Customers holding an account of this credit type.

  • Maximum length: 50
low_balance optional

querystring

A threshold, not a flag: ?low_balance=10 means "holds an account with fewer than 10 credits still spendable".

q optional

querystring

Narrows the list to the customers whose external_user_id contains this text. % and _ are matched as themselves.

  • Maximum length: 255

Responses

200

One cursor page of customers

application/json
{
  "data": [
    {
      "customer_id": "74438200973594624",
      "external_user_id": "user_8421",
      "status": "active",
      "blocked_at": "2026-10-02T09:30:00Z",
      "block_reason": "string",
      "accounts": [
        {
          "customer_account_id": "74438200973594624",
          "customer_id": "74438200973594624",
          "project_id": "74438200973594624",
          "external_user_id": "user_8421",
          "credit_type": "default",
          "balance": "12.5000",
          "reserved": "12.5000",
          "available": "12.5000",
          "allow_negative": true,
          "low_balance_threshold": "12.5000",
          "created_at": "2026-10-02T09:30:00Z",
          "updated_at": "2026-10-02T09:30:00Z"
        }
      ],
      "created_at": "2026-10-02T09:30:00Z",
      "updated_at": "2026-10-02T09:30:00Z"
    }
  ],
  "meta": {
    "limit": 1,
    "next_cursor": "string"
  }
}

Errors

StatusCodesWhen
401

No credential, or one that is not valid

403

Authenticated, but not allowed: scope (insufficient_scope), policy or tenant (not_a_member); a blocked end customer (customer_blocked); an act only a signed-in person may take (session_required); the role rule on members and invitations (member_forbidden, invite_forbidden); a write to the organization's own rows, or a read of the audit journal, by a caller that does not reach every project (project_access_restricted)

422

Validation failure or a semantically impossible request. Field-level validation from the framework answers {"message", "errors"}; domain refusals answer the standard error envelope. An Idempotency-Key longer than 190 characters is invalid_request in that envelope.

Headers

  • X-Request-Id

The body of every error is the error envelope.

One end customer with its credit accounts

GET /v1/customers/{externalUserId}

  • Scope: customers:read
  • Available in the SDK for PHP and Node.js

The customer and every credit account it holds, by credit_type. A customer with no account yet answers with accounts: []; an external_user_id the project has never seen is 404 customer_not_found, and so is one of another project. The external_user_id is the caller's opaque identifier — not an email address or a name.

Parameters

ParameterDescription
externalUserId required

pathstring

The end customer's identifier in the caller's own system.

  • Maximum length: 190

Responses

200

The customer

application/json
{
  "data": {
    "customer_id": "74438200973594624",
    "external_user_id": "user_8421",
    "status": "active",
    "blocked_at": "2026-10-02T09:30:00Z",
    "block_reason": "string",
    "accounts": [
      {
        "customer_account_id": "74438200973594624",
        "customer_id": "74438200973594624",
        "project_id": "74438200973594624",
        "external_user_id": "user_8421",
        "credit_type": "default",
        "balance": "12.5000",
        "reserved": "12.5000",
        "available": "12.5000",
        "allow_negative": true,
        "low_balance_threshold": "12.5000",
        "created_at": "2026-10-02T09:30:00Z",
        "updated_at": "2026-10-02T09:30:00Z"
      }
    ],
    "created_at": "2026-10-02T09:30:00Z",
    "updated_at": "2026-10-02T09:30:00Z"
  }
}

Errors

StatusCodesWhen
401

No credential, or one that is not valid

403

Authenticated, but not allowed: scope (insufficient_scope), policy or tenant (not_a_member); a blocked end customer (customer_blocked); an act only a signed-in person may take (session_required); the role rule on members and invitations (member_forbidden, invite_forbidden); a write to the organization's own rows, or a read of the audit journal, by a caller that does not reach every project (project_access_restricted)

404

No such resource for this tenant. Somebody else's resource — and a resource of a project the caller does not reach — answers the same way on purpose: the two must not be distinguishable.

Headers

  • X-Request-Id

The body of every error is the error envelope.

Make sure an end customer exists

PUT /v1/customers/{externalUserId}

  • Scope: customers:write
  • Available in the SDK for PHP and Node.js

Creates the customer when the project has none by this external_user_id (201) and answers the one it has otherwise (200) — idempotent by nature, so no Idempotency-Key: a repeat, or two first calls at once, end with one customer. No credit account is created: a customer without accounts is a legal state, and the first top-up or account setting creates the account of its credit type. The body is an empty object; any field is 422.

Parameters

ParameterDescription
externalUserId required

pathstring

The end customer's identifier in the caller's own system.

  • Maximum length: 190

Request body optional

application/json
{}
  • Maximum keys: 0

Responses

200

The customer already existed

application/json
{
  "data": {
    "customer_id": "74438200973594624",
    "external_user_id": "user_8421",
    "status": "active",
    "blocked_at": "2026-10-02T09:30:00Z",
    "block_reason": "string",
    "accounts": [
      {
        "customer_account_id": "74438200973594624",
        "customer_id": "74438200973594624",
        "project_id": "74438200973594624",
        "external_user_id": "user_8421",
        "credit_type": "default",
        "balance": "12.5000",
        "reserved": "12.5000",
        "available": "12.5000",
        "allow_negative": true,
        "low_balance_threshold": "12.5000",
        "created_at": "2026-10-02T09:30:00Z",
        "updated_at": "2026-10-02T09:30:00Z"
      }
    ],
    "created_at": "2026-10-02T09:30:00Z",
    "updated_at": "2026-10-02T09:30:00Z"
  }
}
201

The customer was created

application/json
{
  "data": {
    "customer_id": "74438200973594624",
    "external_user_id": "user_8421",
    "status": "active",
    "blocked_at": "2026-10-02T09:30:00Z",
    "block_reason": "string",
    "accounts": [
      {
        "customer_account_id": "74438200973594624",
        "customer_id": "74438200973594624",
        "project_id": "74438200973594624",
        "external_user_id": "user_8421",
        "credit_type": "default",
        "balance": "12.5000",
        "reserved": "12.5000",
        "available": "12.5000",
        "allow_negative": true,
        "low_balance_threshold": "12.5000",
        "created_at": "2026-10-02T09:30:00Z",
        "updated_at": "2026-10-02T09:30:00Z"
      }
    ],
    "created_at": "2026-10-02T09:30:00Z",
    "updated_at": "2026-10-02T09:30:00Z"
  }
}

Errors

StatusCodesWhen
401

No credential, or one that is not valid

403

Authenticated, but not allowed: scope (insufficient_scope), policy or tenant (not_a_member); a blocked end customer (customer_blocked); an act only a signed-in person may take (session_required); the role rule on members and invitations (member_forbidden, invite_forbidden); a write to the organization's own rows, or a read of the audit journal, by a caller that does not reach every project (project_access_restricted)

422

Validation failure or a semantically impossible request. Field-level validation from the framework answers {"message", "errors"}; domain refusals answer the standard error envelope. An Idempotency-Key longer than 190 characters is invalid_request in that envelope.

Headers

  • X-Request-Id

The body of every error is the error envelope.

Delete an end customer without history

DELETE /v1/customers/{externalUserId}

  • Scope: customers:write
  • Available in the SDK for PHP and Node.js

Removes the customer and its credit accounts — only when nothing ever happened to them: every account at a zero balance with nothing reserved, and not one entry in its statement. Otherwise 409 customer_has_history: the journal is append-only, its entries explain the balance, so a customer with history is blocked (POST /v1/customers/{externalUserId}/block) rather than deleted. A delete that meets a top-up or a charge of the same customer under way waits for it, and then refuses; a top-up that meets a delete under way waits, and then creates the customer again. An external_user_id the project has never seen is 404 customer_not_found. The external_user_id is the caller's opaque identifier — not an email address or a name: erasing one with history is not offered. Audited.

Parameters

ParameterDescription
externalUserId required

pathstring

The end customer's identifier in the caller's own system.

  • Maximum length: 190

Responses

204

The customer and its accounts are gone

No body

Errors

StatusCodesWhen
401

No credential, or one that is not valid

403

Authenticated, but not allowed: scope (insufficient_scope), policy or tenant (not_a_member); a blocked end customer (customer_blocked); an act only a signed-in person may take (session_required); the role rule on members and invitations (member_forbidden, invite_forbidden); a write to the organization's own rows, or a read of the audit journal, by a caller that does not reach every project (project_access_restricted)

404

No such resource for this tenant. Somebody else's resource — and a resource of a project the caller does not reach — answers the same way on purpose: the two must not be distinguishable.

409

State conflict: idempotency clash, stale draft, illegal transition; the last owner of an organization (last_owner); the owned-organization limit (organization_limit_reached); an end customer with credit history that cannot be deleted (customer_has_history)

Headers

  • X-Request-Id

The body of every error is the error envelope.

Set the settings of one credit account

PUT /v1/customers/{externalUserId}/accounts/{creditType}

  • Scope: customers:write
  • Available in the SDK for PHP and Node.js

The settings of the customer's account of this credit_type: whether it may go below zero (allow_negative) and the level under which a movement sends customer.balance_low (low_balance_threshold, 0 switches the warning off). Both fields are required — the body is the whole of the settings. Creates the customer and the account when they do not exist yet (201); otherwise changes the settings and answers 200. Not a movement of credits, so no Idempotency-Key: the same settings put twice are the same settings. allow_negative: false on an account already below zero is allowed — the guard holds from the next movement on. A blocked customer's settings can be changed.

This is the one place the settings change: a top-up or an adjustment that names either field is 422.

Parameters

ParameterDescription
externalUserId required

pathstring

The end customer's identifier in the caller's own system.

  • Maximum length: 190
creditType required

pathstring

The credit type of the account — tenant-defined text, default when the tenant sells one kind.

  • Maximum length: 50

Request body

application/json
{
  "allow_negative": true,
  "low_balance_threshold": "12.5000"
}

Responses

200

The settings were changed

application/json
{
  "data": {
    "customer_account_id": "74438200973594624",
    "customer_id": "74438200973594624",
    "project_id": "74438200973594624",
    "external_user_id": "user_8421",
    "credit_type": "default",
    "balance": "12.5000",
    "reserved": "12.5000",
    "available": "12.5000",
    "allow_negative": true,
    "low_balance_threshold": "12.5000",
    "created_at": "2026-10-02T09:30:00Z",
    "updated_at": "2026-10-02T09:30:00Z"
  }
}
201

The account was created with these settings

application/json
{
  "data": {
    "customer_account_id": "74438200973594624",
    "customer_id": "74438200973594624",
    "project_id": "74438200973594624",
    "external_user_id": "user_8421",
    "credit_type": "default",
    "balance": "12.5000",
    "reserved": "12.5000",
    "available": "12.5000",
    "allow_negative": true,
    "low_balance_threshold": "12.5000",
    "created_at": "2026-10-02T09:30:00Z",
    "updated_at": "2026-10-02T09:30:00Z"
  }
}

Errors

StatusCodesWhen
401

No credential, or one that is not valid

403

Authenticated, but not allowed: scope (insufficient_scope), policy or tenant (not_a_member); a blocked end customer (customer_blocked); an act only a signed-in person may take (session_required); the role rule on members and invitations (member_forbidden, invite_forbidden); a write to the organization's own rows, or a read of the audit journal, by a caller that does not reach every project (project_access_restricted)

422

Validation failure or a semantically impossible request. Field-level validation from the framework answers {"message", "errors"}; domain refusals answer the standard error envelope. An Idempotency-Key longer than 190 characters is invalid_request in that envelope.

Headers

  • X-Request-Id

The body of every error is the error envelope.

Block an end customer

POST /v1/customers/{externalUserId}/block

  • Scope: customers:write
  • Available in the SDK for PHP and Node.js

A blocked customer's new runs are refused 403 customer_blocked before anything is created (POST /v1/operations/execute with its context.user_id), and a run of theirs already under way is refused at its next hold of credits. The balance can still be moved — top-up, charge, adjustment and the account settings stay open, so the customer can be settled with — and the statement still reads. blocked_at is set the first time; blocking again answers 200 without moving it, and replaces block_reason only when a reason is given. An external_user_id the project has never seen is 404 customer_not_found. Audited.

Parameters

ParameterDescription
externalUserId required

pathstring

The end customer's identifier in the caller's own system.

  • Maximum length: 190

Request body optional

application/json
{
  "reason": "string"
}

Responses

200

The customer, blocked

application/json
{
  "data": {
    "customer_id": "74438200973594624",
    "external_user_id": "user_8421",
    "status": "active",
    "blocked_at": "2026-10-02T09:30:00Z",
    "block_reason": "string",
    "accounts": [
      {
        "customer_account_id": "74438200973594624",
        "customer_id": "74438200973594624",
        "project_id": "74438200973594624",
        "external_user_id": "user_8421",
        "credit_type": "default",
        "balance": "12.5000",
        "reserved": "12.5000",
        "available": "12.5000",
        "allow_negative": true,
        "low_balance_threshold": "12.5000",
        "created_at": "2026-10-02T09:30:00Z",
        "updated_at": "2026-10-02T09:30:00Z"
      }
    ],
    "created_at": "2026-10-02T09:30:00Z",
    "updated_at": "2026-10-02T09:30:00Z"
  }
}

Errors

StatusCodesWhen
401

No credential, or one that is not valid

403

Authenticated, but not allowed: scope (insufficient_scope), policy or tenant (not_a_member); a blocked end customer (customer_blocked); an act only a signed-in person may take (session_required); the role rule on members and invitations (member_forbidden, invite_forbidden); a write to the organization's own rows, or a read of the audit journal, by a caller that does not reach every project (project_access_restricted)

404

No such resource for this tenant. Somebody else's resource — and a resource of a project the caller does not reach — answers the same way on purpose: the two must not be distinguishable.

422

Validation failure or a semantically impossible request. Field-level validation from the framework answers {"message", "errors"}; domain refusals answer the standard error envelope. An Idempotency-Key longer than 190 characters is invalid_request in that envelope.

Headers

  • X-Request-Id

The body of every error is the error envelope.

Lift the block of an end customer

POST /v1/customers/{externalUserId}/unblock

  • Scope: customers:write
  • Available in the SDK for PHP and Node.js

The customer is active again: blocked_at and block_reason are cleared and new runs are accepted. Unblocking a customer that is not blocked answers 200 with the customer as it is. The body is empty; any field is 422. An external_user_id the project has never seen is 404 customer_not_found. Audited.

Parameters

ParameterDescription
externalUserId required

pathstring

The end customer's identifier in the caller's own system.

  • Maximum length: 190

Request body optional

application/json
{}
  • Maximum keys: 0

Responses

200

The customer, active

application/json
{
  "data": {
    "customer_id": "74438200973594624",
    "external_user_id": "user_8421",
    "status": "active",
    "blocked_at": "2026-10-02T09:30:00Z",
    "block_reason": "string",
    "accounts": [
      {
        "customer_account_id": "74438200973594624",
        "customer_id": "74438200973594624",
        "project_id": "74438200973594624",
        "external_user_id": "user_8421",
        "credit_type": "default",
        "balance": "12.5000",
        "reserved": "12.5000",
        "available": "12.5000",
        "allow_negative": true,
        "low_balance_threshold": "12.5000",
        "created_at": "2026-10-02T09:30:00Z",
        "updated_at": "2026-10-02T09:30:00Z"
      }
    ],
    "created_at": "2026-10-02T09:30:00Z",
    "updated_at": "2026-10-02T09:30:00Z"
  }
}

Errors

StatusCodesWhen
401

No credential, or one that is not valid

403

Authenticated, but not allowed: scope (insufficient_scope), policy or tenant (not_a_member); a blocked end customer (customer_blocked); an act only a signed-in person may take (session_required); the role rule on members and invitations (member_forbidden, invite_forbidden); a write to the organization's own rows, or a read of the audit journal, by a caller that does not reach every project (project_access_restricted)

404

No such resource for this tenant. Somebody else's resource — and a resource of a project the caller does not reach — answers the same way on purpose: the two must not be distinguishable.

422

Validation failure or a semantically impossible request. Field-level validation from the framework answers {"message", "errors"}; domain refusals answer the standard error envelope. An Idempotency-Key longer than 190 characters is invalid_request in that envelope.

Headers

  • X-Request-Id

The body of every error is the error envelope.

One end customer's credit statement

GET /v1/customers/{externalUserId}/entries

  • Scope: customers:read
  • Available in the SDK for PHP and Node.js

Every movement of the customer's credits, newest first, each carrying the balance it left behind — so a reader never has to replay the feed to know where the customer stood — and the note its caller gave. Cursor-paged, no date window: a statement is read from the top. An external_user_id the project has never seen is 404 customer_not_found; a customer without an account (or without one of the credit_type asked for) has an empty statement.

Parameters

ParameterDescription
externalUserId required

pathstring

The end customer's identifier in the caller's own system.

  • Maximum length: 190
cursor optional

querystring

The meta.next_cursor of the previous page.

limit optional

queryinteger

Page size (default 30).

  • Minimum: 1
  • Maximum: 100
credit_type optional

querystring

Narrows a customer who holds several pots down to one.

  • Maximum length: 50
entry_type optional

querystring

Only the movements of this type — the top-ups, say, or the charges.

  • One of: hold, commit, release, topup, adjust, charge

Responses

200

One cursor page of credit movements

application/json
{
  "data": [
    {
      "entry_id": "74438200973594624",
      "customer_account_id": "74438200973594624",
      "external_user_id": "user_8421",
      "credit_type": "default",
      "entry_type": "hold",
      "credits": "12.5000",
      "balance_after": "12.5000",
      "available_after": "12.5000",
      "reservation_id": "74438200973594624",
      "note": "string",
      "created_at": "2026-10-02T09:30:00Z"
    }
  ],
  "meta": {
    "limit": 1,
    "next_cursor": "string"
  }
}

Errors

StatusCodesWhen
401

No credential, or one that is not valid

403

Authenticated, but not allowed: scope (insufficient_scope), policy or tenant (not_a_member); a blocked end customer (customer_blocked); an act only a signed-in person may take (session_required); the role rule on members and invitations (member_forbidden, invite_forbidden); a write to the organization's own rows, or a read of the audit journal, by a caller that does not reach every project (project_access_restricted)

404

No such resource for this tenant. Somebody else's resource — and a resource of a project the caller does not reach — answers the same way on purpose: the two must not be distinguishable.

422

Validation failure or a semantically impossible request. Field-level validation from the framework answers {"message", "errors"}; domain refusals answer the standard error envelope. An Idempotency-Key longer than 190 characters is invalid_request in that envelope.

Headers

  • X-Request-Id

The body of every error is the error envelope.

Add credits to an end customer

POST /v1/customers/{externalUserId}/topup

  • Scope: customers:write
  • Idempotency-Key required
  • Available in the SDK for PHP and Node.js

Creates the account when it does not exist yet. Moves money, so it is behind the idempotency middleware.

The Idempotency-Key is also written on the journal entry, where it is unique within the project for as long as the entry exists. A key that already names this top-up — same customer, same credit_type, same credits — answers 200 with the account as it stands now and credits nothing, however long ago the first call was and even while it is still running. A key that names any other top-up, adjustment or charge of the project answers 409 idempotency_conflict and moves nothing. The note does not take part in that comparison; while the stored answer of the first call lasts, any other body under its key — another note included — is 409 idempotency_conflict as for every financial write.

An account the top-up creates starts with allow_negative: false and no low-balance warning. The settings are PUT /v1/customers/{externalUserId}/accounts/{creditType}'s: a body that names allow_negative or low_balance_threshold is 422, as is any field this body does not describe.

Parameters

ParameterDescription
externalUserId required

pathstring

The end customer's identifier in the caller's own system.

  • Maximum length: 190
Idempotency-Key required

headerstring

Replay guard for a financial write. The same key returns the original result with the original status and never charges twice; a different body under a used key answers idempotency_conflict.

  • Maximum length: 190

Request body

application/json
{
  "credits": "12.5000",
  "credit_type": "default",
  "note": "string"
}

Responses

200

The account after the top-up

application/json
{
  "data": {
    "customer_account_id": "74438200973594624",
    "customer_id": "74438200973594624",
    "project_id": "74438200973594624",
    "external_user_id": "user_8421",
    "credit_type": "default",
    "balance": "12.5000",
    "reserved": "12.5000",
    "available": "12.5000",
    "allow_negative": true,
    "low_balance_threshold": "12.5000",
    "created_at": "2026-10-02T09:30:00Z",
    "updated_at": "2026-10-02T09:30:00Z"
  }
}

Errors

StatusCodesWhen
400

Malformed request — e.g. the Idempotency-Key header is missing

401

No credential, or one that is not valid

403

Authenticated, but not allowed: scope (insufficient_scope), policy or tenant (not_a_member); a blocked end customer (customer_blocked); an act only a signed-in person may take (session_required); the role rule on members and invitations (member_forbidden, invite_forbidden); a write to the organization's own rows, or a read of the audit journal, by a caller that does not reach every project (project_access_restricted)

409

State conflict: idempotency clash, stale draft, illegal transition; the last owner of an organization (last_owner); the owned-organization limit (organization_limit_reached); an end customer with credit history that cannot be deleted (customer_has_history)

422

Validation failure or a semantically impossible request. Field-level validation from the framework answers {"message", "errors"}; domain refusals answer the standard error envelope. An Idempotency-Key longer than 190 characters is invalid_request in that envelope.

Headers

  • X-Request-Id

The body of every error is the error envelope.

Correct an end customer's balance

POST /v1/customers/{externalUserId}/adjust

  • Scope: customers:write
  • Idempotency-Key required
  • Available in the SDK for PHP and Node.js

Signed: an adjustment may take credits away. Zero is refused — it would be an audit row saying nothing.

The Idempotency-Key is unique within the project on the journal entry, exactly as for a top-up: repeating the same adjustment under its key answers 200 with the account as it stands now and moves nothing — also when the balance could no longer cover it a second time — and a key that names any other top-up, adjustment or charge answers 409 idempotency_conflict. The note takes no part in that comparison, exactly as for a top-up.

Parameters

ParameterDescription
externalUserId required

pathstring

The end customer's identifier in the caller's own system.

  • Maximum length: 190
Idempotency-Key required

headerstring

Replay guard for a financial write. The same key returns the original result with the original status and never charges twice; a different body under a used key answers idempotency_conflict.

  • Maximum length: 190

Request body

application/json
{
  "credits": "12.5000",
  "credit_type": "default",
  "note": "string"
}

Responses

200

The account after the adjustment

application/json
{
  "data": {
    "customer_account_id": "74438200973594624",
    "customer_id": "74438200973594624",
    "project_id": "74438200973594624",
    "external_user_id": "user_8421",
    "credit_type": "default",
    "balance": "12.5000",
    "reserved": "12.5000",
    "available": "12.5000",
    "allow_negative": true,
    "low_balance_threshold": "12.5000",
    "created_at": "2026-10-02T09:30:00Z",
    "updated_at": "2026-10-02T09:30:00Z"
  }
}

Errors

StatusCodesWhen
400

Malformed request — e.g. the Idempotency-Key header is missing

401

No credential, or one that is not valid

402
403

Authenticated, but not allowed: scope (insufficient_scope), policy or tenant (not_a_member); a blocked end customer (customer_blocked); an act only a signed-in person may take (session_required); the role rule on members and invitations (member_forbidden, invite_forbidden); a write to the organization's own rows, or a read of the audit journal, by a caller that does not reach every project (project_access_restricted)

404

No such resource for this tenant. Somebody else's resource — and a resource of a project the caller does not reach — answers the same way on purpose: the two must not be distinguishable.

409

State conflict: idempotency clash, stale draft, illegal transition; the last owner of an organization (last_owner); the owned-organization limit (organization_limit_reached); an end customer with credit history that cannot be deleted (customer_has_history)

422

Validation failure or a semantically impossible request. Field-level validation from the framework answers {"message", "errors"}; domain refusals answer the standard error envelope. An Idempotency-Key longer than 190 characters is invalid_request in that envelope.

Headers

  • X-Request-Id

The body of every error is the error envelope.

Take credits from an end customer for a service of the application

POST /v1/customers/{externalUserId}/charge

  • Scope: customers:write
  • Idempotency-Key required
  • Available in the SDK for PHP and Node.js

The application's own charge — a PDF export, a seat, anything it sells outside an operation. credits is the positive amount to take; the journal entry is a charge with the amount negative and the note the caller gave. Guarded like every debit: an account with allow_negative off cannot go below what is held on it (402 insufficient_credits). A charge is not spend: the margin report sets credits against provider dollars, and no provider stands behind it. Crossing the account's low_balance_threshold sends customer.balance_low like any movement.

An external_user_id the project has never seen is 404 customer_not_found — nothing is created; a known customer without an account of the credit_type holds no such credits: 402 insufficient_credits. A blocked customer can be charged. Moves money, so it is behind the idempotency middleware, and the Idempotency-Key is unique within the project on the journal entry exactly as for a top-up: the same charge repeated under its key answers 200 with the account as it stands now and takes nothing — also when the balance could no longer cover it a second time — and a key that names any other top-up, adjustment or charge answers 409 idempotency_conflict.

Parameters

ParameterDescription
externalUserId required

pathstring

The end customer's identifier in the caller's own system.

  • Maximum length: 190
Idempotency-Key required

headerstring

Replay guard for a financial write. The same key returns the original result with the original status and never charges twice; a different body under a used key answers idempotency_conflict.

  • Maximum length: 190

Request body

application/json
{
  "credits": "12.5000",
  "credit_type": "default",
  "note": "string"
}

Responses

200

The account after the charge

application/json
{
  "data": {
    "customer_account_id": "74438200973594624",
    "customer_id": "74438200973594624",
    "project_id": "74438200973594624",
    "external_user_id": "user_8421",
    "credit_type": "default",
    "balance": "12.5000",
    "reserved": "12.5000",
    "available": "12.5000",
    "allow_negative": true,
    "low_balance_threshold": "12.5000",
    "created_at": "2026-10-02T09:30:00Z",
    "updated_at": "2026-10-02T09:30:00Z"
  }
}

Errors

StatusCodesWhen
400

Malformed request — e.g. the Idempotency-Key header is missing

401

No credential, or one that is not valid

402
403

Authenticated, but not allowed: scope (insufficient_scope), policy or tenant (not_a_member); a blocked end customer (customer_blocked); an act only a signed-in person may take (session_required); the role rule on members and invitations (member_forbidden, invite_forbidden); a write to the organization's own rows, or a read of the audit journal, by a caller that does not reach every project (project_access_restricted)

404

No such resource for this tenant. Somebody else's resource — and a resource of a project the caller does not reach — answers the same way on purpose: the two must not be distinguishable.

409

State conflict: idempotency clash, stale draft, illegal transition; the last owner of an organization (last_owner); the owned-organization limit (organization_limit_reached); an end customer with credit history that cannot be deleted (customer_has_history)

422

Validation failure or a semantically impossible request. Field-level validation from the framework answers {"message", "errors"}; domain refusals answer the standard error envelope. An Idempotency-Key longer than 190 characters is invalid_request in that envelope.

Headers

  • X-Request-Id

The body of every error is the error envelope.

What an operation costs an end customer in credits

GET /v1/credit-prices

  • Scope: customers:read
  • Available in the SDK for PHP and Node.js

The project's price list: how many credits of which type one run of an operation holds from the customer named by context.user_id. An operation without a price does not touch credits at all. A handful of rows per project, so no cursor; the filters are equality.

Parameters

ParameterDescription
operation_code optional

querystring

Only the prices of this operation code (equality).

  • Maximum length: 120
credit_type optional

querystring

Only the prices in this credit type (equality).

  • Maximum length: 50

Responses

200

Credit prices of the project, by operation code and credit type

application/json
{
  "data": [
    {
      "credit_price_id": "74438200973594624",
      "project_id": "74438200973594624",
      "operation_code": "generate_email",
      "credit_type": "default",
      "credits": "12.5000",
      "created_at": "2026-10-02T09:30:00Z",
      "updated_at": "2026-10-02T09:30:00Z"
    }
  ]
}

Errors

StatusCodesWhen
401

No credential, or one that is not valid

403

Authenticated, but not allowed: scope (insufficient_scope), policy or tenant (not_a_member); a blocked end customer (customer_blocked); an act only a signed-in person may take (session_required); the role rule on members and invitations (member_forbidden, invite_forbidden); a write to the organization's own rows, or a read of the audit journal, by a caller that does not reach every project (project_access_restricted)

422

Validation failure or a semantically impossible request. Field-level validation from the framework answers {"message", "errors"}; domain refusals answer the standard error envelope. An Idempotency-Key longer than 190 characters is invalid_request in that envelope.

Headers

  • X-Request-Id

The body of every error is the error envelope.

Set the credit price of one operation

PUT /v1/credit-prices

  • Scope: management:write

Upsert by (operation_code, credit_type). Zero is allowed — it marks an operation free without deleting the row. A new price takes effect on the next hold; holds already taken keep theirs.

Request body

application/json
{
  "operation_code": "generate_email",
  "credits": "12.5000",
  "credit_type": "default"
}

Responses

200

The stored price

application/json
{
  "data": {
    "credit_price_id": "74438200973594624",
    "project_id": "74438200973594624",
    "operation_code": "generate_email",
    "credit_type": "default",
    "credits": "12.5000",
    "created_at": "2026-10-02T09:30:00Z",
    "updated_at": "2026-10-02T09:30:00Z"
  }
}

Errors

StatusCodesWhen
401

No credential, or one that is not valid

403

Authenticated, but not allowed: scope (insufficient_scope), policy or tenant (not_a_member); a blocked end customer (customer_blocked); an act only a signed-in person may take (session_required); the role rule on members and invitations (member_forbidden, invite_forbidden); a write to the organization's own rows, or a read of the audit journal, by a caller that does not reach every project (project_access_restricted)

422

Validation failure or a semantically impossible request. Field-level validation from the framework answers {"message", "errors"}; domain refusals answer the standard error envelope. An Idempotency-Key longer than 190 characters is invalid_request in that envelope.

Headers

  • X-Request-Id

The body of every error is the error envelope.

Examples

Find the customers who run low

low_balance keeps the customers with an account that has fewer than 20 credits available. This customer has 18 on the balance, and 4 of them are held.

Terminal
curl "https://api.slen.ai/api/v1/customers?low_balance=20" \
  -H "Authorization: Bearer $SLEN_API_KEY"
200 OK
{
  "data": [
    {
      "customer_id": "74439840149372928",
      "external_user_id": "user_3107",
      "status": "active",
      "blocked_at": null,
      "block_reason": null,
      "accounts": [
        {
          "customer_account_id": "74439840153567232",
          "customer_id": "74439840149372928",
          "project_id": "74438200973594624",
          "external_user_id": "user_3107",
          "credit_type": "default",
          "balance": "18.0000",
          "reserved": "4.0000",
          "available": "14.0000",
          "allow_negative": false,
          "low_balance_threshold": "0.0000",
          "created_at": "2026-09-28T11:02:17+00:00",
          "updated_at": "2026-10-02T08:39:51+00:00"
        }
      ],
      "created_at": "2026-09-28T11:02:17+00:00",
      "updated_at": "2026-10-02T08:39:51+00:00"
    }
  ],
  "meta": {
    "limit": 50,
    "next_cursor": null
  }
}

Read a customer

The customer has one account, of the credit type default. A movement that takes its available below 10 sends customer.balance_low.

Terminal
curl https://api.slen.ai/api/v1/customers/user_8421 \
  -H "Authorization: Bearer $SLEN_API_KEY"
200 OK
{
  "data": {
    "customer_id": "74439117522108416",
    "external_user_id": "user_8421",
    "status": "active",
    "blocked_at": null,
    "block_reason": null,
    "accounts": [
      {
        "customer_account_id": "74439117526302720",
        "customer_id": "74439117522108416",
        "project_id": "74438200973594624",
        "external_user_id": "user_8421",
        "credit_type": "default",
        "balance": "82.5000",
        "reserved": "0.0000",
        "available": "82.5000",
        "allow_negative": false,
        "low_balance_threshold": "10.0000",
        "created_at": "2026-10-02T08:40:30+00:00",
        "updated_at": "2026-10-02T09:20:05+00:00"
      }
    ],
    "created_at": "2026-10-02T08:40:00+00:00",
    "updated_at": "2026-10-02T08:40:00+00:00"
  }
}

Add a customer

The body is empty. The customer is new, so the answer is 201, and accounts is empty until a top-up or the settings create one.

Terminal
curl -X PUT https://api.slen.ai/api/v1/customers/user_8421 \
  -H "Authorization: Bearer $SLEN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'
201 Created
{
  "data": {
    "customer_id": "74439117522108416",
    "external_user_id": "user_8421",
    "status": "active",
    "blocked_at": null,
    "block_reason": null,
    "accounts": [],
    "created_at": "2026-10-02T08:40:00+00:00",
    "updated_at": "2026-10-02T08:40:00+00:00"
  }
}

Delete a customer

This customer was added and never topped up, so the customer goes. The answer has no body.

Terminal
curl -X DELETE https://api.slen.ai/api/v1/customers/user_9050 \
  -H "Authorization: Bearer $SLEN_API_KEY"

204 No Content

Set up an account

The settings create the account of the credit type default with a warning below 10 credits. The account cannot go below zero.

Terminal
curl -X PUT https://api.slen.ai/api/v1/customers/user_8421/accounts/default \
  -H "Authorization: Bearer $SLEN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "allow_negative": false,
    "low_balance_threshold": "10"
  }'
201 Created
{
  "data": {
    "customer_account_id": "74439117526302720",
    "customer_id": "74439117522108416",
    "project_id": "74438200973594624",
    "external_user_id": "user_8421",
    "credit_type": "default",
    "balance": "0.0000",
    "reserved": "0.0000",
    "available": "0.0000",
    "allow_negative": false,
    "low_balance_threshold": "10.0000",
    "created_at": "2026-10-02T08:40:30+00:00",
    "updated_at": "2026-10-02T08:40:30+00:00"
  }
}

Block a customer

The reason is shown as block_reason. The accounts keep their credits.

Terminal
curl https://api.slen.ai/api/v1/customers/user_8421/block \
  -H "Authorization: Bearer $SLEN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "reason": "Chargeback on invoice 1042"
  }'
200 OK
{
  "data": {
    "customer_id": "74439117522108416",
    "external_user_id": "user_8421",
    "status": "blocked",
    "blocked_at": "2026-10-02T09:31:10+00:00",
    "block_reason": "Chargeback on invoice 1042",
    "accounts": [
      {
        "customer_account_id": "74439117526302720",
        "customer_id": "74439117522108416",
        "project_id": "74438200973594624",
        "external_user_id": "user_8421",
        "credit_type": "default",
        "balance": "82.5000",
        "reserved": "0.0000",
        "available": "82.5000",
        "allow_negative": false,
        "low_balance_threshold": "10.0000",
        "created_at": "2026-10-02T08:40:30+00:00",
        "updated_at": "2026-10-02T09:20:05+00:00"
      }
    ],
    "created_at": "2026-10-02T08:40:00+00:00",
    "updated_at": "2026-10-02T09:31:10+00:00"
  }
}

Unblock a customer

The request has no body. The customer is active again, and blocked_at and block_reason are cleared.

Terminal
curl -X POST https://api.slen.ai/api/v1/customers/user_8421/unblock \
  -H "Authorization: Bearer $SLEN_API_KEY"
200 OK
{
  "data": {
    "customer_id": "74439117522108416",
    "external_user_id": "user_8421",
    "status": "active",
    "blocked_at": null,
    "block_reason": null,
    "accounts": [
      {
        "customer_account_id": "74439117526302720",
        "customer_id": "74439117522108416",
        "project_id": "74438200973594624",
        "external_user_id": "user_8421",
        "credit_type": "default",
        "balance": "82.5000",
        "reserved": "0.0000",
        "available": "82.5000",
        "allow_negative": false,
        "low_balance_threshold": "10.0000",
        "created_at": "2026-10-02T08:40:30+00:00",
        "updated_at": "2026-10-02T09:20:05+00:00"
      }
    ],
    "created_at": "2026-10-02T08:40:00+00:00",
    "updated_at": "2026-10-02T10:02:00+00:00"
  }
}

Read a customer's statement

The answer holds three movements, newest first: a charge for an export, an adjustment that took 12.5 credits, and the top-up before them.

Terminal
curl https://api.slen.ai/api/v1/customers/user_8421/entries \
  -H "Authorization: Bearer $SLEN_API_KEY"
200 OK
{
  "data": [
    {
      "entry_id": "74439673397166080",
      "customer_account_id": "74439117526302720",
      "external_user_id": "user_8421",
      "credit_type": "default",
      "entry_type": "charge",
      "credits": "-5.0000",
      "balance_after": "82.5000",
      "available_after": "82.5000",
      "reservation_id": null,
      "note": "PDF export 311",
      "created_at": "2026-10-02T09:20:05+00:00"
    },
    {
      "entry_id": "74439652312547328",
      "customer_account_id": "74439117526302720",
      "external_user_id": "user_8421",
      "credit_type": "default",
      "entry_type": "adjust",
      "credits": "-12.5000",
      "balance_after": "87.5000",
      "available_after": "87.5000",
      "reservation_id": null,
      "note": null,
      "created_at": "2026-10-02T09:15:42+00:00"
    },
    {
      "entry_id": "74439117530497024",
      "customer_account_id": "74439117526302720",
      "external_user_id": "user_8421",
      "credit_type": "default",
      "entry_type": "topup",
      "credits": "100.0000",
      "balance_after": "100.0000",
      "available_after": "100.0000",
      "reservation_id": null,
      "note": "Invoice 1042",
      "created_at": "2026-10-02T08:41:00+00:00"
    }
  ],
  "meta": {
    "limit": 30,
    "next_cursor": null
  }
}

Top up a customer

The key names this top-up, and a repeat under the same key adds nothing. The note names the invoice it was paid by.

Terminal
curl https://api.slen.ai/api/v1/customers/user_8421/topup \
  -H "Authorization: Bearer $SLEN_API_KEY" \
  -H "Idempotency-Key: topup-user_8421-invoice-1042" \
  -H "Content-Type: application/json" \
  -d '{
    "credits": "100",
    "note": "Invoice 1042"
  }'
200 OK
{
  "data": {
    "customer_account_id": "74439117526302720",
    "customer_id": "74439117522108416",
    "project_id": "74438200973594624",
    "external_user_id": "user_8421",
    "credit_type": "default",
    "balance": "100.0000",
    "reserved": "0.0000",
    "available": "100.0000",
    "allow_negative": false,
    "low_balance_threshold": "10.0000",
    "created_at": "2026-10-02T08:40:30+00:00",
    "updated_at": "2026-10-02T08:41:00+00:00"
  }
}

Adjust a balance

A negative amount takes credits away.

Terminal
curl https://api.slen.ai/api/v1/customers/user_8421/adjust \
  -H "Authorization: Bearer $SLEN_API_KEY" \
  -H "Idempotency-Key: adjust-user_8421-refund-77" \
  -H "Content-Type: application/json" \
  -d '{
    "credits": "-12.5"
  }'
200 OK
{
  "data": {
    "customer_account_id": "74439117526302720",
    "customer_id": "74439117522108416",
    "project_id": "74438200973594624",
    "external_user_id": "user_8421",
    "credit_type": "default",
    "balance": "87.5000",
    "reserved": "0.0000",
    "available": "87.5000",
    "allow_negative": false,
    "low_balance_threshold": "10.0000",
    "created_at": "2026-10-02T08:40:30+00:00",
    "updated_at": "2026-10-02T09:15:42+00:00"
  }
}

Charge a customer

Your application takes 5 credits for an export it made. The key names the export, so a repeat takes nothing more.

Terminal
curl https://api.slen.ai/api/v1/customers/user_8421/charge \
  -H "Authorization: Bearer $SLEN_API_KEY" \
  -H "Idempotency-Key: charge-user_8421-export-311" \
  -H "Content-Type: application/json" \
  -d '{
    "credits": "5",
    "note": "PDF export 311"
  }'
200 OK
{
  "data": {
    "customer_account_id": "74439117526302720",
    "customer_id": "74439117522108416",
    "project_id": "74438200973594624",
    "external_user_id": "user_8421",
    "credit_type": "default",
    "balance": "82.5000",
    "reserved": "0.0000",
    "available": "82.5000",
    "allow_negative": false,
    "low_balance_threshold": "10.0000",
    "created_at": "2026-10-02T08:40:30+00:00",
    "updated_at": "2026-10-02T09:20:05+00:00"
  }
}

List the credit prices

The project has one price.

Terminal
curl https://api.slen.ai/api/v1/credit-prices \
  -H "Authorization: Bearer $SLEN_API_KEY"
200 OK
{
  "data": [
    {
      "credit_price_id": "74440031913676800",
      "project_id": "74438200973594624",
      "operation_code": "generate_email",
      "credit_type": "default",
      "credits": "2.0000",
      "created_at": "2026-10-02T08:30:00+00:00",
      "updated_at": "2026-10-02T08:30:00+00:00"
    }
  ]
}

Set a credit price

From the next hold on, one model call of the operation costs a customer two credits.

Terminal
curl -X PUT https://api.slen.ai/api/v1/credit-prices \
  -H "Authorization: Bearer $SLEN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "operation_code": "generate_email",
    "credits": "2"
  }'
200 OK
{
  "data": {
    "credit_price_id": "74440031913676800",
    "project_id": "74438200973594624",
    "operation_code": "generate_email",
    "credit_type": "default",
    "credits": "2.0000",
    "created_at": "2026-10-02T08:30:00+00:00",
    "updated_at": "2026-10-02T08:30:00+00:00"
  }
}

Where to go next

  • Customer credits — the same customers in the console.

  • Customers and credits — the same operations from the SDK.

  • Analytics — the credits your customers were charged, against what their calls cost.

  • Authentication — the scopes a key needs to read and to change customers.

  • Overview — how credits are written in a request and in an answer.

  • Error codes — every code of the API, what it means and what to do about it.

  • Webhooks — how customer.balance_low arrives.

Built from openapi b070e1f, sdk contract 6a2e0e0, php 4089db3, node 0fa87be