Credits & Billing
The Credits and Billing endpoints let you check your credit balance, view transaction history, estimate costs, and manage Stripe-powered billing. Credits are the currency for running optimizations on JAOT.
GET /api/v2/credits/balance
Get the current credit balance for your organization.
Authentication: Requires API key or JWT token.
Response
| Field | Type | Description |
|---|---|---|
credits_balance | integer | Total credits available (purchased + earned) |
credits_earned | integer | Credits earned from marketplace model sales (withdrawable) |
currency | string | Organization's preferred currency |
local_balance | number | Balance converted to preferred currency |
local_earned | number | Earned credits converted to preferred currency |
exchange_rate | number | Current exchange rate to preferred currency |
credits_per_eur | integer | Credits per euro (currently 10) |
Examples
import httpx
API_URL = "https://api.jaot.io/api/v2"
headers = {"Authorization": "Bearer ok_live_your_key_here"}
response = httpx.get(f"{API_URL}/credits/balance", headers=headers)
balance = response.json()
print(f"Credits: {balance['credits_balance']}")
print(f"Earned: {balance['credits_earned']}")
print(f"Local balance: {balance['local_balance']} {balance['currency']}")Response
{
"credits_balance": 950,
"credits_earned": 200,
"currency": "EUR",
"local_balance": 95.0,
"local_earned": 20.0,
"exchange_rate": 1.0,
"credits_per_eur": 10
}GET /api/v2/credits/transactions
Get credit transaction history for your organization.
Authentication: Requires API key or JWT token.
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
transaction_type | string | -- | Filter by type: purchase, execution, sale_earning, withdrawal, refund, adjustment |
limit | integer | 50 | Max results (1-100) |
offset | integer | 0 | Number of results to skip |
Response
Returns an array of transaction objects.
| Field | Type | Description |
|---|---|---|
id | string | Transaction ID (e.g. "txn_a1b2c3d4") |
transaction_type | string | Type of transaction |
credits_amount | integer | Credits change (negative = deduction, positive = addition) |
balance_after | integer | Credit balance after this transaction |
description | string | Human-readable description |
reference_type | string | Related entity type (e.g. "solve", "topup") |
reference_id | string | Related entity ID |
amount_eur | number | Euro equivalent amount |
created_at | string | ISO 8601 timestamp |
Examples
import httpx
response = httpx.get(
"https://api.jaot.io/api/v2/credits/transactions",
params={"limit": 10},
headers={"Authorization": "Bearer ok_live_your_key_here"},
)
transactions = response.json()
for tx in transactions:
print(f"{tx['created_at']}: {tx['credits_amount']:+d} credits - {tx['description']}")Response
[
{
"id": "txn_a1b2c3d4",
"transaction_type": "execution",
"credits_amount": -3,
"balance_after": 947,
"description": "Solver execution",
"reference_type": "solve",
"reference_id": "exe_9a1b2c3d",
"amount_eur": 0.048,
"created_at": "2026-02-19T10:05:12Z"
}
]POST /api/v2/credits/calculator
Estimate credits for an optimization problem. This endpoint is public and does not require authentication.
Info: The credit calculator is public -- no authentication required. Use it to estimate costs before signing up or committing credits.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
num_variables | integer | Yes | Total number of decision variables (0-100,000) |
num_integer_vars | integer | No | Number of integer variables (default: 0) |
num_binary_vars | integer | No | Number of binary variables (default: 0) |
num_constraints | integer | No | Number of constraints (0-100,000, default: 0) |
time_limit_seconds | number | No | Time limit in seconds (1-3600, default: 60) |
Response
| Field | Type | Description |
|---|---|---|
credits_required | integer | Estimated credits needed |
breakdown | object | Cost breakdown by component |
breakdown.base_cost | number | Base cost (always 1) |
breakdown.variable_cost | number | Cost from number of variables |
breakdown.integer_penalty | number | Additional cost for integer variables |
breakdown.binary_penalty | number | Additional cost for binary variables |
breakdown.constraint_cost | number | Cost from number of constraints |
breakdown.time_limit_bonus | number | Extra cost for time limits above 60s |
cost_eur | number | Estimated cost in EUR |
cost_by_plan | object | Cost in EUR for each plan tier |
Examples
import httpx
API_URL = "https://api.jaot.io/api/v2"
response = httpx.post(f"{API_URL}/credits/calculator", json={
"num_variables": 100,
"num_integer_vars": 50,
"num_binary_vars": 20,
"num_constraints": 80,
"time_limit_seconds": 60,
})
estimate = response.json()
print(f"Estimated credits: {estimate['credits_required']}")
print(f"Breakdown: {estimate['breakdown']}")
print(f"Cost (Pro plan): EUR {estimate['cost_by_plan']['pro']}")Response
{
"credits_required": 33,
"breakdown": {
"base_cost": 1,
"variable_cost": 10.0,
"integer_penalty": 15.0,
"binary_penalty": 4.0,
"constraint_cost": 4.0,
"time_limit_bonus": 0
},
"cost_eur": 0.528,
"cost_by_plan": {
"free": 0,
"starter": 0.627,
"pro": 0.528,
"topup_500": 0.924,
"topup_2000": 0.792,
"topup_5000": 0.66,
"topup_20000": 0.528
}
}For the full credit formula and pricing details, see Rate Limits & Credits.
POST /api/v2/billing/checkout/subscription
Create a Stripe Checkout session for a subscription plan.
Authentication: Requires API key or JWT token.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
plan | string | Yes | Plan name: "starter", "pro", or "business" |
success_url | string | No | Redirect URL after successful payment |
cancel_url | string | No | Redirect URL if user cancels |
Response
| Field | Type | Description |
|---|---|---|
checkout_url | string | Stripe Checkout URL -- redirect the user here |
session_id | string | Stripe session ID |
Examples
import httpx
response = httpx.post(
"https://api.jaot.io/api/v2/billing/checkout/subscription",
headers={"Authorization": "Bearer ok_live_your_key_here"},
json={"plan": "pro"},
)
checkout = response.json()
print(f"Redirect to: {checkout['checkout_url']}")Response
{
"checkout_url": "https://checkout.stripe.com/c/pay/cs_live_...",
"session_id": "cs_live_..."
}POST /api/v2/billing/checkout/topup
Create a Stripe Checkout session for a credit top-up purchase.
Authentication: Requires API key or JWT token.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
credits | integer | Yes | Credit package: 500, 2000, 5000, or 20000 |
success_url | string | No | Redirect URL after payment |
cancel_url | string | No | Redirect URL if cancelled |
Available packages:
| Credits | Price | Per Credit |
|---|---|---|
| 500 | EUR 14 | EUR 0.028 |
| 2,000 | EUR 48 | EUR 0.024 |
| 5,000 | EUR 100 | EUR 0.020 |
| 20,000 | EUR 320 | EUR 0.016 |
Examples
import httpx
response = httpx.post(
"https://api.jaot.io/api/v2/billing/checkout/topup",
headers={"Authorization": "Bearer ok_live_your_key_here"},
json={"credits": 2000},
)
checkout = response.json()
print(f"Top-up checkout: {checkout['checkout_url']}")GET /api/v2/billing/status
Get the current billing and subscription status for your organization.
Authentication: Requires API key or JWT token.
Response
| Field | Type | Description |
|---|---|---|
stripe_configured | boolean | Whether Stripe is configured on the server |
has_subscription | boolean | Whether the org has an active subscription |
subscription | object | Subscription details (null if none) |
subscription.id | string | Stripe subscription ID |
subscription.status | string | Subscription status |
subscription.plan | string | Plan name |
subscription.current_period_start | string | Current billing period start |
subscription.current_period_end | string | Current billing period end |
Examples
import httpx
response = httpx.get(
"https://api.jaot.io/api/v2/billing/status",
headers={"Authorization": "Bearer ok_live_your_key_here"},
)
status = response.json()
if status["has_subscription"]:
print(f"Plan: {status['subscription']['plan']}")POST /api/v2/billing/portal
Create a Stripe Billing Portal session for self-service subscription management, payment methods, and invoice history.
Authentication: Requires API key or JWT token.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
return_url | string | No | URL to redirect back to after portal session |
Response
| Field | Type | Description |
|---|---|---|
portal_url | string | Stripe Billing Portal URL |
Examples
import httpx
response = httpx.post(
"https://api.jaot.io/api/v2/billing/portal",
headers={
"Authorization": "Bearer ok_live_your_key_here",
"Content-Type": "application/json",
},
json={"return_url": "https://app.jaot.io/workspace/credits"},
)
portal = response.json()
print(f"Portal URL: {portal['portal_url']}")Response
{
"portal_url": "https://billing.stripe.com/p/session/..."
}POST /api/v2/billing/webhook
Stripe webhook endpoint. This endpoint is public -- it does not require API key authentication. Instead, Stripe signs each request using the webhook secret.
Handles events: checkout.session.completed, invoice.paid, customer.subscription.updated, customer.subscription.deleted.
Configure the webhook URL in your Stripe Dashboard: https://your-domain.com/api/v2/billing/webhook
GET /api/v2/billing/invoices
List invoices for your organization.
Authentication: Requires API key or JWT token.
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
limit | integer | 50 | Max results (1-100) |
offset | integer | 0 | Number of results to skip |
Examples
import httpx
response = httpx.get(
"https://api.jaot.io/api/v2/billing/invoices",
headers={"Authorization": "Bearer ok_live_your_key_here"},
)
invoices = response.json()
for inv in invoices["items"]:
print(f"{inv['invoice_number']}: EUR {inv['total_eur']} ({inv['status']})")Response
{
"items": [
{
"id": "inv_a1b2c3d4e5f67890",
"invoice_number": "INV-2026-00001",
"invoice_type": "topup",
"status": "paid",
"issued_at": "2026-02-19T15:00:00",
"paid_at": "2026-02-19T15:00:00",
"org_name": "Acme Corp",
"subtotal_eur": 48.0,
"tax_rate": 0.0,
"tax_amount_eur": 0.0,
"total_eur": 48.0,
"currency": "EUR",
"total_local": 48.0,
"credits_granted": 2000,
"line_items": [
{
"description": "Credit Top-Up: 2,000 credits",
"quantity": 2000,
"unit_price_eur": 0.024,
"total_eur": 48.0,
"credits": 2000
}
],
"notes": "Credit top-up: 2,000 credits"
}
],
"total": 1
}Errors
| HTTP Code | Error | Description |
|---|---|---|
| 401 | unauthorized | Missing or invalid API key |
| 503 | service_unavailable | Stripe is not configured on the server |