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

# API Overview

> The Invoke HTTP API: the effects endpoints the SDK is built on, the decisions they return, and the standalone state and reconcile checks.

Most teams use the [SDK](/sdk/typescript), which wraps this API. Use the API directly from a language without an SDK, or to see exactly what goes over the wire.

## Basics

* **Base URL:** `https://api.invokehq.run`
* **Auth:** send your key in the `X-API-Key` header. See [Authentication](/configuration/authentication).
* **Bodies:** JSON in, JSON out.

## Running actions

These are the endpoints `invoke.call()` and friends use. `{ws}` is your workspace id.

| Endpoint | What it does |
| - | - |
| `POST /v1/workspaces/{ws}/effects` | Run an action. This is what `invoke.call()` sends. |
| `POST /v1/workspaces/{ws}/effects/preview` | Would this action run right now? Runs nothing. |
| `GET /v1/workspaces/{ws}/effects/{id}` | One action and its ledger events |
| `GET /v1/workspaces/{ws}/effects/{id}/receipt` | Its receipt |
| `GET /v1/workspaces/{ws}/effects/{id}/run` | The run, stage by stage |
| `POST /v1/workspaces/{ws}/effects/{id}/resolve` | Settle an unknown outcome: `{"outcome": "happened" \| "not_happened"}`. Needs an account key. |

A tool call looks like this:

```bash theme={null}
curl -X POST https://api.invokehq.run/v1/workspaces/$WORKSPACE_ID/effects \
  -H "X-API-Key: $INVOKE_API_KEY" -H "Content-Type: application/json" \
  -d '{
    "action_type": "mcp.tool_call",
    "tool": "stripe.charge_customer",
    "target": "stripe.charge_customer",
    "params": { "customer_id": "cus_123", "amount": 2400, "invoice_id": "inv_881" },
    "idempotency_key": "invoice:inv_881"
  }'
```

With an agent key, the key names the acting agent. With an account key, add `"agent_id"`.

## Decisions

Every response carries a `decision`, and the HTTP status follows it:

| `decision` | Status | Did it happen? |
| - | - | - |
| `committed` | `200` | Yes. The response includes the `receipt`. |
| `duplicate_blocked` | `409` | Yes, earlier. The original `receipt` is returned and nothing ran again. |
| `pending_approval` | `202` | Not yet. It's waiting for a human. |
| `in_progress` | `409` | It's running now. Poll the effect. |
| `denied_permission`, `denied_policy`, `denied_identity` | `403` | No |
| `denied_budget` | `402` | No |
| `denied_claim`, `idempotency_conflict` | `409` | No |
| `denied_reservation`, `denied_paused` | `423` | No |
| `failed` | `502` | No. The tool failed and nothing changed. |
| `unknown_effect` | `504`, or `409` for a repeat | Maybe. See `safe_to_retry` and `resolve`. |

Retrying a request that got no answer is safe as long as you send the same `idempotency_key`: it's the same action.

## Standalone checks

* [`POST /state/verify`](/api/state-verify): does the world still match what the agent assumed?
* [`POST /outcomes/reconcile`](/api/outcomes-reconcile): given live state, is a retry safe?


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