Misar IO Docs

Deduct credits

POST /io/wallet/deduct — atomically charge credits for a feature. Service-key only, fail-closed, idempotent.

Atomically charges credits against a user's balance for a billable feature. The check (does the user have enough?) and the debit happen in a single atomic operation, so concurrent calls can never overspend.

POST https://api.misar.io/io/wallet/deduct

Service key only

Charging credits is never client-initiated. This endpoint requires x-wallet-service-key and rejects SSO bearer tokens.

Authentication

x-wallet-service-key: <WALLET_SERVICE_KEY>
Content-Type: application/json

Body parameters

user_idstringrequired

The Misar SSO user id to charge.

featurestringrequired

The billable feature key (e.g. blog.article.generate). The number of credits charged is count multiplied by the feature's per-unit rate from the credit rate table.

countnumberdefault: 1

How many units of the feature to charge. Defaults to 1.

idempotency_keystring

A stable key (e.g. article slug, job/run id) that makes retries safe. Re-sending the same idempotency_key will not double-charge — the original result is returned. See Idempotency & concurrency.

Request

curl -X POST "https://api.misar.io/io/wallet/deduct" \
  -H "x-wallet-service-key: $WALLET_SERVICE_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "user_id": "usr_123",
    "feature": "blog.article.generate",
    "count": 1,
    "idempotency_key": "article:my-post-slug"
  }'

Response

When the charge succeeds:

{
  "allowed": true,
  "balanceBefore": 42,
  "balanceAfter": 41,
  "deducted": 1
}

When the user lacks sufficient credits, nothing is debited:

{
  "allowed": false,
  "balanceBefore": 0,
  "required": 1
}
allowedboolean

true if the credits were debited; false if the balance was insufficient or the request failed. Always check this before granting the feature.

balanceBeforenumber

The balance immediately before this operation.

balanceAfternumber

The balance after a successful debit. Present only when allowed is true.

deductednumber

The number of credits actually debited. Present only when allowed is true.

requirednumber

How many credits the operation needed. Present when allowed is false so you can prompt the user to top up by the shortfall.

Fail-closed behavior

A failure denies usage — never grants it

If the ledger is unreachable, the request times out, or the response is malformed, the wallet (and the SDK) return allowed: false. Treat allowed: false as "do not run the billable feature." A billing outage must never result in free usage. See Errors & fail-closed.

Recommended flow

Deduct first

Call deduct with a stable idempotency_key before doing the billable work.

Gate on allowed

If allowed is false, stop and surface a top-up prompt (use required to show the shortfall).

Run the feature

Only proceed when allowed is true.