---
title: "Read the workspace credit balance"
method: GET
path: "/credits/balance"
tags: ["Credits"]
---

# Read the workspace credit balance

`GET /credits/balance`

## Request

- Base URL: `https://inkseal.net/api/v1`
- URL: `https://inkseal.net/api/v1/credits/balance`
- Auth: HTTP bearer

The credit balance of the workspace this credential is bound to.

A send spends one credit for the envelope, one for every signer who is not the sender, and one more when the envelope requires a one-time code; `GET /envelopes/{envelopeId}` quotes the total as `creditCost`. Check this balance before calling `POST /envelopes/{envelopeId}/send`: a send the balance cannot cover is refused, and the envelope stays in `draft`.

`policy` says whether that refusal can happen at all. A `metered` workspace is the normal case. An `unmetered` workspace is exempt from the charge: its balance never moves, and a send is never refused for credits, so an integration can skip the pre-flight check entirely.

Credits belong to the workspace, not to a member, so this never reports the balance of the user who issued the credential, and nothing in the request can point it at another workspace. Credits are bought at a Stripe checkout a human completes; `createCreditCheckout` opens one and returns the URL to hand them, and this number moves when they pay.

## Response `200`

The workspace's current balance.

- object
  - `data` CreditBalance, required: The workspace's credit balance.
    - `balance` integer, required: Credits available to spend. A send costs one credit for the envelope plus one per signer who is not the sender. On an `unmetered` workspace this number does not move and does not gate sending.
    - `policy` 'metered' | 'unmetered', required: How the workspace pays for sends. `metered` spends the envelope's credits and refuses a send the balance cannot cover. `unmetered` records zero-cost usage instead; the balance never moves and `insufficient_credits` is never returned. The account owner sets the policy out of band; no API call changes it.

## Other responses

- `401`: The credential is missing, malformed, unknown, expired, revoked, or past its rotation grace window. Code: `unauthorized`. Every authentication failure is deliberately indistinguishable.
- `403`: The credential is valid but may not do this. Codes: `insufficient_scope` (the route's scopes are not all held; `details` names `requiredScopes` and `missingScopes`), `forbidden` (the capability check on the resolved resource failed), `scope_escalation` (a grant wider than the caller's own was requested).
- `429`: A limit was reached. Codes: `rate_limited` (the credential's per-bucket HTTP limit, or the per-workspace detection throttle), `workspace_limit_exceeded` (a workspace content or send limit; `details.limit` names it), `daily_budget_exceeded` (the workspace's daily detection budget). The four rate-limit headers are sent on this response and on no successful one, so a client cannot read its remaining budget without being refused. Retrying after `Retry-After` is always safe: a rate-limit refusal happens before the handler runs.
- `503`: A dependency the request needs is unreachable and nothing was changed. Codes: `queue_unavailable` (a background job could not be enqueued; retry the call), `billing_unavailable` (Stripe would not open a checkout session; nothing was charged, retry the call), `service_unavailable` (the rate-limit store is down, so the request was refused before running).

---

[API](https://skmtc.dev/inkseal/apis/inkseal-api.md) · [All operations](https://skmtc.dev/inkseal/apis/inkseal-api/llms.txt) · [OpenAPI document](https://skmtc.dev/inkseal/apis/inkseal-api/revisions/c440c981d578?raw)
