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

# Customer State

> Read a customer's active subscriptions, benefits, and meter balances in one call — the fastest way to gate access.

Most billing integrations stitch together three or four lookups just to answer one question: *should this customer have access right now?* Customer State collapses that into a single source of truth. One read returns everything you need to make the call — active subscriptions, granted [benefits](/features/benefits/introduction), and live meter balances — so your access logic stays simple and correct.

Pair it with an [external ID](/features/customer-management#external-id) and you can map Macropay customers onto your own user records without storing a separate identifier. Sign up, point at the endpoint, ship.

## What's inside the object

A customer state object is a complete entitlement snapshot. Instead of joining subscriptions, benefits, and usage by hand, you get them pre-resolved:

| Field                | What it gives you                                                                                    |
| -------------------- | ---------------------------------------------------------------------------------------------------- |
| Customer             | All profile data, including custom fields and external ID.                                           |
| Active subscriptions | Every subscription currently in force — no expired or canceled noise.                                |
| Granted benefits     | License keys, downloads, repo access, credits, and more — only the ones the customer actually holds. |
| Active meters        | Each metered feature with its **current balance**, ready for usage gating.                           |

<Note>
  Because Macropay is the Merchant of Record, those subscriptions and benefits are billed and tax-collected under our name — you read the resolved entitlement and provision access, while we remit sales tax and VAT worldwide on your behalf.
</Note>

That single object is enough to decide whether to unlock a dashboard, release a download, or let an agent keep running.

## Read it on demand

When you need the state right now — say, on login or before serving a gated request — fetch it directly. Query by your own ID or by Macropay's:

<CardGroup cols={2}>
  <Card title="By your external ID" icon="ring" iconType="duotone" href="/api-reference/customers/state-external" horizontal>
    Use the customer ID you already store. No extra mapping table required.
  </Card>

  <Card title="By Macropay customer ID" icon="ring" iconType="duotone" href="/api-reference/customers/state" horizontal>
    The same payload, keyed by the internal Macropay customer ID.
  </Card>
</CardGroup>

A login check looks like this — swap in your stored user ID:

```bash theme={null}
curl https://api.macropay.ai/v1/customers/external/usr_8421/state \
  -H "Authorization: Bearer $MACROPAY_API_KEY"
```

The response carries the customer, their active subscriptions, granted benefits, and active meters with balances — provision access from that and you're done.

## Stay in sync

Polling works for on-demand checks, but for keeping your own database current you want to be told the moment anything changes. Subscribe to the `customer.state_changed` webhook and Macropay pushes the full, updated state object whenever:

* A customer is created, updated, or deleted.
* A subscription starts or changes.
* A benefit is granted or revoked.

Each delivery is the same shape as the on-demand read, so a single handler can serve both paths: persist the snapshot, recompute access, done.

<Card title="customer.state_changed" icon="ring" iconType="duotone" href="/api-reference/webhooks/customer.state_changed" horizontal>
  One event that mirrors the full state object on every change.
</Card>

<Tip>
  Verify deliveries with the Standard Webhooks signature and treat the payload as the source of truth — re-deriving access from each event keeps you correct even if an individual delivery is retried.
</Tip>

## Gating usage and AI agents

The active-meter balances in the state object make it a natural control point for usage-based and AI workloads. Before letting an agent run another step or a request consume a metered feature, read the customer's state and check the relevant meter balance — when prepaid credits run out, you stop. Combine that with [benefits](/features/benefits/introduction) for plan-level entitlements and you have both *what they're allowed* and *how much they have left* in one place.
