> ## Documentation Index
> Fetch the complete documentation index at: https://docs.meshai.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Billing API

> Query billing info, manage checkout, and handle webhooks

## Get Billing Info

```
GET /billing
```

Get the current billing status for your tenant.

```bash theme={null}
curl https://api.meshai.dev/api/v1/billing \
  -H "Authorization: Bearer msh_YOUR_API_KEY"
```

<ResponseExample>
  ```json Response theme={null}
  {
    "success": true,
    "data": {
      "plan": "professional",
      "active_agents": 47,
      "agent_limit": 100,
      "billing_period_start": "2026-03-01T00:00:00Z",
      "billing_period_end": "2026-03-31T23:59:59Z",
      "monthly_cost_usd": 799.00,
      "features": {
        "anomaly_detection": true,
        "governance_policies": "unlimited",
        "hitl_approvals": true,
        "risk_classification": true,
        "audit_trail_retention_days": 365,
        "eu_ai_act_compliance": "basic",
        "fria_support": false,
        "incident_reporting": false,
        "sso": false
      },
      "payment_method": {
        "type": "card",
        "last_four": "4242",
        "expiry": "12/2027"
      }
    }
  }
  ```
</ResponseExample>

## Switch Free-Tier Slot

```
PATCH /billing/free-slot
```

Switch which agent occupies the tenant's free-tier agent slot. Requires the `admin` scope.

This recovers a free tenant whose first-seen agent was a throwaway, or whose agent identity changed on redeploy, from being locked out of its own free tier. Full recovery when the wrong agent claimed the slot is a 3-step flow:

<Steps>
  <Step title="Remove the wrong agent">
    Soft-delete the old (wrong) agent via `DELETE /api/v1/agents/{id}`.
  </Step>

  <Step title="Register the new agent">
    Start emitting from the new agent so it exists in the registry.
  </Step>

  <Step title="Move the slot">
    Call this endpoint with the new agent's ID to move the free slot to it.
  </Step>
</Steps>

Recording then follows the new agent from the next ingest batch onward.

### Request Body

| Field      | Type   | Required | Description                                      |
| ---------- | ------ | -------- | ------------------------------------------------ |
| `agent_id` | string | Yes      | ULID of the agent that should hold the free slot |

```bash theme={null}
curl -X PATCH https://api.meshai.dev/api/v1/billing/free-slot \
  -H "Authorization: Bearer msh_YOUR_ADMIN_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "agent_id": "01JABC123DEF456GHI789JKLMN"
  }'
```

<ResponseExample>
  ```json Response theme={null}
  {
    "success": true,
    "data": {
      "free_agent_id": "01JABC123DEF456GHI789JKLMN"
    }
  }
  ```
</ResponseExample>

## Checkout (Change Plan)

```
POST /billing/checkout
```

Initiate a plan change. Returns a checkout URL for payment if upgrading, or confirms the downgrade if moving to a lower tier.

```bash theme={null}
curl -X POST https://api.meshai.dev/api/v1/billing/checkout \
  -H "Authorization: Bearer msh_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "plan": "enterprise" }'
```

<ResponseExample>
  ```json Response (upgrade) theme={null}
  {
    "success": true,
    "data": {
      "action": "upgrade",
      "from_plan": "professional",
      "to_plan": "enterprise",
      "prorated_amount_usd": 1200.00,
      "checkout_url": "https://checkout.meshai.dev/session/cs_abc123",
      "expires_at": "2026-03-17T11:00:00Z"
    }
  }
  ```
</ResponseExample>

<ResponseExample>
  ```json Response (downgrade) theme={null}
  {
    "success": true,
    "data": {
      "action": "downgrade",
      "from_plan": "professional",
      "to_plan": "starter",
      "effective_date": "2026-04-01T00:00:00Z",
      "message": "Downgrade will take effect at the start of the next billing cycle. Ensure you have 25 or fewer active agents by then."
    }
  }
  ```
</ResponseExample>

Valid plan values: `starter`, `professional`, `enterprise`. For Enterprise Plus, [contact sales](mailto:hello@meshai.dev).

## Webhook

```
POST /billing/webhook
```

Endpoint for payment provider webhooks (Stripe). This endpoint is called by the payment provider, not by your application.

### Webhook Events

| Event                    | Description                       |
| ------------------------ | --------------------------------- |
| `checkout.completed`     | Payment successful, plan upgraded |
| `invoice.paid`           | Monthly invoice paid              |
| `invoice.payment_failed` | Payment failed: retry scheduled   |
| `subscription.canceled`  | Subscription canceled             |

### Verifying Webhooks

MeshAI verifies webhook signatures automatically. If you're self-hosting, configure the webhook signing secret in your environment:

```bash theme={null}
STRIPE_WEBHOOK_SECRET=whsec_...
```

### Webhook Payload Example

```json theme={null}
{
  "event": "checkout.completed",
  "tenant_id": "tnt_abc123",
  "plan": "enterprise",
  "amount_usd": 1999.00,
  "timestamp": "2026-03-17T10:30:00Z"
}
```
