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

# Integration overview

> The contract between ZeroClick and your API: what arrives on every forwarded request, your backend's four obligations, and the three refusals it must produce.

Agents buy and pay at your pay URL (`https://acme.pay.zeroclick.io`). ZeroClick verifies the payment, signs the request, and forwards it to your API at your configured upstream base URL. This page is the whole contract between ZeroClick and your backend. The [seller SDKs](/sdks/overview) implement it; the [REST walkthrough](/integrate/rest-walkthrough) shows how to implement it without one.

## What arrives on every forwarded request

ZeroClick sets three headers on each request it forwards:

| Header          | Value                                     | Purpose                                                                                                                                  |
| --------------- | ----------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `zc-request-id` | `zcreq_8h2m4x0q9k1f`                      | Correlation id. The same id flows through the probe, the challenge, the paid retry, the allowance check, and the usage record.           |
| `zc-agent-id`   | `agt_x7f2kq93bh0d`                        | The buyer. Absent or empty on signed anonymous probes, which are valid. See [verify requests](/integrate/verify-requests).               |
| `zc-signature`  | `t=<unix seconds>,kid=hsec_…,v1=<64 hex>` | HMAC-SHA256 proof that the request came through ZeroClick unmodified. Sandbox traffic appends `,sb=1` and adds a `zc-sandbox: 1` header. |

Before forwarding, ZeroClick strips all inbound `zc-*`, `x-payment`, and `payment*` headers and sets its own, so a caller can never inject them. Other request headers pass through untouched. Your API's own authentication remains whatever you configured between yourself and ZeroClick.

One more header matters to the contract without ever reaching you: `zc-mode`. A buyer sends `zc-mode: free` to the pay URL to opt a call into included-units coverage. ZeroClick consumes it there, and a missing or unrecognized value means paid. See [free and identity endpoints](/integrate/free-and-identity-endpoints). The full header reference is at [headers](/resources/headers).

## The four obligations

On every forwarded request, your backend must:

1. **Verify** the `zc-signature` against your signing secret, before anything else. Only ZeroClick-signed traffic reaches your handlers. See [verify requests](/integrate/verify-requests).
2. **Check the allowance** with `POST /v1/usage/check`: does the buyer's plan cover what this request will use? See [check allowances](/integrate/check-allowances).
3. **Serve** the request as your API normally would.
4. **Settle** what the request used: a `zc-usage` header on the successful response, or an asynchronous usage report. See [settle usage](/integrate/settle-usage).

With an SDK, the first two obligations are one `guard` call and the fourth is one helper:

<CodeGroup>
  ```ts TypeScript theme={null}
  const decision = await zeroClick.guard(request, {
    serviceSlug: "product-watch",
    usage: [{ meterSlug: "requests", quantity: 1 }],
  });
  if (decision.action === "deny") return decision.response;

  const response = Response.json({ watching: true });
  return zeroClick.withUsage(response, [
    { serviceSlug: "product-watch", meterSlug: "requests", quantity: 1 },
  ]);
  ```

  ```python Python theme={null}
  zc_request = zc_request_from_asgi_scope(request.scope, await request.body())

  decision = await zeroclick.guard(
      zc_request,
      service_slug="product-watch",
      usage=[UsageItem(meter_slug="requests", quantity=1)],
  )
  if decision.action == "deny":
      return to_fastapi(decision.response)

  return to_fastapi(
      zeroclick.with_usage(
          ZcResponse.json({"watching": True}),
          [SyncUsageItem(service_slug="product-watch", meter_slug="requests", quantity=1)],
      )
  )
  ```

  ```go Go theme={null}
  // Meter verifies the signature, checks the allowance, refuses before the
  // handler runs, and settles the zc-usage header on a delivered 2xx.
  mux.Handle("/v1/product-watch", seller.Meter(sellers.PerRequest("requests", 1))(
  	http.HandlerFunc(productWatch)))
  ```
</CodeGroup>

## The three refusals

When your API cannot serve, it must answer ZeroClick with one of exactly three responses. The SDKs build all of them. A deny decision carries the response ready to return.

| Status | When                                                                    | Exact body                                                                                                   |
| ------ | ----------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
| `401`  | The signature is missing, malformed, stale, or invalid.                 | `{"error":"invalid_zeroclick_signature"}`                                                                    |
| `402`  | The allowance check denies, or an unpaid request needs payment.         | `{"error":"payment_required","serviceSlug":"product-watch","usage":[{"meterSlug":"requests","quantity":1}]}` |
| `503`  | The allowance API is unreachable and your outage policy is fail-closed. | `{"error":"allowance_unavailable"}`                                                                          |

The `402` body is not an error page. It is data. ZeroClick reads the usage list, prices it from your catalog, and issues the buyer a signable payment challenge. The buyer never sees your body. A `402` with `usage: []` means "free, but identity-scoped", which ZeroClick answers with a \$0 identity challenge. The [errors](/resources/errors) page lists error codes across the platform.

## What never to do

* **Never serve unverified traffic.** Your upstream URL is reachable; the signature is the gate. A request with no ZeroClick headers must get the `401`, not your handler.
* **Never bill on a non-2xx.** `zc-usage` belongs on 2xx responses only: a 4xx is the buyer's bad input and a 5xx is your failure. Neither delivered anything worth charging for.
* **Never price or cache challenges yourself.** Your `402` declares usage quantities, not prices. ZeroClick prices each refusal from your catalog per request and binds each challenge to that exact request. A cached price or replayed challenge cannot settle.

## SDK or REST

If your backend is TypeScript, Python, or Go, use the SDK. It implements the contract, including the denial bodies and the signature edge cases:

* [TypeScript quickstart](/sdks/typescript/quickstart): `@zeroclickai/sellers` on npm
* [Python quickstart](/sdks/python/quickstart): `zeroclick-sellers` on PyPI
* [Go quickstart](/sdks/go/quickstart): `cdn.zeroclick.io/sdks/sellers-go`

Otherwise the contract is small enough to implement over REST: two API calls, one signature check, three fixed response bodies. Start at the [REST walkthrough](/integrate/rest-walkthrough) and the byte-level [signature spec](/integrate/signature-spec).

## Work through the contract

<Columns cols={2}>
  <Card title="Keys and secrets" icon="key" href="/integrate/keys-and-secrets">
    The three runtime keys, scopes, split read/write keys, and rotation.
  </Card>

  <Card title="Verify requests" icon="shield-check" href="/integrate/verify-requests">
    What verification proves, anonymous probes, and the raw-path rule.
  </Card>

  <Card title="Check allowances" icon="list-checks" href="/integrate/check-allowances">
    Guard semantics, usage items, denials, and the outage policy.
  </Card>

  <Card title="Settle usage" icon="receipt" href="/integrate/settle-usage">
    The `zc-usage` header and asynchronous usage reports.
  </Card>

  <Card title="Charge up to a maximum" icon="gauge" href="/integrate/charge-up-to-a-maximum">
    Use ceilings to bill work you can't size up front.
  </Card>

  <Card title="Free and identity endpoints" icon="id-card" href="/integrate/free-and-identity-endpoints">
    Endpoints that cost nothing but must know the buyer.
  </Card>
</Columns>
