API
Quote, 202 scan, SSE, milliscale.
Hunt API on Detective, Chief, and Director.
Get started
1Mint
Session cookie. Plaintext mago_sk_ once. Customer keys cannot call /api/keys.
Request
curl -sS https://mago.team/api/keys/generate \
-H "Cookie: mago-token=…" \
-H "Content-Type: application/json" \
-d '{"name":"desk"}'2Quote
Milliscale estimate. No debit. estimated_credits is what the scan reserves.
curl -sS https://mago.team/api/v1/quote \
-H "X-API-Key: mago_sk_…" \
-H "Content-Type: application/json" \
-d '{"target":"example.com"}'{
"product": "search",
"estimated_credits": 208,
"charged_credits": 208,
"module_credits": 208,
"token_credits": 0,
"offer_id": "domain",
"spells": ["dns_deep", "subdomain_enum", "whois_osint"]
}3Scan
authorization_confirmed must be true. Live keys hunt. mago_sk_test_ is client-dev: sandbox-example, no hunt.
curl -sS https://mago.team/api/v1/scans \
-H "X-API-Key: mago_sk_…" \
-H "Content-Type: application/json" \
-d '{"target":"example.com","authorization_confirmed": true,"passive_only":true,"ai":false}'{
"order_id": "ord_01EXAMPLE",
"credits_reserved": 208,
"status": "queued"
}{
"order_id": "sandbox-example",
"credits_reserved": 208,
"status": "sandbox"
}4Stream
SSE until done, failed, or cancelled. Then GET the report.
curl -N https://mago.team/api/billing/order/{order_id}/stream \
-H "X-API-Key: mago_sk_…"curl -sS https://mago.team/api/v1/reports/{order_id} \
-H "X-API-Key: mago_sk_…"curl -sS https://mago.team/api/v1/reports/sandbox-example \
-H "X-API-Key: mago_sk_test_…"
Authentication
Hunt calls take X-API-Key or Authorization: Bearer mago_sk_. Mint stays on the session cookie. HTTPS only.
Header
| Header | Use |
|---|
| X-API-Key | mago_sk_… |
| Authorization | Bearer mago_sk_ |
| Cookie | mago-token (mint only) |
Prefix
| Prefix | Use |
|---|
| mago_sk_ | Live hunt. Minted. Debits milliscale. |
| mago_sk_test_ | Integrator client-dev fixture. Public prefix. No owner, no wallet, no hunt. |
Reference
Public hunt surface. Examples are milliscale for example.com with AI off. Quote is the live figure.
Milliscale estimate. No debit. Quote before every hunt.
X-API-Key or Bearer mago_sk_
Request
| Field | Type | Notes |
|---|
| target | string | Domain, mailbox, IP, handle, or phone. Max 255. |
| offer_id | string? | Optional. Resolved from the target type when omitted. |
| passive_only | bool | Default true. Skip active HTTP probes. |
| ai | bool | Default false. Adds the token hold to estimated_credits. |
Response
| Field | Type | Notes |
|---|
| product | string | Always search on the public hunt. |
| estimated_credits | int | Milliscale debit. SPELL_CREDITS sum plus tokens when ai is true. |
| charged_credits | int | Same number the scan will reserve. |
| module_credits | int | Spell sum without the token hold. |
| token_credits | int | AI hold. Zero when ai is false. |
| offer_id | string | Resolved offer, e.g. domain. |
| spells | string[] | Modules that will run. Truncated in the example below. |
curl -sS https://mago.team/api/v1/quote \
-H "X-API-Key: mago_sk_…" \
-H "Content-Type: application/json" \
-d '{"target":"example.com"}'{
"product": "search",
"estimated_credits": 208,
"charged_credits": 208,
"module_credits": 208,
"token_credits": 0,
"offer_id": "domain",
"spells": ["dns_deep", "subdomain_enum", "whois_osint"]
}Start the hunt. Returns order_id. Sandbox keys return sandbox-example and never debit.
X-API-Key or Bearer mago_sk_
Request
| Field | Type | Notes |
|---|
| target | string | Same selector as quote. |
| authorization_confirmed | bool | Must be true. 400 AuthorizationRequired otherwise. |
| passive_only | bool | Default true. |
| ai | bool | Default false. Reserved credits include the token hold. |
| offer_id | string? | Optional. Pack SKUs are ignored; product is search. |
Response
| Field | Type | Notes |
|---|
| order_id | string | Poll and stream secret. Foreign ids are 404. |
| credits_reserved | int | Equals charged_credits from quote for the same body. |
| status | string | queued on live. sandbox on mago_sk_test_. |
curl -sS https://mago.team/api/v1/scans \
-H "X-API-Key: mago_sk_…" \
-H "Content-Type: application/json" \
-d '{"target":"example.com","authorization_confirmed": true,"passive_only":true,"ai":false}'{
"order_id": "ord_01EXAMPLE",
"credits_reserved": 208,
"status": "queued"
}GET/api/v1/scans/{order_id}
200Owner poll. Another account’s order_id is 404.
X-API-Key or Bearer mago_sk_
Response
| Field | Type | Notes |
|---|
| order_id | string | Same id you posted. |
| status | string | queued, running, building, done, failed, cancelled. |
| target | string? | Selector. |
| product | string? | search. |
| progress | object? | done / total while running. |
curl -sS https://mago.team/api/v1/scans/{order_id} \
-H "X-API-Key: mago_sk_…"{
"order_id": "ord_01EXAMPLE",
"status": "running",
"target": "example.com",
"product": "search",
"progress": { "done": 4, "total": 18 }
}GET/api/billing/order/{order_id}/stream
200SSE until done, failed, or cancelled. One JSON object per event.
X-API-Key or Bearer mago_sk_
Response
| Field | Type | Notes |
|---|
| done | int | Modules finished. |
| total | int | Modules in this hunt. |
| status | string | Mirrors the order status. |
| order_id | string | Same id. |
curl -N https://mago.team/api/billing/order/{order_id}/stream \
-H "X-API-Key: mago_sk_…"{
"done": 4,
"total": 18,
"status": "running",
"order_id": "ord_01EXAMPLE"
}GET/api/v1/reports/{order_id}
200Public report JSON (project_public_dict). 409 while the report is still building.
X-API-Key or Bearer mago_sk_
curl -sS https://mago.team/api/v1/reports/{order_id} \
-H "X-API-Key: mago_sk_…"{
"target": { "value": "example.com", "type": "domain" },
"findings": [],
"metadata": { "order_id": "ord_01EXAMPLE", "generated_by": "MAGO" }
}Wallet. Monthly burns first, then permanent.
X-API-Key or Bearer mago_sk_
Response
| Field | Type | Notes |
|---|
| monthly | int | Plan allotment remaining. |
| permanent | int | Pack balance. |
| total | int | monthly + permanent. |
curl -sS https://mago.team/api/v1/credits \
-H "X-API-Key: mago_sk_…"
{
"monthly": 3000,
"permanent": 0,
"total": 3000
}POST/api/keys/generate
200Plaintext mago_sk_ returned once. Store it. Live hunts use this key.
Cookie mago-token. Detective+ session. Customer keys cannot mint.
Request
| Field | Type | Notes |
|---|
| name | string | Label. Default default. |
Response
| Field | Type | Notes |
|---|
| api_key | string | Shown once. |
| key_id | string | Revoke handle. |
| name | string | Label. |
| created_at | string | ISO-8601. |
curl -sS https://mago.team/api/keys/generate \
-H "Cookie: mago-token=…" \
-H "Content-Type: application/json" \
-d '{"name":"desk"}'{
"api_key": "mago_sk_…",
"key_id": "key_…",
"name": "desk",
"created_at": "2026-10-03T00:00:00+00:00"
}Errors
JSON bodies. A hunt that exceeds the wallet is 402. Another account's order_id is 404.
| Status | Name | When |
|---|
| AuthorizationRequired | POST /api/v1/scans without authorization_confirmed true. |
| Invalid API key | Missing, revoked, or malformed mago_sk_ header. |
| Insufficient credits | Wallet total is below the milliscale debit for this target. |
| ApiAccessRequired | Operative or Scout key. Customer keys on admin, spells/run, or /api/keys. |
400 AuthorizationRequired
{
"detail": {
"error": "AuthorizationRequired",
"message": "You must confirm authorization to scan this target."
}
}{
"detail": {
"error": "AuthorizationRequired",
"message": "You must confirm authorization to scan this target."
}
}{ "detail": "Invalid API key" }{ "detail": "Insufficient credits: need 208, have 50" }{
"detail": {
"error": "ApiAccessRequired",
"required_plan": "pro",
"current_plan": "solo",
"upgrade_url": "/pricing"
}
}