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

# API

> Trigger Macroscope's agent programmatically via webhooks

<Note>To use the API,  you must configure Status. To configure Status, click on Status in the left sidebar, then complete the Product Overview and Sprint Cadence. Once your backfill has finished, you'll be able to use the API.</Note>
Macroscope exposes an inbound webhook that triggers the agent. It's the same agent you use in Slack and GitHub, but invoked via HTTP so you can call it from CI pipelines, scripts, cron jobs, or any other system.

When the agent finishes, you can get the results two ways:

* **Push** — Macroscope delivers them to a destination you specify (a Slack channel or an external URL).
* **Pull** — omit the destination and poll for the result using the token returned by the trigger.

## Setup

1. Go to **Settings → Connections → Webhooks**
2. Click **Add Webhook** and give it a name (e.g. `ci-pipeline`)
3. Copy your **API key**. It's shown once and can't be retrieved later.
4. Copy your **Trigger URL**. You can access it anytime in Settings → Connections → Webhooks.

Your **Trigger URL** will follow this format:

```
POST https://hooks.macroscope.com/api/v1/workspaces/{workspaceType}/{workspaceId}/query-agent-webhook-trigger
```

## URL Allowlisting

<a id="allowed-external-urls" />

If you want Macroscope to deliver results to an external URL (rather than Slack), that URL must be allowlisted first. For example, if you're routing results to a Zapier or n8n webhook endpoint, add that URL here. Manage the list in **Settings → Connections → Webhooks → Allowed External URLs**. Only GitHub organization admins can add or remove URLs. Must be HTTPS.

## Request

Every request needs two headers:

```bash theme={null}
-H "Content-Type: application/json"
-H "X-Webhook-Secret: your-api-key"
```

POST a JSON body to your trigger URL:

<ParamField body="query" type="string" required>
  The question to ask the agent.
</ParamField>

<ParamField body="responseDestination" type="object">
  Where to deliver the results. Use `slackChannelId` (string) to post to Slack, or `webhookUrl` (string) to POST to an external URL (must be [allowlisted](#allowed-external-urls)). Optionally include `slackThreadTs` (string) to reply in a specific Slack thread.

  **Optional.** Omit it to retrieve the result by [polling](#polling-for-results) instead.
</ParamField>

<ParamField body="timezone" type="string">
  IANA timezone (e.g. `America/Los_Angeles`). Affects date references in the query.
</ParamField>

The request returns `202 Accepted` with a job token and poll URL:

```json theme={null}
{
  "jobToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "pollUrl": "https://hooks.macroscope.com/api/v1/workspaces/{workspaceType}/{workspaceId}/query-agent-jobs",
  "workflowId": "abc-123-def-456"
}
```

* **`jobToken`** — a signed token (valid \~1 hour) authorizing you to read this one job's result. Send it as an `Authorization: Bearer` header when polling.
* **`pollUrl`** — where to poll for the result. The token is **not** in the URL.
* **`workflowId`** — *deprecated*.

## Example Requests

**Deliver results to Slack:**

```bash theme={null}
curl -X POST \
  "https://hooks.macroscope.com/api/v1/workspaces/{workspaceType}/{workspaceId}/query-agent-webhook-trigger" \
  -H "Content-Type: application/json" \
  -H "X-Webhook-Secret: your-api-key" \
  -d '{
    "query": "What were the main changes this week?",
    "responseDestination": { "slackChannelId": "C0123456789" },
    "timezone": "America/Los_Angeles"
  }'
```

**Deliver results to a Slack thread:**

```bash theme={null}
curl -X POST \
  "https://hooks.macroscope.com/api/v1/workspaces/{workspaceType}/{workspaceId}/query-agent-webhook-trigger" \
  -H "Content-Type: application/json" \
  -H "X-Webhook-Secret: your-api-key" \
  -d '{
    "query": "Investigate this alert and respond in thread",
    "responseDestination": {
      "slackChannelId": "C0123456789",
      "slackThreadTs": "1234567890.123456"
    },
    "timezone": "America/Los_Angeles"
  }'
```

**Deliver results to an external URL:**

```bash theme={null}
curl -X POST \
  "https://hooks.macroscope.com/api/v1/workspaces/{workspaceType}/{workspaceId}/query-agent-webhook-trigger" \
  -H "Content-Type: application/json" \
  -H "X-Webhook-Secret: your-api-key" \
  -d '{
    "query": "What were the main changes this week?",
    "responseDestination": { "webhookUrl": "https://your-endpoint.com/callback" },
    "timezone": "America/Los_Angeles"
  }'
```

## Polling for results

<a id="polling-for-results" />

If you didn't set a `responseDestination`, poll the `pollUrl` from the trigger response. Send the `jobToken` as a bearer token:

```bash theme={null}
curl -i "$POLL_URL" -H "Authorization: Bearer $JOB_TOKEN"
```

| Status        | HTTP  | Body                                           |
| ------------- | ----- | ---------------------------------------------- |
| Still running | `202` | `{ "status": "running" }`                      |
| Finished      | `200` | `{ "status": "completed", "response": "..." }` |
| Failed        | `200` | `{ "status": "failed" }`                       |

While running, the response carries a `Retry-After` header (seconds) suggesting how long to wait before polling again. The job token is valid for about **one hour** — if it expires before the job finishes you'll get `403`; re-trigger to get a fresh one.

### Example: trigger and poll

```bash theme={null}
# 1. Trigger without a destination
RESP=$(curl -s -X POST \
  "https://hooks.macroscope.com/api/v1/workspaces/{workspaceType}/{workspaceId}/query-agent-webhook-trigger" \
  -H "Content-Type: application/json" \
  -H "X-Webhook-Secret: your-api-key" \
  -d '{ "query": "What were the main changes this week?" }')

JOB_TOKEN=$(echo "$RESP" | jq -r .jobToken)
POLL_URL=$(echo "$RESP" | jq -r .pollUrl)

# 2. Poll until done
while :; do
  OUT=$(curl -s "$POLL_URL" -H "Authorization: Bearer $JOB_TOKEN")
  [ "$(echo "$OUT" | jq -r .status)" != "running" ] && break
  sleep 10
done
echo "$OUT" | jq -r .response
```

## Response Payload

When the agent finishes, Macroscope POSTs this to your Slack channel or URL:

```json theme={null}
{
  "query": "What were the main changes this week?",
  "response": "Here are the main changes...",
  "workflowId": "abc-123-def-456"
}
```

## Error Codes

| Code  | Meaning                                          |
| ----- | ------------------------------------------------ |
| `202` | Query accepted.                                  |
| `400` | Malformed request or missing `query`.            |
| `401` | Missing or invalid `X-Webhook-Secret`.           |
| `403` | Wrong workspace, or webhook URL not allowlisted. |

When polling:

| Code  | Meaning                                                |
| ----- | ------------------------------------------------------ |
| `200` | Job finished (`completed` or `failed`).                |
| `202` | Still running; retry after the `Retry-After` interval. |
| `401` | Missing or invalid job token.                          |
| `403` | Job token expired, or doesn't match this workspace.    |
| `404` | Job not found.                                         |

## Use Cases

* **Post-deploy summaries**: GitHub Actions runs a deploy, triggers a webhook asking "what changed in this release?", and Macroscope posts a plain-English summary to your team's Slack channel.
* **Incident response**: wire a PagerDuty or Sentry alert to trigger a Macroscope webhook. The agent can investigate the error, open a PR with a proposed fix, assign the most relevant teammate as a reviewer, and post a summary to your on-call Slack channel.
* **No-code automations**: a Zapier or n8n workflow triggers Macroscope every Monday morning to generate a weekly engineering digest and routes the answer to email, Notion, or wherever your team tracks updates.
* **Synchronous Q\&A / chatbots**: trigger a query from your own app with no destination, poll until complete, and show the answer inline — for building a custom "ask Macroscope" experience.
