The Ledgerage REST API
One deterministic engine for ASC 842, IFRS 16 and GASB 87 — the present value, the right-of-use asset and lease liability, the full amortization schedule, the journal entries and the disclosures. Single-key auth, structured errors, idempotency and quota headers. Every response cites the standard behind it.
Base URL
All endpoints live under a single base URL. Paths are versioned under /v1, so the full URL for the compute endpoint is https://ledgerage.com/api/v1/compute.
https://ledgerage.com/api
Every request is POST with a JSON body and returns a JSON response.
Authentication
Authenticate every request with an API key. Send it either as a Bearer token in the Authorization header (recommended) or in the x-api-key header. Create and manage keys from your account settings.
Keys come in two modes, distinguished by their prefix: sk_test_… and sk_live_…. Test keys are safe by default — use them in development and CI; use a live key in production. Only a hash of each key is ever stored, so a key is shown to you exactly once at creation. Treat keys as secrets: never embed them in client-side code, and rotate any key you suspect is exposed.
# Bearer token (recommended)
curl https://ledgerage.com/api/v1/compute \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{ "commencementDate": "2026-01-01", "termMonths": 60, "paymentAmount": 5000, "discountRateAnnual": 0.07 }'
# …or the x-api-key header
curl https://ledgerage.com/api/v1/compute \
-H "x-api-key: sk_live_..." \
-H "Content-Type: application/json" \
-d '{ "commencementDate": "2026-01-01", "termMonths": 60, "paymentAmount": 5000, "discountRateAnnual": 0.07 }'A missing key returns unauthorized; an unknown or revoked key returns invalid_key — both with HTTP 401.
Endpoints
There are four endpoints. All share the same request body (a lease) and differ only in what they return. /v1/classify is free (0 units); the other three cost one computation unit each against your monthly quota.
Request body
The body describes one lease. Only four fields are truly required; the rest have sensible defaults or refine the computation and classification.
| Field | Type | Description | |
|---|---|---|---|
| standard | "ASC_842" | "IFRS_16" | "GASB_87" | optional | Reporting standard. Defaults to ASC_842. |
| commencementDate | string (yyyy-mm-dd) | required | Lease commencement date. |
| termMonths | integer (1–1200) | required | Total lease term in months. |
| paymentAmount | number (> 0) | required | Recurring payment per period, before any escalation. |
| discountRateAnnual | number (0–1) | required | Annual discount rate as a decimal — e.g. 0.07 for 7%. |
| paymentFrequency | "monthly" | "quarterly" | "semiannual" | "annual" | optional | Defaults to monthly. |
| paymentTiming | "advance" | "arrears" | optional | advance = start of period (typical for real estate). Defaults to advance. |
| classification | "operating" | "finance" | optional | Override the derived classification. Otherwise the engine derives it. |
| annualEscalationPct | number (0–1) | optional | Compounding annual rent escalation, e.g. 0.03 for 3%/yr. |
| initialDirectCosts | number (≥ 0) | optional | Added to the ROU asset. |
| leaseIncentives | number (≥ 0) | optional | Received at or before commencement — reduces the ROU asset. |
| prepaidRent | number (≥ 0) | optional | Paid before commencement — added to the ROU asset. |
| residualValueGuarantee | number (≥ 0) | optional | Probable amount owed — included in lease payments. |
| purchaseOptionAmount | number (≥ 0) | optional | Purchase-option exercise price, if included in payments. |
| transfersOwnership | boolean | optional | Classification input: title transfers by end of term. |
| purchaseOptionReasonablyCertain | boolean | optional | Classification input: option reasonably certain to be exercised. |
| assetFairValue | number (≥ 0) | optional | Classification input: fair value of the underlying asset. |
| assetEconomicLifeMonths | integer (> 0) | optional | Classification input: remaining economic life of the asset, in months. |
| specializedAsset | boolean | optional | Classification input: no alternative use to the lessor. |
{
"standard": "ASC_842",
"commencementDate": "2026-01-01",
"termMonths": 60,
"paymentAmount": 5000,
"paymentFrequency": "monthly",
"paymentTiming": "advance",
"discountRateAnnual": 0.07
}/api/v1/computeCompute a full lease
The complete computation: normalized input, the measured result (initial liability, ROU asset, full schedule, disclosures, citations), the operating-vs-finance classification with all five criteria, and the journal entries.
curl https://ledgerage.com/api/v1/compute \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"standard": "ASC_842",
"commencementDate": "2026-01-01",
"termMonths": 60,
"paymentAmount": 5000,
"paymentFrequency": "monthly",
"paymentTiming": "advance",
"discountRateAnnual": 0.07
}'{
"input": { /* the lease you sent, normalized */ },
"result": {
"standard": "ASC_842",
"classification": "operating",
"commencementDate": "2026-01-01",
"termMonths": 60,
"periods": 60,
"periodicRate": 0.0058333,
"initialLiability": 253982.94,
"initialRouAsset": 253982.94,
"totalUndiscountedPayments": 300000,
"totalLeaseCost": 300000,
"schedule": [
{
"period": 1,
"date": "2026-01-01",
"payment": 5000,
"interest": 1452.4,
"principal": 3547.6,
"liabilityClose": 250435.34,
"rouAmortization": 3547.6,
"rouAssetClose": 250435.34,
"leaseExpense": 5000
}
/* … 60 periods, liability reconciled to exactly 0.00 */
],
"disclosures": {
"weightedAverageRemainingTermMonths": 60,
"weightedAverageDiscountRate": 0.07,
"totalUndiscountedPayments": 300000,
"imputedInterest": 46017.06,
"maturityAnalysis": [
{ "year": 1, "label": "Year 1", "undiscountedPayments": 60000 }
/* … Year 2 … Year 5, then "Thereafter" for longer terms */
],
"currentLiability": 43963.93,
"longTermLiability": 210019.01,
"totalLeaseCost": 300000
},
"citations": [
"ASC 842-20-30-1 — initial measurement of the lease liability at the present value of lease payments.",
"ASC 842-20-30-5 — the right-of-use asset comprises the initial liability, prepaid lease payments and initial direct costs, less lease incentives received."
/* … full citation list */
],
"notes": [
"Discount rate applied as a nominal monthly rate: 7.000% ÷ periods-per-year.",
"Payments treated as made in advance (annuity-due): each period's payment is applied before interest accretes."
]
},
"classification": {
"classification": "operating",
"standard": "ASC_842",
"single_model": false,
"criteria": [
{
"key": "transfer_of_ownership",
"label": "Transfer of ownership",
"met": false,
"detail": "No transfer of ownership at the end of the term.",
"citation": "ASC 842-10-25-2(a)"
}
/* … five criteria in total */
],
"rationale": "Classified as an OPERATING lease under ASC 842 because none of the five finance-lease criteria are met. The lessee still recognises a right-of-use asset and lease liability, but total lease cost is expensed on a straight-line basis."
},
"journalEntries": [
{
"date": "2026-01-01",
"memo": "Initial recognition of lease (ROU asset and lease liability)",
"lines": [
{ "account": "Right-of-use asset", "debit": 253982.94, "credit": 0 },
{ "account": "Lease liability", "debit": 0, "credit": 253982.94 }
]
}
/* … one balanced entry per period */
],
"request_id": "req_1a2b3c4d5e6f7a8b9c0d1e2f",
"replay": false
}/api/v1/scheduleAmortization schedule
Just the period-by-period schedule — interest, principal, lease-liability balance, ROU amortization and ROU asset balance — reconciled to exactly zero.
{
"standard": "ASC_842",
"classification": "operating",
"initialLiability": 253982.94,
"initialRouAsset": 253982.94,
"periods": 60,
"schedule": [
{
"period": 1,
"date": "2026-01-01",
"payment": 5000,
"interest": 1452.4,
"principal": 3547.6,
"liabilityClose": 250435.34,
"rouAmortization": 3547.6,
"rouAssetClose": 250435.34,
"leaseExpense": 5000
}
/* … one row per period */
],
"request_id": "req_…",
"replay": false
}/api/v1/journal-entriesJournal entries
Double-entry journal entries: the commencement entry plus one balanced entry per period (interest + amortization for finance leases, straight-line lease cost for operating leases).
{
"standard": "ASC_842",
"classification": "operating",
"journalEntries": [
{
"date": "2026-01-01",
"memo": "Initial recognition of lease (ROU asset and lease liability)",
"lines": [
{ "account": "Right-of-use asset", "debit": 253982.94, "credit": 0 },
{ "account": "Lease liability", "debit": 0, "credit": 253982.94 }
]
},
{
"date": "2026-01-01",
"memo": "Period 1 — operating lease",
"lines": [
{ "account": "Lease expense", "debit": 5000, "credit": 0 },
{ "account": "Cash", "debit": 0, "credit": 5000 },
{ "account": "Lease liability", "debit": 3547.6, "credit": 0 },
{ "account": "Right-of-use asset", "debit": 0, "credit": 3547.6 }
]
}
/* … one balanced entry per period. A finance lease instead posts separate
interest expense and straight-line amortization entries. */
],
"request_id": "req_…",
"replay": false
}/api/v1/classifyClassify a lease
Evaluate the five ASC 842 finance-lease criteria and return operating vs finance with the reasoning and citation for each. IFRS 16 / GASB 87 return the single lessee model. Billed at 0 units so an agent can classify before committing.
{
"classification": "operating",
"standard": "ASC_842",
"single_model": false,
"criteria": [
{
"key": "transfer_of_ownership",
"label": "Transfer of ownership",
"met": false,
"detail": "The lease does not transfer ownership by the end of the term.",
"citation": "ASC 842-10-25-2(a)"
},
{
"key": "purchase_option",
"label": "Reasonably certain purchase option",
"met": false,
"detail": "No purchase option the lessee is reasonably certain to exercise.",
"citation": "ASC 842-10-25-2(b)"
}
/* … five criteria: economic life, fair value, specialized asset */
],
"rationale": "No finance-lease criterion is met, so the lease is operating.",
"request_id": "req_…",
"replay": false
}Errors
Errors are structured and machine-parseable. Every error returns a JSON body with a stable code, a human-readable message, a link to these docs, and the request_id (also returned in the x-request-id response header) so you can correlate it in your logs.
{
"error": {
"code": "quota_exceeded",
"message": "Monthly computation quota reached (25). Upgrade to Pro for more.",
"docs": "https://ledgerage.com/docs/api#errors",
"request_id": "req_1a2b3c4d5e6f7a8b9c0d1e2f"
}
}| code | HTTP | Meaning |
|---|---|---|
| unauthorized | 401 | No API key was supplied. Send it as a Bearer token or x-api-key. |
| invalid_key | 401 | The API key is unknown or has been revoked. |
| invalid_request | 400 / 405 | The body was not valid JSON, failed validation, or the method was not POST. The message names the offending field. |
| quota_exceeded | 429 | The monthly computation quota for the plan has been used up. Includes x-quota-remaining: 0. |
| rate_limited | 429 | Too many requests in the last minute. Honour the retry-after header. |
| plan_required | 402 / 403 | The endpoint or feature requires a plan the key does not have. |
| not_found | 404 | The referenced resource does not exist. |
| internal_error | 500 | An unexpected server error. Safe to retry with an Idempotency-Key. |
Quota headers
Successful and quota-related responses carry your metering state so you never have to guess how much headroom is left:
| Field | Type | Description | |
|---|---|---|---|
| x-quota-limit | integer | optional | Your plan's monthly computation quota. |
| x-quota-remaining | integer | optional | Computations left in the current UTC-month window. The window rolls over on the 1st. |
| x-request-id | string | optional | The unique id for this request, echoed in the body as request_id. |
Only billed endpoints consume quota. /v1/classify is free and never decrements it.
Idempotency
Send an Idempotency-Key header to make a request safe to retry. Because the engine is deterministic, a repeated key returns the same result without charging you again — the response carries the header idempotent-replay: true and the body field replay: true, and the call is billed 0 units.
curl https://ledgerage.com/api/v1/compute \
-H "Authorization: Bearer sk_live_..." \
-H "Idempotency-Key: lease-4152-jan" \
-H "Content-Type: application/json" \
-d '{
"standard": "ASC_842",
"commencementDate": "2026-01-01",
"termMonths": 60,
"paymentAmount": 5000,
"paymentFrequency": "monthly",
"paymentTiming": "advance",
"discountRateAnnual": 0.07
}'
# A repeat of the same key returns the same result, billed 0 units:
# idempotent-replay: true
# "replay": trueUse a stable, unique key per logical computation (for example a lease id plus period).
Rate limits & quota by plan
Each key is subject to a per-minute rate limit and a monthly computation quota, both set by your plan. Exceeding the per-minute limit returns rate_limited (HTTP 429) with a retry-after header; exhausting the monthly quota returns quota_exceeded.
| Plan | Rate limit | Monthly computations |
|---|---|---|
| Free | 10 requests / minute | 25 / month |
| Pro | 120 requests / minute | 5,000 / month |
Built for agents
Ledgerage is designed to be called by AI accounting and close agents, not just humans. The API is deterministic, cites its sources, and fails with structured errors — so an agent never has to hallucinate a right-of-use asset.
MCP server
Prefer tools over raw HTTP? The MCP server wraps these four endpoints as compute_lease, lease_schedule, journal_entries and classify_lease.
llms.txt
A machine-readable manifest of what Ledgerage does and how to call it, for agents that discover tools automatically.
View /llms.txt →Questions? Email hello@ledgerage.com.