Quickstart
Agent Pay status: Approve does not execute. Execution: not enabled. ACH settlement: not enabled. prepare_payment never moves money. Machine-readable: /docs/agents/status.json.
This guide takes an agent from its first connection to a signed authorization. It ends with a payment draft that a human approved and that has not executed.
Before you start
- An MCP host that connects to remote MCP servers with OAuth. ChatGPT is the live host today; see the ChatGPT guide.
- A POINTS account for the operator, the person who signs in, sets policy, and approves. Sign up as an agent operator.
1. Discover and connect
- Point the host at
https://thepoints.io/mcp(Streamable HTTP). - A call without a token gets HTTP 401 with a
WWW-Authenticateheader whoseresource_metadatapoints to/.well-known/oauth-protected-resource. - The host reads that document, then the authorization server metadata at
/.well-known/oauth-authorization-server. - The host registers itself at the
registration_endpoint(dynamic client registration, public client), then runs the authorization code flow with PKCE (S256). - The operator signs in to POINTS, reviews the requested scopes, and grants them. This guide needs
payments:draft,payments:status, andmodule-status:read. - The host calls
tools/list. Every tool is described in the MCP tools reference.
Endpoint details are on the Discovery page.
2. Read the policy vocabulary
Call get_agent_pay_policy_vocabulary with no arguments. Keep three things from the result:
policySchemaVersion: send it with everyprepare_paymentcall. An unsupported version fails closed.categories: the exactvaluestrings to use forcategory. Aliases are rejected.velocityCapsand the allow and block lists: what the operator's policy permits on this connection.
The static part of the vocabulary is published at /docs/agents/reference/policy-vocabulary.json.
3. Prepare a payment
Call prepare_payment:
{
"amountCents": 2500,
"currency": "USD",
"merchant": "Example Compute Co",
"category": "ai_compute",
"reference": "GPU hours for job 42",
"idempotencyKey": "job-42-gpu-hours",
"policySchemaVersion": 1
}
When policy allows the payment to be proposed, the result is a draft waiting for a human:
{
"payment_id": "<draft id>",
"status": "requires_approval",
"merchant": "Example Compute Co",
"amount": 2500,
"currency": "USD",
"policy_result": "allowed_with_approval",
"estimated_fee": null,
"estimated_reward": null,
"expires_at": "<ISO 8601 time>"
}
- The draft waits up to 24 hours for a decision (
expires_at). - Retrying with the same
idempotencyKeyand the same data returns the same draft. Reusing the key with different data is refused. - When policy blocks the payment, the tool returns an error with a readable reason and no approvable draft. See Errors.
4. A human approves
The operator opens Approvals in POINTS and approves or rejects the draft. Approval needs a signed-in POINTS session. MCP access tokens cannot reach the approval routes, so an agent cannot approve its own payment.
At approval, POINTS signs an authorization envelope that binds the amount, currency, payee, idempotency key, approver, and an executableUntil time, 1 hour after approval by default. The signing key stays on the server.
5. Check the status
Call get_payment_status with the payment_id:
{ "draftId": "<draft id>" }
{
"id": "<draft id>",
"status": "approved",
"amountCents": 2500,
"currency": "USD",
"createdAt": "<ISO 8601 time>",
"expiresAt": "<ISO 8601 time>",
"executed": false,
"executionProvider": null,
"executionRail": null,
"providerStatus": null
}
statusmoves fromrequires_approvaltoapproved,rejected,expired, orrevoked. All values are in Statuses.executedis alwaysfalse.- Once
executableUntilpasses, the draft reads asexpired. See Lifecycle. get_payment_statusonly returns drafts on the connected account. It never returns another account's drafts.
The prepare result may include an optional cash_check warning for insufficient or unknown unreserved cash. The warning also appears on the approval card. Prepare warns today; the same codes become refusals at a future execution launch.
What happens next
Nothing executes. Approve does not execute, and the live state is published at /docs/agents/status.json. Read it before telling a user what an approval means.