Reference

API Overview

Programmatic access to SPEND.md through a RESTful API. Create wallets, manage cards, and monitor transactions from your applications.

Base URL

https://api.spend.md/v1

Authentication

All API requests require authentication using an API key. Include the key in theAuthorization header:

Authorization: Bearer sk_live_your_api_key_here

Getting an API Key

Generate API keys from the CLI or dashboard:

$ spend api-key create --name "production"

✓ API Key created

Key:     sk_live_abc123...xyz789
Name:    production
Created: 2026-01-30
Expires: 2026-04-30

⚠️  Save this key securely. It won't be shown again.

API Key Types

PrefixEnvironmentUse Case
sk_live_ProductionReal transactions, live cards
sk_test_TestSimulated transactions, no real money
sk_dev_DevelopmentLocal development, mock responses

Request Format

All requests should include the following headers:

Content-Type: application/json
Authorization: Bearer sk_live_your_api_key
X-Idempotency-Key: unique-request-id  # Recommended for mutations

Idempotency

For POST, PUT, and DELETE requests, include an X-Idempotency-Key header with a unique ID. This ensures requests are not duplicated if retried.

Endpoints

Wallets

MethodEndpointDescription
GET/walletsList all wallets
POST/walletsCreate a new wallet
GET/wallets/:idGet wallet details
PATCH/wallets/:idUpdate wallet configuration
DELETE/wallets/:idDelete a wallet

Cards

MethodEndpointDescription
GET/wallets/:id/cardsList cards for a wallet
POST/wallets/:id/cardsCreate a virtual card
GET/cards/:idGet card details
POST/cards/:id/freezeFreeze a card
POST/cards/:id/unfreezeUnfreeze a card
DELETE/cards/:idDelete a card

Transactions

MethodEndpointDescription
GET/transactionsList transactions (with filters)
GET/transactions/:idGet transaction details
GET/wallets/:id/transactionsList transactions for a wallet

Approvals

MethodEndpointDescription
GET/approvalsList pending approvals
POST/approvals/:id/approveApprove a transaction
POST/approvals/:id/denyDeny a transaction

Example Requests

Create a Wallet

curl -X POST https://api.spend.md/v1/wallets \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "agent_name": "my-assistant",
    "owner": "team@company.com",
    "spend": {
      "monthly_limit": { "amount": 500, "currency": "USD" },
      "daily_limit": { "amount": 50, "currency": "USD" },
      "allowlist": ["openai.com", "anthropic.com"]
    }
  }'

Response

{
  "id": "wal_abc123xyz",
  "agent_name": "my-assistant",
  "owner": "team@company.com",
  "status": "active",
  "balance": {
    "amount": 0,
    "currency": "USD"
  },
  "spend": {
    "monthly_limit": { "amount": 500, "currency": "USD" },
    "daily_limit": { "amount": 50, "currency": "USD" },
    "spent_this_month": { "amount": 0, "currency": "USD" },
    "spent_today": { "amount": 0, "currency": "USD" },
    "allowlist": ["openai.com", "anthropic.com"]
  },
  "cards": [],
  "created_at": "2026-01-30T12:00:00Z",
  "updated_at": "2026-01-30T12:00:00Z"
}

Create a Card

curl -X POST https://api.spend.md/v1/wallets/wal_abc123xyz/cards \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "primary",
    "limit": { "amount": 100, "currency": "USD" }
  }'

List Transactions

curl "https://api.spend.md/v1/transactions?wallet=wal_abc123xyz&limit=10" \
  -H "Authorization: Bearer sk_live_..."

Webhooks

Receive real-time notifications about transactions, approvals, and other events via webhooks. Configure webhook URLs in your SPEND.md or via the API.

Webhook Payload

{
  "id": "evt_abc123",
  "type": "transaction.completed",
  "created": "2026-01-30T14:23:45Z",
  "data": {
    "transaction": {
      "id": "txn_xyz789",
      "wallet_id": "wal_abc123xyz",
      "card_id": "crd_def456",
      "amount": { "amount": 12.50, "currency": "USD" },
      "merchant": {
        "name": "OpenAI",
        "domain": "openai.com",
        "category": "api_services"
      },
      "status": "completed",
      "created_at": "2026-01-30T14:23:45Z"
    }
  }
}

Verifying Webhooks

All webhooks include a signature in the X-Spend-Signature header. Verify this signature to ensure the webhook is authentic:

import crypto from 'crypto';

function verifyWebhook(payload, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');
  
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(`sha256=${expected}`)
  );
}

Error Handling

The API uses standard HTTP status codes and returns errors in a consistent format:

{
  "error": {
    "code": "insufficient_funds",
    "message": "Transaction would exceed daily limit",
    "details": {
      "requested": { "amount": 75.00, "currency": "USD" },
      "available": { "amount": 25.00, "currency": "USD" },
      "limit": { "amount": 50.00, "currency": "USD" }
    }
  }
}

Status Codes

CodeDescription
200Success
201Created
400Bad request (invalid parameters)
401Unauthorized (invalid or missing API key)
403Forbidden (insufficient permissions)
404Not found
422Unprocessable (business logic error)
429Rate limited
500Internal server error

Rate Limits

API requests are rate limited based on your plan:

PlanRequests/minuteRequests/day
Free601,000
Pro30050,000
Team1,000Unlimited

Rate limit headers are included in every response: X-RateLimit-Limit,X-RateLimit-Remaining, andX-RateLimit-Reset.

SDKs & Libraries

Official SDKs are available for popular languages:

Node.js / TypeScript

npm install @spend/sdk

Python

pip install spend-sdk

Go

go get github.com/spend-md/go

Ruby

gem install spend-sdk