Aira

Billing

Plans, pricing, Stripe checkout, subscription management, and overage billing.

Billing endpoints are only available in cloud mode. Self-hosted deployments manage billing externally. All endpoints require admin role.

Base URL: https://api.airaproof.com/api/v1

Plans & Pricing

PlanMonthlyIncluded OpsSeatsCase OverageOther Op OverageSupport
Free€01003Hard wall (429)Hard wall (429)
Pro€29910,000Unlimited€0.03/case€0.05/opEmail
Business€699100,000Unlimited€0.015/case€0.03/opPriority, 99.5% SLA
EnterpriseCustomUnlimitedUnlimitedCustomCustomDedicated, 99.9% SLA, self-hosted

All features are available on all plans. Self-hosted deployments have no limits.

What counts as an operation?

An operation is any billable event on your monthly counter. Every billable event is 1 op; cases use the case rate, everything else uses the op rate.

EventFired byBillable
case_runPOST /api/v1/cases1 op (case rate)
action_authorizePOST /api/v1/actions — at policy decision1 op
chatPOST /api/v1/chat1 op per message
compliance_bundlePOST /api/v1/compliance/bundles1 op per bundle
settlementPOST /api/v1/settlements (admin)1 op per sealed batch
drift_checkPOST /api/v1/agents/{id}/drift/check1 op per check

Agent actions bill at authorize, not notarize. The expensive compute — policy engine evaluation, any LLM calls in AI/consensus mode, content scan, and the multi-party signature on the PolicyEvaluation row — all happens inside POST /api/v1/actions. The follow-up POST /api/v1/actions/{id}/notarize is a free bookkeeping call that just mints the Ed25519 receipt for the outcome your agent reports.

This means denied-by-policy and held-for-approval actions also bill: the policy decision is the artifact you're paying for, regardless of what the agent was ultimately allowed to do.

You can't notarize without authorizing first. The action_uuid in the notarize URL is a server-assigned identifier that only exists after POST /api/v1/actions creates the action row. If you pass an unknown id you get 404 NOT_FOUND; denied or pending-approval actions return 409 INVALID_ACTION_STATE. Every successful notarize is backed by exactly one billable authorize in the same org, so the free-notarize rule can't be used to avoid paying for compute.

The following are not billed — they stay free on every plan:

  • Notarize: POST /api/v1/actions/{id}/notarize is free — and it only succeeds for actions that were previously authorized by your org, so the decision has always been paid for already.
  • Reads: every GET endpoint, including verification, inclusion proofs, and bundle exports.
  • Workflow metadata: approvals, denials, cosignatures, drift-alert acknowledgements, legal-hold release.
  • One-time setup: drift baseline computations (production, synthetic, pooled).
  • Retries with the same idempotency_key — they return the original resource without a second charge.

Create Checkout Session

POST /api/v1/billing/checkout
Authorization: Bearer <token>

Redirects to Stripe Checkout for plan upgrade. Only pro and business plans are available for self-service.

Request Body

FieldTypeRequiredDescription
planstringYesTarget plan: pro or business
success_urlstringYesURL to redirect after successful checkout
cancel_urlstringYesURL to redirect if checkout is cancelled

Response

{
  "checkout_url": "https://checkout.stripe.com/c/pay/cs_test_...",
  "request_id": "req_abc123"
}

Behavior

  • Free → Pro/Business: Creates a new Stripe Checkout session
  • Pro → Business: Upgrades inline (swaps subscription items, prorated)
  • Same plan: Returns error (You are already on the pro plan.)
  • Downgrade: Not supported via self-service. Use the billing portal to cancel, then resubscribe.

Create Portal Session

POST /api/v1/billing/portal
Authorization: Bearer <token>

Opens the Stripe Customer Portal for subscription management (update payment method, view invoices, cancel subscription).

Request Body

FieldTypeRequiredDescription
return_urlstringYesURL to return to after portal session

Response

{
  "portal_url": "https://billing.stripe.com/p/session/...",
  "request_id": "req_abc123"
}

Billing Status

GET /api/v1/billing/status
Authorization: Bearer <token>

Returns current subscription status.

Response

{
  "plan": "pro",
  "has_subscription": true,
  "billing_period_end": "2026-04-26T00:00:00Z",
  "cancel_at_period_end": false,
  "request_id": "req_abc123"
}
FieldTypeDescription
planstringCurrent plan: free, pro, business, enterprise
has_subscriptionbooleanWhether a Stripe subscription exists
billing_period_endstring/nullISO 8601 datetime of period end
cancel_at_period_endbooleanWhether subscription cancels at period end

Stripe Webhook

POST /api/v1/billing/stripe/webhook

No authentication — verified by Stripe signature. Handles:

EventAction
checkout.session.completedActivates plan, stores subscription ID
customer.subscription.updatedSyncs plan and billing period
customer.subscription.deletedReverts to free plan
invoice.paidLogged for audit
invoice.payment_failedLogged as warning (Stripe handles retry)

Overage Billing

When a paid plan exceeds its included operations:

  1. Each usage event (case run, action notarization) is reported to Stripe's Billing Meter
  2. Stripe aggregates usage over the billing period
  3. At the end of the period, overage is invoiced alongside the base subscription

Overage is never charged on the free plan — free users hit a hard wall (HTTP 429) at 100 operations.

Testing

Use Stripe test mode with card 4242 4242 4242 4242 (any future expiry, any CVC). Test webhook events with the Stripe CLI:

stripe listen --forward-to localhost:8001/api/v1/billing/stripe/webhook

On this page