REST calculation API
The REST calculation API runs your calculators from your own servers. You send inputs as JSON and get results, tables and a disclaimer back.
Before you start
You need:
- A secret API key. Create one in the portal under API keys. A secret key starts with
sk_. - The API host. The Go live page in the portal shows it.
- At least one calculator group on your cobrand. Calling a calculator outside your groups gives a
403.
Use secret keys on your servers only. Never put a secret key in browser code, a mobile app or source control. Browsers use the embed endpoints with a public key instead. The API sends no CORS headers, so a browser can't call it.
Minimal example
Set the host and key, then ask for a calculation:
export AZTEC_API_HOST="<your API host>"
export AZTEC_SECRET_KEY="<your secret key>"
curl -sS -X POST "https://$AZTEC_API_HOST/v1/calculators/auto-loan-payment/calculate" \
-H "Authorization: Bearer $AZTEC_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{"inputs":{"vehiclePrice":30000,"downPayment":3000,"tradeInValue":0,"salesTaxRate":6,"apr":7,"termMonths":60},"locale":"en-US"}'
The response looks like this:
{
"calculatorKey": "auto-loan-payment",
"engineVersion": "1",
"calculatedAt": "2026-01-15T12:00:00+00:00",
"results": { "monthlyPayment": 566.02, "totalInterest": 8274.3 },
"tables": [
{
"key": "schedule",
"label": "Amortization schedule",
"columns": [
{ "key": "month", "label": "Month", "type": "integer" },
{ "key": "balance", "label": "Balance", "type": "currency" }
],
"rows": [{ "month": 1, "balance": 27650.19 }]
}
],
"disclaimer": "Educational use only, not financial advice.",
"inputsUsed": { "vehiclePrice": 30000, "downPayment": 3000, "tradeInValue": 0, "salesTaxRate": 6, "apr": 7, "termMonths": 60 }
}
Show the disclaimer text with every result you display.
Operations
All operations are under /v1/calculators and need the header Authorization: Bearer <secret key>.
| Operation | Request | Returns |
|---|---|---|
| List calculators | GET /v1/calculators | An array of the calculators your cobrand can use: key, name, group and category |
| Get calculator schema | GET /v1/calculators/{calculatorKey}/schema | The inputs and results of one calculator |
| Calculate | POST /v1/calculators/{calculatorKey}/calculate | The results, tables and disclaimer |
Use the schema operation to find each input's key, type, range, allowed values and default. Inputs you leave out take their default, and inputsUsed shows the values the engine used.
Options
The calculate request body is a JSON object with these properties:
| Property | Required | Description |
|---|---|---|
inputs | Yes | An object of input values by input key. The engine ignores properties that aren't inputs of the calculator. |
locale | No | en-US, es-US, en-CA or fr-CA. The default is your cobrand's default locale. Any other value is a validation_failed error. |
The response always carries your engine version in the engineVersion field and in the Aztec-Engine-Version header. See Engine versions.
Errors and limits
Errors use the application/problem+json format. Each error has type, title, status, detail, instance, a stable code and a traceId. Branch on code, not on detail. Validation errors also carry an errors array.
| Status | code | Meaning |
|---|---|---|
| 400 | malformed_json | The body isn't a JSON object. |
| 400 or 422 | validation_failed | One or more inputs are invalid. Business calculators answer 400. All other calculators answer 422. |
| 401 | unauthorized | The key is missing, revoked or not a secret key. The response has WWW-Authenticate: Bearer. |
| 403 | calculator_not_entitled | Your cobrand doesn't have this calculator's group. |
| 404 | calculator_not_found | No active calculator has this key. |
| 413 | payload_too_large | The body is over 64 KB. |
| 429 | rate_limited | You went over your request limit. Wait the number of seconds in Retry-After. |
| 500 | engine_fault | The calculation failed. Quote the traceId to support. |
| 503 | catalog_unavailable | The calculator catalog can't be read right now. |
| 503 | cobrand_resolution_unavailable | The service can't verify the key right now. |
| 503 | engine_version_unavailable | The engine version your cobrand uses isn't loaded. |
| 503 | engine_timeout | The calculation took more than 10 seconds. |
| 503 | engine_overloaded | The engine is busy. |
Retry a 503 after a short wait. Don't retry a 4xx other than 429 without changing the request.
Each item in the errors array of a validation error has field, code and a message in English. Some items also have min and max. The field code is one of required, invalid_type, below_min, above_max, invalid_step, invalid_option, unsupported_locale, invalid, too_many_items, out_of_range, not_whole_number, nothing_to_finance, price_not_above_variable_cost, target_margin_too_high, payment_below_interest or payoff_too_long.
| Limit | Value |
|---|---|
| Request body | 64 KB |
| Calculation time | 10 seconds |
| Request rate | 600 requests a minute for each cobrand, shared with the MCP endpoint. See Rate limits. |
| Caching | Every response has Cache-Control: no-store. |