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

# Workflows API

> Start, follow, and approve workflow runs over HTTP with an API key

You can create goals, start runs, follow them, and answer approvals over the
CostGraph API. This lets a script or pipeline start a workflow and approve its
changes without opening the app.

For every endpoint and schema, see the
[API reference](/api-reference/costgraph/introduction).

## Authenticate

Send an API key in the `X-API-Key` header, and your tenant ID in
`X-CostGraph-Tenant-ID`. Create a key under **Settings > API keys**.

An API key carries the role of the person who created it. A key created by
any member of the tenant can start runs and answer approvals.

All calls use the base URL `https://api.costgraph.ai` and the path prefix
`/api/v1/tenant/automation`.

```bash theme={null}
export CG=https://api.costgraph.ai/api/v1/tenant/automation
export H_KEY="X-API-Key: $COSTGRAPH_API_KEY"
export H_TENANT="X-CostGraph-Tenant-ID: $TENANT_ID"
```

## Create a goal

`POST /goals` creates a goal. A goal that runs once starts its first run
right away. Send a new UUID in `Idempotency-Key`. Repeating a request with the
same key doesn't create a second goal.

The `specification` holds the same settings as the goal form. Set
`allowedCategories` to include `integrations` for changes in
[connected services](/costgraph/workflows/what-workflows-can-change#connected-services),
and `approval.mode` to `every_change`, `low_risk_reversible`, or `any_change`.

```bash theme={null}
curl -X POST "$CG/goals" -H "$H_KEY" -H "$H_TENANT" \
  -H "Idempotency-Key: $(uuidgen)" -H "Content-Type: application/json" \
  -d '{
    "name": "Clean up idle droplets",
    "objective": "Find idle DigitalOcean droplets and delete the ones CostGraph created.",
    "specification": {
      "allowedConnectionIds": ["<connection id>"],
      "allowedCategories": ["integrations"],
      "exclusions": [],
      "schedule": {"kind": "once"},
      "limits": {"maxActiveRuntimeSeconds": 1800, "maxDecisions": 20},
      "approval": {"mode": "every_change"}
    }
  }'
```

The response includes the goal and, for a goal that runs once, the `run_id`.
`GET /connections` lists connection IDs, and `GET /capability-categories`
lists the categories a goal can allow.

## Run a goal

`POST /goals/{goal_id}/runs` starts a new run from the goal's current settings.
It also needs an `Idempotency-Key`.

```bash theme={null}
curl -X POST "$CG/goals/$GOAL_ID/runs" -H "$H_KEY" -H "$H_TENANT" \
  -H "Idempotency-Key: $(uuidgen)"
```

## Follow a run

`GET /runs/{run_id}` returns the run's state, its plan, the changes it made,
and any approval or question waiting for you.

```bash theme={null}
curl "$CG/runs/$RUN_ID" -H "$H_KEY" -H "$H_TENANT"
```

`GET /events/v2` is an event stream of run updates for the tenant. Send
`Last-Event-ID` to continue after the last event you processed.

```bash theme={null}
curl -N "$CG/events/v2" -H "$H_KEY" -H "$H_TENANT"
```

## Answer an approval

When a run needs you, `GET /runs/{run_id}` lists the pending approval with its
ID, version, and `effect_hash`. Answer it with
`POST /runs/{run_id}/checkpoints/{checkpoint_id}/responses`. The `outcome` is
`approved`, `rejected`, or `answered` for a question. Send the version and
`effect_hash` from the approval you reviewed. If the approval no longer matches, the
call is refused and nothing is applied.

```bash theme={null}
curl -X POST "$CG/runs/$RUN_ID/checkpoints/$CHECKPOINT_ID/responses" \
  -H "$H_KEY" -H "$H_TENANT" -H "Content-Type: application/json" \
  -d '{"checkpoint_version": 1, "effect_hash": "<effect hash>", "outcome": "approved", "payload": {}}'
```

For a question, put the answer in `payload`. For a rejection, put your reason
in `payload` so the agent can read it.

## Pause, resume, retry, and cancel

| Action | Call |
| - | - |
| Pause a goal's schedule | `POST /goals/{goal_id}/pause` |
| Resume a goal's schedule | `POST /goals/{goal_id}/resume` |
| Retry a run | `POST /runs/{run_id}/retry`, with an `Idempotency-Key` |
| Cancel a run | `POST /runs/{run_id}/cancel` |

```bash theme={null}
curl -X POST "$CG/runs/$RUN_ID/cancel" -H "$H_KEY" -H "$H_TENANT"
```

## Next steps

<CardGroup cols={2}>
  <Card title="Approvals" icon="circle-check" href="/costgraph/workflows/approvals">
    What an approval shows and when a change waits.
  </Card>

  <Card title="API reference" icon="code" href="/api-reference/costgraph/introduction">
    Authentication, errors, and every endpoint.
  </Card>
</CardGroup>


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