Developers
v1ComplianceLayer exposes a small, honest REST API. Submit a URL, poll for the result, block the merge if the score drops. A signed webhook is also available for push-based integrations.
Quick start
Create a key on the keys page. Export it as an environment variable and you're set.
export CL_API_KEY="cl_live_..."
# 1. Submit a scan
curl -X POST https://compliancelayer.eu/api/v1/scan \
-H "Authorization: Bearer $CL_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://your-site.eu"}'
# 2. Poll for the result (threshold optional)
curl "https://compliancelayer.eu/api/v1/scan?id=JOB_ID&threshold=70" \
-H "Authorization: Bearer $CL_API_KEY"Authentication
Every API request carries an Authorization header. Keys start with cl_live_.
Authorization: Bearer cl_live_...On failure you'll get 401 with a JSON body explaining whether the key was missing, invalid, or rate limited. A key is a password — keep it in a secrets store, not in the repo. Rotate from the keys page if it leaks.
Submit a scan
Request body:
{ "url": "https://your-site.eu" }Response (201 Created):
{
"id": "2d0a…",
"status": "pending",
"url": "https://your-site.eu",
"poll_url": "/api/v1/scan?id=2d0a…",
"created_at": "2026-05-01T12:00:00.000Z"
}Returns immediately with a job ID. The scan runs in the background. Each call counts against your daily API quota.
Poll for the result
Poll every few seconds until status becomes complete or failed. When the scan completes, the response includes score, framework, violations, GDPR checks, and permanent report and badge URLs. Pass &threshold=70 to get a boolean pass field you can use as a CI exit code.
{
"id": "2d0a…",
"url": "https://your-site.eu",
"status": "complete",
"score": 82,
"framework": "nextjs",
"pages_scanned": 12,
"violation_count": 4,
"violations": [ { "title": "...", "severity": "...", "description": "...", "remediation": "..." } ],
"gdpr_checks": [ { "name": "...", "passed": true, "details": "..." } ],
"report_url": "/report/2d0a…",
"badge_url": "/api/badge/2d0a…",
"pass": true,
"threshold": 70
}Webhooks
Create an endpoint by POSTing to /api/v1/webhooks. You'll get back a secret (one time — save it). We deliver each matching event with two headers:
X-ComplianceLayer-Event: scan.completed
X-ComplianceLayer-Signature: sha256=<hex digest of body>Body shape:
{
"event": "scan.completed",
"timestamp": "2026-05-01T12:00:00.000Z",
"data": { "scan_id": "2d0a…", "score": 82, "url": "https://..." }
}Verify (Node):
import crypto from "node:crypto";
function verify(secret, rawBody, header) {
const expected = crypto
.createHmac("sha256", secret)
.update(rawBody)
.digest("hex");
return header === `sha256=${expected}`;
}Every payload is signed with HMAC-SHA256 — verify it. We retry once on network failure. Non-2xx responses between 400 and 499 are treated as terminal.
GitHub Action
- name: ComplianceLayer scan
uses: compliancelayer/action@v1
with:
url: https://your-site.eu
api-key: ${{ secrets.CL_API_KEY }}
threshold: 70A GitLab CI template is available in docs/gitlab-ci-template.yml.
MCP server
Add the hosted Attestloop MCP endpoint to Cursor, Claude Code, or another MCP-compatible client. It exposes deterministic AI-surface scanning at generation time.
{
"mcpServers": {
"attestloop": {
"url": "https://compliancelayer-production.up.railway.app/api/mcp"
}
}
}Claude Code:
claude mcp add --transport http attestloop \
https://compliancelayer-production.up.railway.app/api/mcpRate limits
| Plan | Keys | API scans / day |
|---|---|---|
| Reader | 1 | 10 |
| Professional | 5 | 500 |
| Team | 10 | 2,000 |
| Agency | 25 | 10,000 |
Limits are per plan, enforced per key. When you hit them, you get a 429 back and a note explaining how much remains. Need more? hello@compliancelayer.eu.