Skip to main content

credits

Use talonic.credits.getBalance() to fetch the workspace's current credit balance and budget metadata. Pair this with the cost block on extract responses for budget-aware behaviour: read the balance before scheduling a batch, log per-call cost as you go.

The balance response includes burn_rate_30d_credits and projected_runway_days so you can build alerts before credits run out. A projected_runway_days value of -1 means zero consumption in the trailing window, so no projection is possible.

Credits are workspace-scoped and shared across all API keys. The tier field reflects your current plan (free, pro, enterprise) and tier_resets_at indicates when the monthly allocation refreshes. This call is read-only and does not consume credits.

Check workspace balance
// Get the enriched workspace balance
const balance = await talonic.credits.getBalance()

console.log(balance.balance_credits)        // 1888
console.log(balance.balance_eur)            // 9.44
console.log(balance.burn_rate_30d_credits)  // 360
console.log(balance.projected_runway_days)  // 157 (-1 means no consumption)
console.log(balance.tier)                   // 'pro'
console.log(balance.tier_resets_at)         // '2026-06-01T00:00:00.000Z'

The getBalance() method returns an EnhancedBalance object wrapped with WithRateLimit metadata. The balance_credits field is the raw credit count, while balance_eur converts credits to EUR using the workspace's configured rate (rounded to two decimals). The burn_rate_30d_credits is the total credits consumed in the trailing 30 days, and projected_runway_days extrapolates how many days remain at that burn rate. The API computes these values fresh on every call, so results are always current.

Budget-aware batch processing
// Check budget before starting a batch job
const balance = await talonic.credits.getBalance()
const estimatedCost = documentIds.length * 12 // ~12 credits per extraction

if (balance.balance_credits < estimatedCost) {
  console.warn(`Insufficient credits: ${balance.balance_credits} available, ~${estimatedCost} needed`)
  console.warn(`Tier resets at ${balance.tier_resets_at}`)
  process.exit(1)
}

// Run the batch and track spend
const job = await talonic.jobs.create({ schema_id, document_ids: documentIds })
console.log(`Batch started. Pre-batch balance: ${balance.balance_credits} credits`)

// After batch completes, check remaining balance
const postBatch = await talonic.credits.getBalance()
const spent = balance.balance_credits - postBatch.balance_credits
console.log(`Batch complete. Spent ${spent} credits, ${postBatch.balance_credits} remaining`)
Track per-call costs on extract responses
// Every extract response includes cost metadata
const result = await talonic.extract({
  file_path: './invoice.pdf',
  schema_id: 'sch_abc123',
})

if (result.cost) {
  console.log(`Cost: ${result.cost.costCredits} credits (${result.cost.costEur} EUR)`)
  console.log(`Balance after: ${result.cost.balanceCredits} credits`)
  console.log(`Registry cells: ${result.cost.cellsResolvedRegistry} (cheap path)`)
  console.log(`AI cells: ${result.cost.cellsResolvedAi} (priced path)`)
}

// cost is null on non-extract endpoints (documents.list, schemas.get, etc.)
const docs = await talonic.documents.list()
console.log(docs.cost) // null

The cost block on extract responses provides granular consumption data. The cellsResolvedRegistry count represents fields resolved from the materialized field registry (the cheap path), while cellsResolvedAi counts fields resolved by AI extraction (the priced path). Understanding this split helps optimize schemas: fields that frequently resolve from the registry cost less, so reusing consistent field names across schemas reduces your per-extraction spend over time.

Low-balance alerting
// Set up a runway alert
const balance = await talonic.credits.getBalance()

if (balance.projected_runway_days >= 0 && balance.projected_runway_days < 7) {
  console.warn(
    `WARNING: Only ${balance.projected_runway_days} days of runway remaining ` +
    `at current burn rate (${balance.burn_rate_30d_credits} credits/30d)`
  )
}

if (balance.projected_runway_days === -1) {
  console.log('No consumption in the trailing 30 days — runway cannot be projected')
}

Frequently asked questions

How do I check my Talonic credit balance from the Node SDK?+
Call talonic.credits.getBalance(). It returns balance_credits, balance_eur, burn_rate_30d_credits, projected_runway_days, tier, and tier_resets_at. Read-only and safe to call at any time without consuming credits.
What is the cost field on extract responses?+
Every extract response carries a cost block parsed from the X-Talonic-Cost-* and X-Talonic-Balance-* response headers. Fields: costCredits, costEur, balanceCredits, cellsResolvedRegistry, cellsResolvedAi. Null on calls that did not run through extract (e.g. documents.list, schemas.get).
What does projected_runway_days = -1 mean?+
It means the workspace has had zero credit consumption in the trailing 30 days, so a meaningful runway projection cannot be computed. Treat -1 as 'unknown' rather than '0 days'.
What is the difference between cellsResolvedRegistry and cellsResolvedAi?+
cellsResolvedRegistry counts fields resolved from the materialized field registry, which is the cheap path. cellsResolvedAi counts fields resolved by AI extraction, which is the priced path. Reusing consistent field names across schemas increases registry hits and reduces per-extraction cost over time.
Are credits shared across all API keys in a workspace?+
Yes. Credits are workspace-scoped and shared across all API keys. The balance returned by getBalance() reflects the total workspace balance, not a per-key allocation. The tier and tier_resets_at fields indicate when the monthly credit allocation refreshes.