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

# Verify an action

> Create an API key and verify one action with POST /api/v1/intent.

<Steps>
  <Step title="Sign in">
    Sign in at [harness.chance.cc/login](https://harness.chance.cc/login). Check your balance before running a paid verification.
  </Step>

  <Step title="Create an API key">
    Open [harness.chance.cc/keys](https://harness.chance.cc/keys) and click **Create key**. The key starts with `chance_sk_live_` and is shown once. Keep it in a server-side secret, not in client code.
  </Step>

  <Step title="Verify an action">
    Send the user's rules as `intent` and the proposed action as `action`. Authenticate with `x-api-key: <key>` or `Authorization: Bearer <key>`.
  </Step>
</Steps>

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://harness.chance.cc/api/v1/intent \
    -H "x-api-key: $CHANCE_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "intent": "Only buy favorites priced at 95c or more. Reject longshots.",
      "action": "Buy YES on the Will-X-win market at 21c for $10."
    }'
  ```

  ```ts TypeScript theme={null}
  const res = await fetch("https://harness.chance.cc/api/v1/intent", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.CHANCE_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      intent: "Only buy favorites priced at 95c or more. Reject longshots.",
      action: "Buy YES on the Will-X-win market at 21c for $10.",
    }),
  });

  const body = await res.json();
  if (!res.ok) throw new Error(`${res.status} ${body.error}`);
  if (body.verdict !== "ALLOW") {
    // Do not execute. body.reasoning says why.
  }
  ```

  ```python Python theme={null}
  import os, requests

  r = requests.post(
      "https://harness.chance.cc/api/v1/intent",
      headers={"x-api-key": os.environ["CHANCE_API_KEY"]},
      json={
          "intent": "Only buy favorites priced at 95c or more. Reject longshots.",
          "action": "Buy YES on the Will-X-win market at 21c for $10.",
      },
  )
  r.raise_for_status()
  print(r.json()["verdict"])  # expected: BLOCK
  ```
</CodeGroup>

## The response

A completed verification returns `201`:

```json theme={null}
{
  "id": "3f6c2a0e-7b1d-4c5e-9a2f-1d4b8e6c0a91",
  "requestHash": "0x…",
  "status": "COMPLETED",
  "verdict": "BLOCK",
  "reasoning": "The action buys a 21c contract, below the 95c floor the intent sets.",
  "mode": "semantic",
  "venue": null,
  "actionFamily": null,
  "actionType": null,
  "proof": {
    "transcriptRoot": "0x…",
    "outputHash": "0x…",
    "signature": "0x…",
    "judge": "0x…",
    "attested": true,
    "anchorTx": "0x…",
    "anchorVerified": false,
    "transcriptUri": "https://harness.chance.cc/api/runs/…/transcript",
    "explorerTx": "https://…/tx/0x…"
  },
  "creditsRemaining": 49
}
```

| Field | Meaning |
| - | - |
| `id` | The verification id. Pass it to `GET /api/v1/intent/{id}`. |
| `requestHash` | An identifier for this run. `GET /api/v1/intent/{id}` also accepts it. |
| `verdict` | `ALLOW`, `BLOCK`, `ESCALATE`, or `null` when the judge produced no decision. |
| `reasoning` | The judge's explanation. |
| `mode` | `structured` when `action` is an object a venue adapter recognized, otherwise `semantic`. |
| `venue`, `actionFamily`, `actionType` | What the venue adapter classified. `null` for a plain-text action with no `venue`. |
| `proof` | The receipt. `anchorTx` and `explorerTx` are `null` when the run was not anchored. See [Receipts](/concepts/proofs). |
| `creditsRemaining` | Your balance after this call. |

Execute the action only when `verdict` is `"ALLOW"`. Treat every other value, including `null` and any non-`201` response, as do not execute.

## Errors

| Status | Body | What to do |
| - | - | - |
| `400` | `{"error": "invalid JSON body"}`, `{"error": "intent is required"}` or `{"error": "action is required"}` | Fix the request. No credit is charged. |
| `401` | `{"error": "missing API key (send x-api-key)"}` or `{"error": "invalid or revoked API key"}` | Send a valid key. |
| `402` | `{"error": "out_of_credits", "message": "…", "topup": {…}}` | Add credits. `topup` is present when top-ups are enabled. See [Credits](/concepts/credits). |
| `502` | `{"error": "verification_failed", "message": "…"}` | The run failed and the credit was refunded. Retry. |

## Next steps

* Send the exact payload the venue will receive as `action` (a JSON object) and set `venue`. The judge then sees exactly what will be submitted, and the receipt records it. See [Venues](/venues/overview).
* Fetch a past result with `GET /api/v1/intent/{id}`. Its response has a different shape: no `mode`, `venue`, `actionFamily`, `actionType` or `creditsRemaining`, a `proof` with `anchorStatus` (`verified`, `pending` or `skipped`) in place of `anchorVerified`, `transcriptUri` and `explorerTx`, and a `createdAt`. See [Verification request](/api-reference/verification-request).
* Give an agent the same check as an MCP tool. See [Connectors](/connectors).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.