---
title: Errors, statuses & go-live | API Docs
description: Agentcard payment and connection states, Linq's error model, and the checklist to ship to production.
---

## Payment statuses

| Status                 | Terminal? | Meaning                                         |
| ---------------------- | --------- | ----------------------------------------------- |
| `needs_connection`     | no        | The handle isn’t connected yet.                 |
| `connecting`           | no        | Connection in progress.                         |
| `awaiting_user_action` | no        | Waiting on the customer (e.g. approval).        |
| `ready`                | no        | Card available — retrieve the handoff and pay.  |
| `authorized`           | no        | Merchant placed a hold on the card.             |
| `succeeded`            | yes       | Charge settled.                                 |
| `declined`             | yes       | Charge declined; create a new payment to retry. |
| `canceled`             | yes       | You canceled the payment.                       |
| `expired`              | yes       | The payment lapsed before completing.           |

## Connection statuses

`not_connected` · `pending` · `connected` · `revoked`

## Error model

Every error returns the same envelope:

```
{
  "success": false,
  "error": {
    "status": 400,
    "code": 1002,
    "message": "Phone number must be in E.164 format",
    "doc_url": "https://docs.linqapp.com/error/codes/1xxx/1002/"
  },
  "trace_id": "3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f"
}
```

Every error carries a `doc_url` pointing at the page for that code — follow it rather than guessing from the message. On `429`, `error` also includes `retry_after` (seconds to wait before retrying).

### Codes you’ll hit with Agentcard

| Code                                      | HTTP | Meaning                 | Fix                                            |
| ----------------------------------------- | ---- | ----------------------- | ---------------------------------------------- |
| [`1001`](/error/codes/1xxx/1001/index.md) | 400  | Missing required field  | Include `handle`, `amount_cents`, `currency`.  |
| [`1002`](/error/codes/1xxx/1002/index.md) | 400  | Phone not E.164         | Format the handle as `+14155550123`.           |
| [`1003`](/error/codes/1xxx/1003/index.md) | 400  | Invalid request body    | Check JSON + `Content-Type: application/json`. |
| [`1005`](/error/codes/1xxx/1005/index.md) | 400  | Invalid parameter value | e.g. bad currency or negative amount.          |
| [`1007`](/error/codes/1xxx/1007/index.md) | 429  | Rate limit exceeded     | Back off using `retry_after`.                  |
| [`2004`](/error/codes/2xxx/2004/index.md) | 401  | Unauthorized            | Send a valid `Authorization: Bearer` token.    |
| [`2005`](/error/codes/2xxx/2005/index.md) | 403  | Access denied           | Token lacks access to this resource/org.       |

An unknown `paymentId` or handle returns `404` with the same envelope — read the `code` and `doc_url` from the response rather than assuming a fixed code. The full list is at [Error Codes](/error/index.md).

## Error-handling principles

- **Re-fetch on every webhook** — never trust the status in the event body.
- **Dedupe** payments on `Idempotency-Key` and webhooks on `webhook-id`.
- **Never log or store** the fetched card number (PAN/CVC).
- Treat `declined` / `canceled` / `expired` as terminal — create a fresh payment to retry.

## Go-live checklist

- [ ] Agentcard connected for the **production** org in the [Linq dashboard](https://zero.linqapp.com/organization/payments).
- [ ] Production API token stored server-side only (never shipped to the client/agent).
- [ ] Webhook subscription created; `signing_secret` stored securely.
- [ ] Webhook **signatures verified** (Standard Webhooks: HMAC-SHA256, 5-min replay window).
- [ ] Webhook handler returns `2xx` fast and is **idempotent** (dedupe on `webhook-id`).
- [ ] `Idempotency-Key` sent on every payment create.
- [ ] Amounts sent as `amount_cents` (minor units) everywhere.
- [ ] Card handoff redeemed just-in-time; PAN/CVC never logged or stored.
- [ ] `succeeded` confirmed by polling `GET /payments/{id}` (no succeeded webhook).
- [ ] `connection.revoked` handled (stop paying a revoked handle).
- [ ] Full loop rehearsed end to end against a handle you control.

## Next

- [Webhooks & lifecycle](/guides/agentcard/webhooks/index.md)
- [Create & complete a payment](/guides/agentcard/create-a-payment/index.md)
