PINTI Docs

API Reference

Complete REST API reference for PINTI.

Base URL

https://pinti.ai/api/v1

Authentication

All endpoints require an API key via the x-api-key header.

x-api-key: pinti_xxxxxxxx_...

Note

All monetary amounts use minor units (cents for USD, kuruş for TRY). For example, $50.00 = amountMinor: 5000.

Error Format

Error response
{
  "error": "Human-readable error message"
}

Rate Limits

PlanEvaluations/dayPoliciesAPI Keys
Free10011
Pro ($29/mo)UnlimitedUnlimitedUnlimited

POST /spend/evaluate

Evaluate a spend intent against workspace policies. Returns a SAT (Spend Authorization Token) on ALLOW.

Request Body

Request
{
  "agentId": "my-agent",         // required — who is spending
  "amountMinor": 5000,           // required — amount in minor units (cents)
  "unit": "USD",                 // required — currency
  "merchant": "openai.com",      // required — where
  "category": "api",             // required — what type
  "reason": "Monthly credits",   // required — why
  "metadata": {},                // optional — extra context
  "idempotencyKey": "abc123",    // optional — deduplication
  "handleId": "clxyz...",        // optional — payment handle (falls back to workspace default)
  "callbackUrl": "https://..."   // optional — webhook URL for approval notifications
}

Response

200 OK
{
  "decision": "ALLOW",
  "decisionReason": "OK",
  "spendRequestId": "cm4abc123...",
  "sat": "eyJ2ZXJzaW9uIjox..."    // present on ALLOW
}

Decision Values

DecisionReason Examples
ALLOWOK
DENYBLOCKED_MERCHANT, EXCEEDS_SINGLE_LIMIT, EXCEEDS_DAILY_LIMIT, EXCEEDS_MONTHLY_LIMIT, NO_ACTIVE_POLICY, BLOCKED_CATEGORY, MERCHANT_NOT_ALLOWED, CATEGORY_NOT_ALLOWED, VELOCITY_LIMIT_MINUTE, VELOCITY_LIMIT_HOUR
REQUIRE_APPROVALREQUIRES_APPROVAL

POST /spend/receipt

Submit a payment receipt (SDK Guard mode). Compares actual payment values against SAT claims and flags anomalies. Idempotent — same SAT returns the same receiptId.

Request Body

Request
{
  "spendRequestId": "cm...",
  "sat": "eyJ...",
  "railId": "stripe",                    // required — "stripe", "moonpay", "evm", "custom:xxx"
  "providerTransactionId": "ch_xxx",     // optional — provider reference
  "destination": null,                   // optional — address / account
  "actualNetwork": "stripe",            // optional — "eth:1", "solana:mainnet", etc.
  "actualAmountMinor": 5000,             // required — actual amount paid (minor units)
  "actualCurrency": "usd",              // required — actual currency
  "actualMerchantNormalized": "aws",    // optional — for merchant mismatch detection
  "rawReceipt": { ... }                 // optional — sanitized provider response
}

Response

200 OK
{
  "receiptId": "cl...",
  "anomalyFlags": [],       // or ["AMOUNT_MISMATCH", "CURRENCY_MISMATCH"]
  "recorded": true
}

Note

Only SATs with executionMode: "sdk" can be used with this endpoint. External executor and managed mode SATs must use /payment/execute.

POST /payment/execute

Execute a payment through a payment handle (External Executor or Managed mode). Requires a valid SAT. Not available for SDK Guard mode.

Request Body

Request
{
  "paymentHandleId": "clxyz...",
  "sat": "eyJ...",
  "params": {
    "amountMinor": 5000,
    "currency": "usd",
    "description": "Monthly API credits"
  }
}

Response

200 OK
{
  "executed": true,
  "spendRequestId": "cm...",
  "transaction": {
    "id": "tx_xxxxxxxxxx",
    "status": "completed"
  }
}

GET /policies

List all policies for the workspace.

Response
[
  {
    "id": "cm...",
    "name": "Default Policy",
    "maxSingleAmount": 10000,
    "dailyLimit": 50000,
    "monthlyLimit": null,
    "requireApprovalOver": 5000,
    "maxTransactionsPerMinute": null,
    "maxTransactionsPerHour": null,
    "unit": "USD",
    "allowedMerchants": [],
    "blockedMerchants": ["evil.com"],
    "allowedCategories": [],
    "blockedCategories": [],
    "isActive": true,
  }
]

POST /policies

Create a new policy.

Request
{
  "name": "API Spend Policy",
  "maxSingleAmount": 10000,
  "dailyLimit": 50000,
  "monthlyLimit": 500000,
  "requireApprovalOver": 5000,
  "maxTransactionsPerMinute": 10,
  "maxTransactionsPerHour": 100,
  "unit": "USD",
  "allowedMerchants": [],
  "blockedMerchants": ["evil.com"],
  "allowedCategories": [],
  "blockedCategories": []
}

Note

All amount fields are in minor currency units (e.g. 10000 = $100.00 in cents).

GET /api-keys

List all API keys for the workspace (prefix only, never the full key).

POST /api-keys

Generate a new API key. The full plaintext key is returned only once in the response.

Response
{
  "id": "cm...",
  "keyPrefix": "pinti_ABcd1234",
  "plaintext": "pinti_ABcd1234_...",
  "createdAt": "2026-01-01T00:00:00.000Z"
}

Warning

Store the plaintext key securely. It cannot be retrieved again after creation. If lost, revoke the key and generate a new one.

GET /spend-requests/:id

Get the status of a spend request. Includes approval details if the decision was REQUIRE_APPROVAL.

Response
{
  "id": "cm...",
  "decision": "REQUIRE_APPROVAL",
  "decisionReason": "REQUIRES_APPROVAL",
  "approval": {
    "id": "cm...",
    "status": "PENDING",
    "decidedAt": null,
    "note": null
  }
}

POST /approvals/:id/resolve

Approve or reject a pending approval.

Request
{
  "status": "APPROVED",
  "note": "Looks good, proceed."
}

Status values: APPROVED or REJECTED.