Constaia
Concepts

Credits & billing

How credits are calculated per page, what is not charged, the free plan of 150 credits a month, packs in EUR and USD, expiry, balance, alerts and 402 errors.

Cette page n'est pas encore traduite dans votre langue. Voici la version anglaise.

Constaia is pay-as-you-go with credits. There is no subscription: you buy packs when you need them and, meanwhile, you get 150 free credits every month. Prices and comparison at /en/pricing.

What each operation costs

OperationCredits
Analysis (POST /v1/analyze) of a document of up to 2 pages1
Every 2 additional pages+1
Classification (POST /v1/classify)0.2
Exports (JSON, CSV, XLSX, XML, vCard, PDF)Included

The rule is credits = ceil(pages / 2), with a minimum of 1. A Spanish DNI with both sides in one file or in a 2-page PDF costs 1 credit.

DocumentPagesCredits
DNI, front and back in one file21
One-page medical certificate11
3-page invoice32
10-page contract105
5 classifications—1
Batch of 100 two-page documents200100

In a batch, each document is counted separately with the same rule. Every analysis shows what it cost in usage:

"usage": { "credits": 1, "pages": 2 }

What is not charged

  • Test mode. ck_test_ keys don't use credits (usage.credits: 0).
  • Failures on our side. An analysis that ends with status: "failed" (for example processing_failed) is not charged.
  • Quality rejections before OCR. If the image is rejected before it is read, it is not charged.
  • Retries with the same Idempotency-Key within 24 h: they return the stored response without charging twice.
  • Exports. Already included.

An analysis that ends as invalid or review is charged: Constaia did the work and gave you an answer.

Reservation and capture

When an analysis starts, Constaia reserves the credits it will cost. When it finishes:

  • if it completes, the reservation is captured;
  • if it fails on our side or is rejected for quality before OCR, the reservation is released and returns to your balance.

While analyses are in progress you will see credits in credits_reserved. If you don't have enough balance to reserve, the request fails with a 402 insufficient_credits and nothing is analysed.

In live mode, a batch checks when it is created that you have at least 1 credit per document; if not, the whole batch is rejected with 402. Each document then costs what its pages require.

Free plan

  • 150 credits a month, renewed on the 1st of each month (UTC). Unused credits don't roll over.
  • Spending them in live mode requires a verified email.
  • free_tier_resets_at in the balance tells you when they renew.

Packs

Packs are one-off payments, no subscription. Prices exclude VAT:

PackEUR≈ €/creditUSD≈ $/credit
1,000 credits€490.049$550.055
5,000 credits€1990.040$2190.044
25,000 credits€7900.032$8690.035
100,000 credits€2,4900.025$2,7400.027
EnterpriseCustom—Custom—
  • Packs expire 12 months after purchase.
  • Consumption order: first this month's free plan, then packs from oldest to newest (FIFO).
  • Enterprise: contract, DPA, SLA and your own limits. Details at /en/pricing.

Buy packs under Billing in app.constaia.com. Payment goes through Stripe Checkout and the credits are added to your balance as soon as it is confirmed.

VAT and invoices

  • Prices exclude VAT. Stripe Tax calculates it at checkout based on your tax details.
  • Every purchase generates an invoice, which you will find under Billing in the dashboard.
  • Fill in your company's tax details before your first purchase so they appear on the invoice.

Checking your balance

GET /v1/balance returns:

200 OK
{
  "object": "balance",
  "credits_available": 4210,
  "credits_reserved": 3,
  "free_tier_remaining": 12,
  "credits_spendable": 4222,
  "free_tier_resets_at": "2026-10-01T00:00:00.000Z"
}
FieldMeaning
credits_availablePack credits available (free plan not included, minus reservations drawn from packs).
credits_reservedCredits reserved by analyses in progress.
free_tier_remainingFree credits left this month (minus their reservations).
credits_spendableWhat you can spend right now: credits_available + free_tier_remaining.
free_tier_resets_atWhen the free plan renews.

What you can spend right now is credits_spendable (credits_available + free_tier_remaining).

curl https://api.constaia.com/v1/balance \
  -H "Authorization: Bearer $CONSTAIA_API_KEY"

Checking usage

GET /v1/usage?from=YYYY-MM-DD&to=YYYY-MM-DD aggregates usage by day and document type (by default, the last 30 days of the key's mode):

curl "https://api.constaia.com/v1/usage?from=2026-09-01&to=2026-09-30" \
  -H "Authorization: Bearer $CONSTAIA_API_KEY"
200 OK
{
  "object": "usage",
  "from": "2026-09-01",
  "to": "2026-09-30",
  "livemode": true,
  "data": [
    { "date": "2026-09-29", "type": "es_dni", "kind": "analysis", "livemode": true, "count": 42, "pages": 84, "credits": 42 }
  ],
  "totals": { "count": 42, "pages": 84, "credits": 42 }
}

To split costs between customers or departments, send metadata with each analysis (for example { "club_id": "42" }) and filter with GET /v1/analyses?metadata[club_id]=42. More in Balance & usage.

Low-credit alert

In the dashboard settings you set an alert threshold (50 credits by default). When, after a charged live analysis, your spendable balance drops below it, Constaia:

  • sends the credits.low webhook to subscribed endpoints, and
  • emails the account's owners and admins.
credits.low
{
  "type": "credits.low",
  "created_at": "2026-09-29T10:00:00Z",
  "data": { "object": "balance", "credits_available": 0, "free_tier_remaining": 48, "credits_spendable": 48, "threshold": 50 }
}

The fields mean the same as in GET /v1/balance: credits_available is pack credits only and credits_spendable is what you can spend (free plan plus packs); the alert fires when credits_spendable drops below the threshold. It is sent once until you top up with a pack or the free plan renews. Subscribe from Webhooks.

Handling 402 errors

Without enough balance, the API responds:

402 Payment Required
{
  "error": {
    "type": "insufficient_credits",
    "code": "insufficient_credits",
    "message": "…",
    "request_id": "req_…"
  }
}

Don't retry it in a loop: it won't fix itself. Queue the work, alert your team and resume when there is balance.

analyze-with-credits.ts
import { Constaia, InsufficientCreditsError } from "@constaia/sdk";
import { fromPath } from "@constaia/sdk/node";

const constaia = new Constaia();

try {
  const analysis = await constaia.analyze(await fromPath("./dni.jpg"), { expect: "es_dni" });
  console.log(analysis.verdict?.status);
} catch (err) {
  if (err instanceof InsufficientCreditsError) {
    // Keep the document for later and alert whoever buys credits.
    console.error(`Out of credits (request ${err.requestId})`);
  } else {
    throw err;
  }
}

Monthly spend cap

You can set a monthly credit cap for the account: if a live-mode analysis would exceed it, it is rejected with 402 monthly_cap_reached and not charged, and owners and admins get an email at 80 % and 100 %. Details in Rate limits.

Coming soon: managed human review

Human review of documents by the Constaia team: +€0.40 per document. Not available yet; meanwhile, build your own queue with the human review guide. Watch the changelog.

Next steps

Sur cette page