CrowdSec Service API (SAPI) — cloud blocklist / allowlist / integration automation
SAPI is the premium REST API behind the CrowdSec Console. It manages
cloud-side objects (private blocklists, allowlists, decisions, firewall integrations)
that then push down to enrolled engines and bouncers. It is not the local
engine API — there is no cscli here, only HTTPS.
Boundary — this skill vs the crowdsec skill
| You want to… |
Use |
| Create/manage a private blocklist in the cloud, push IPs to it via API |
this skill |
| Wire a firewall/appliance (Palo Alto, Fortinet…) to a cloud integration |
this skill |
| Manage cloud allowlists, subscribe engines/tags/orgs to lists |
this skill |
| Create/manage org-level decisions (targeted or ad-hoc bans, non-IP scopes, per tag/entity) |
this skill |
| Pull remediation ROI metrics |
this skill |
Install / run / debug the local engine, cscli, bouncers, WAF |
the crowdsec skill |
Enroll an engine into the Console (cscli console enroll) |
the crowdsec skill → references/install/console.md |
| Configure a local allowlist/whitelist on one engine |
the crowdsec skill → references/configure/allowlists.md |
Cloud allowlists/blocklists here only take effect on an engine once that engine
is enrolled and subscribed to the list. The enrollment half lives in the
crowdsec skill.
Operating contract
Every call here hits production and can change what subscribed engines enforce.
1 — Resolve the key. Never echo it, never write it anywhere but the file
below:
KEY="${CROWDSEC_SAPI_KEY:-$(cat ~/.config/crowdsec/sapi_key 2>/dev/null)}"
[ -n "$KEY" ] || echo "No key: export CROWDSEC_SAPI_KEY or store it in ~/.config/crowdsec/sapi_key (chmod 0600)"
2 — Validate before acting — one read call confirms the key and shows which
tenant is about to change:
curl -s -H "x-api-key: $KEY" https://admin.api.crowdsec.net/v1/info
# → {"organization_id":"…","subscription_type":"…","api_key_name":"…"}
3 — Classify read vs mutate. GET / download / POST …/search are safe —
run them directly. Every POST / PATCH / DELETE that changes state
requires explicit confirmation first: present the exact URL and JSON body,
then wait for a yes.
4 — Extra-danger operations — spell out the consequence in plain words
before the confirm, because subscribed engines enforce these lists, so a
change can block or unblock real traffic and is hard to undo:
| Operation |
Why it's dangerous |
POST …/ips/bulk_overwrite |
Replaces the entire blocklist content. |
DELETE /blocklists/{id} · /allowlists/{id} · /integrations/{id} |
Removes the object and everyone's subscription/feed to it. |
POST …/ips/delete |
Un-blocks IPs fleet-wide. |
POST /decisions with target.type: org |
Bans fleet-wide across every enrolled engine in the org. |
…/shares / unshare |
Grants/revokes another organization access. |
any …/subscribers change |
Changes which engines/bouncers enforce the list. |
5 — Clean up any object created only to test a recipe. A key that was exposed
anywhere in transit must be rotated.
Step — Detect the intent
| Cue from user |
Go to |
| "test my key", "what org / plan am I on" |
references/authentication.md |
| "create a blocklist", "push IPs from my SIEM/SOAR", "expire IPs", "share a blocklist with another org", "subscribe my engine to a list" |
references/blocklists.md |
| "cloud allowlist via API", "allow my office/CDN across the fleet" |
references/allowlists.md |
| "connect Palo Alto / Fortinet / Cisco / F5 / Sophos / pfSense / OPNsense", "firewall integration", "pull IP list in vendor format", "paginate the feed" |
references/integrations.md |
| "remediation metrics", "how much did CrowdSec save / block", "ROI dashboard" |
references/metrics.md |
| "org-level decisions via API", "aggregated decisions" |
references/decisions.md |
Step — curl cheat sheet
All assume KEY is set (see operating contract). jq optional for readability.
| Purpose |
Command |
| Who am I / validate key |
curl -s -H "x-api-key: $KEY" $B/info |
| List blocklists |
curl -s -H "x-api-key: $KEY" "$B/blocklists" |
| List allowlists |
curl -s -H "x-api-key: $KEY" "$B/allowlists" |
| List integrations |
curl -s -H "x-api-key: $KEY" "$B/integrations" |
| List / find decisions |
curl -s -H "x-api-key: $KEY" "$B/decisions" · …?ips=1.2.3.4 |
| Remediation metrics |
curl -s -H "x-api-key: $KEY" "$B/metrics/remediation?start_date=$FROM&end_date=$TO" |
| Add IPs to a blocklist (mutating — confirm) |
curl -s -H "x-api-key: $KEY" -H 'Content-Type: application/json' -X POST "$B/blocklists/$ID/ips" -d '{"ips":["1.2.3.4"]}' |
| Create a decision (mutating — confirm) |
curl -s -H "x-api-key: $KEY" -H 'Content-Type: application/json' -X POST "$B/decisions" -d '{"duration":"4h","origin":"cscli","scenario":"manual","scope":"Ip","type":"ban","value":"1.2.3.4","target":{"type":"org","value":"<org>"}}' |
where B=https://admin.api.crowdsec.net/v1.
Hard don'ts
- Don't send a mutating call before the URL + body have been shown and approved
(see operating contract §3–4).
- Don't use
…/ips/bulk_overwrite when the user means "add a few IPs" — that's
…/ips. bulk_overwrite wipes the list first.
- Don't print, log, or persist the API key anywhere but
~/.config/crowdsec/sapi_key. Resolve it from there or from the env var only.
- Don't assume a cloud allowlist/blocklist is enforced just because the API call
succeeded — the engine must be enrolled and subscribed, and it pulls on a poll
cycle (verify locally via the
crowdsec skill).
Docs
Canonical: https://docs.crowdsec.net/u/console/service_api/getting_started. Each
references/ file cites the specific upstream page and the live OpenAPI operation
it derives from.
1---2name: crowdsec-service-api3description: Use when the user wants to drive the CrowdSec Console **Service API (SAPI)** — the premium cloud REST API at admin.api.crowdsec.net — to programmatically manage blocklists (add/remove/bulk IPs, share, subscribe engines), allowlists, firewall/appliance integrations (Palo Alto, Fortinet, Cisco, F5, Sophos, pfSense/OPNsense…), remediation ROI metrics, and org-level decisions. Acts on the user's behalf with their API key. This is the cloud/API skill — for the local engine, cscli, and bouncers use the `crowdsec` skill.4---56# CrowdSec Service API (SAPI) — cloud blocklist / allowlist / integration automation78SAPI is the **premium** REST API behind the CrowdSec Console. It manages9**cloud-side** objects (private blocklists, allowlists, decisions, firewall integrations)10that then push down to enrolled engines and bouncers. It is **not** the local11engine API — there is no `cscli` here, only HTTPS.1213- **Base URL:** `https://admin.api.crowdsec.net/v1`14- **Auth:** `x-api-key: <key>` header on every call. (One exception: the15 integration *content* endpoint uses HTTP Basic with credentials minted at16 integration creation — see [references/integrations.md](./references/integrations.md).)17- **Interactive API docs:** <https://admin.api.crowdsec.net/v1/docs> · spec18 <https://admin.api.crowdsec.net/v1/openapi.json>1920## Boundary — this skill vs the `crowdsec` skill2122| You want to… | Use |23|---|---|24| Create/manage a **private blocklist** in the cloud, push IPs to it via API | this skill |25| Wire a firewall/appliance (Palo Alto, Fortinet…) to a cloud **integration** | this skill |26| Manage **cloud allowlists**, subscribe engines/tags/orgs to lists | this skill |27| Create/manage **org-level decisions** (targeted or ad-hoc bans, non-IP scopes, per tag/entity) | this skill |28| Pull **remediation ROI metrics** | this skill |29| Install / run / debug the **local engine**, `cscli`, bouncers, WAF | the `crowdsec` skill |30| **Enroll** an engine into the Console (`cscli console enroll`) | the `crowdsec` skill → `references/install/console.md` |31| Configure a **local** allowlist/whitelist on one engine | the `crowdsec` skill → `references/configure/allowlists.md` |3233Cloud allowlists/blocklists here only take effect on an engine once that engine34is enrolled **and** subscribed to the list. The enrollment half lives in the35`crowdsec` skill.3637## Operating contract3839Every call here hits production and can change what subscribed engines enforce.4041**1 — Resolve the key.** Never echo it, never write it anywhere but the file42below:43```bash44KEY="${CROWDSEC_SAPI_KEY:-$(cat ~/.config/crowdsec/sapi_key 2>/dev/null)}"45[ -n "$KEY" ] || echo "No key: export CROWDSEC_SAPI_KEY or store it in ~/.config/crowdsec/sapi_key (chmod 0600)"46```4748**2 — Validate before acting** — one read call confirms the key and shows *which49tenant* is about to change:50```bash51curl -s -H "x-api-key: $KEY" https://admin.api.crowdsec.net/v1/info52# → {"organization_id":"…","subscription_type":"…","api_key_name":"…"}53```5455**3 — Classify read vs mutate.** `GET` / download / `POST …/search` are safe —56run them directly. Every **`POST` / `PATCH` / `DELETE` that changes state**57requires **explicit confirmation first**: present the exact URL and JSON body,58then wait for a yes.5960**4 — Extra-danger operations** — spell out the consequence in plain words61*before* the confirm, because subscribed engines **enforce** these lists, so a62change can block or unblock real traffic and is hard to undo:6364| Operation | Why it's dangerous |65|---|---|66| `POST …/ips/bulk_overwrite` | Replaces the **entire** blocklist content. |67| `DELETE /blocklists/{id}` · `/allowlists/{id}` · `/integrations/{id}` | Removes the object and everyone's subscription/feed to it. |68| `POST …/ips/delete` | Un-blocks IPs fleet-wide. |69| `POST /decisions` with `target.type: org` | Bans fleet-wide across every enrolled engine in the org. |70| `…/shares` / unshare | Grants/revokes another **organization** access. |71| any `…/subscribers` change | Changes which engines/bouncers enforce the list. |7273**5 — Clean up** any object created only to test a recipe. A key that was exposed74anywhere in transit must be rotated.7576## Step — Detect the intent7778| Cue from user | Go to |79|---|---|80| "test my key", "what org / plan am I on" | [references/authentication.md](./references/authentication.md) |81| "create a blocklist", "push IPs from my SIEM/SOAR", "expire IPs", "share a blocklist with another org", "subscribe my engine to a list" | [references/blocklists.md](./references/blocklists.md) |82| "cloud allowlist via API", "allow my office/CDN across the fleet" | [references/allowlists.md](./references/allowlists.md) |83| "connect Palo Alto / Fortinet / Cisco / F5 / Sophos / pfSense / OPNsense", "firewall integration", "pull IP list in vendor format", "paginate the feed" | [references/integrations.md](./references/integrations.md) |84| "remediation metrics", "how much did CrowdSec save / block", "ROI dashboard" | [references/metrics.md](./references/metrics.md) |85| "org-level decisions via API", "aggregated decisions" | [references/decisions.md](./references/decisions.md) |8687## Step — curl cheat sheet8889All assume `KEY` is set (see operating contract). `jq` optional for readability.9091| Purpose | Command |92|---|---|93| Who am I / validate key | `curl -s -H "x-api-key: $KEY" $B/info` |94| List blocklists | `curl -s -H "x-api-key: $KEY" "$B/blocklists"` |95| List allowlists | `curl -s -H "x-api-key: $KEY" "$B/allowlists"` |96| List integrations | `curl -s -H "x-api-key: $KEY" "$B/integrations"` |97| List / find decisions | `curl -s -H "x-api-key: $KEY" "$B/decisions"` · `…?ips=1.2.3.4` |98| Remediation metrics | `curl -s -H "x-api-key: $KEY" "$B/metrics/remediation?start_date=$FROM&end_date=$TO"` |99| Add IPs to a blocklist *(mutating — confirm)* | `curl -s -H "x-api-key: $KEY" -H 'Content-Type: application/json' -X POST "$B/blocklists/$ID/ips" -d '{"ips":["1.2.3.4"]}'` |100| Create a decision *(mutating — confirm)* | `curl -s -H "x-api-key: $KEY" -H 'Content-Type: application/json' -X POST "$B/decisions" -d '{"duration":"4h","origin":"cscli","scenario":"manual","scope":"Ip","type":"ban","value":"1.2.3.4","target":{"type":"org","value":"<org>"}}'` |101102where `B=https://admin.api.crowdsec.net/v1`.103104## Hard don'ts105106- Don't send a mutating call before the URL + body have been shown and approved107 (see operating contract §3–4).108- Don't use `…/ips/bulk_overwrite` when the user means "add a few IPs" — that's109 `…/ips`. `bulk_overwrite` wipes the list first.110- Don't print, log, or persist the API key anywhere but111 `~/.config/crowdsec/sapi_key`. Resolve it from there or from the env var only.112- Don't assume a cloud allowlist/blocklist is enforced just because the API call113 succeeded — the engine must be enrolled and subscribed, and it pulls on a poll114 cycle (verify locally via the `crowdsec` skill).115116## Docs117118Canonical: <https://docs.crowdsec.net/u/console/service_api/getting_started>. Each119`references/` file cites the specific upstream page and the live OpenAPI operation120it derives from.