Audits
Create, fetch, and cancel audits.
Three endpoints cover the full audit lifecycle.
POST /audit — create
Enqueues a new audit. Returns 202 Accepted immediately; the engine
processes asynchronously.
Request
POST /api/v1/audit HTTP/1.1
Host: citeflow.io
Authorization: Bearer ckf_…
Content-Type: application/json
Idempotency-Key: <uuid>{
"url": "https://example.com",
"type": "seo",
"metadata": { "your_internal_id": "abc-123" }
}| Field | Type | Required | Notes |
|---|---|---|---|
url | string | yes | http:// or https://. Max ~2,000 chars. |
type | enum | yes | all · seo · aeo · geo. |
metadata | object | no | Free-form tags echoed back in webhook events (future). |
Idempotency-Key (header) is strongly recommended — see
Idempotency.
Pricing
type | Credits | USD |
|---|---|---|
all | 150 | $1.50 |
seo | 80 | $0.80 |
aeo | 80 | $0.80 |
geo | 80 | $0.80 |
The deduction happens before the engine runs. If your balance is
short, you receive 402 INSUFFICIENT_CREDITS and no audit row is
created.
Response — 202 Accepted
{
"data": {
"audit_id": "vH4kZcLm9YxQrTpA2gWb",
"status": "queued",
"type": "seo",
"url": "https://example.com",
"credits": { "charged": 80, "balance_after": 4820 },
"links": { "self": "/api/v1/audit/vH4kZcLm9YxQrTpA2gWb" },
"created_at": "2026-05-27T14:32:11.001Z"
},
"request_id": "req_01jbq6t8…"
}balance_after is your remaining credit after the debit. Stash the
audit_id — that's how you fetch the result.
Errors
| Status | Code | When |
|---|---|---|
| 400 | INVALID_URL | Body isn't valid JSON or url isn't http(s). |
| 400 | INVALID_TYPE | type not in all/seo/aeo/geo. |
| 402 | INSUFFICIENT_CREDITS | Balance below the required credits. Response includes error.required. |
| 409 | IDEMPOTENCY_CONFLICT | Same Idempotency-Key reused with a different body. |
| 413 | BODY_TOO_LARGE | Body > 1MB. |
| 429 | RATE_LIMITED | Per-key rate limit hit. Honor Retry-After. |
| 503 | ENGINE_BUSY | Engine saturated. Retry after Retry-After (default 30s). |
GET /audit/{audit_id} — fetch
Polled to track audit progress and read the result. Costs 0 credits.
curl https://www.citeflow.io/api/v1/audit/vH4kZcLm9YxQrTpA2gWb \
-H "Authorization: Bearer ckf_…"The response shape depends on status:
queued / processing
{
"data": {
"audit_id": "vH4kZcLm9YxQrTpA2gWb",
"status": "processing",
"type": "seo",
"url": "https://example.com",
"credits": { "charged": 80, "refunded": 0 },
"created_at": "2026-05-27T14:32:11.001Z"
}
}complete
{
"data": {
"audit_id": "vH4kZcLm9YxQrTpA2gWb",
"status": "complete",
"type": "seo",
"url": "https://example.com",
"scores": {
"overall": 76,
"seo": 81,
"aeo": null,
"geo": null
},
"dimensions": { "...": "engine-specific breakdown" },
"issues": [{ "...": "prioritized issues list" }],
"credits": { "charged": 80, "refunded": 0 },
"created_at": "...",
"completed_at": "2026-05-27T14:32:54.622Z"
}
}Score fields outside the purchased type are null, even if the
engine produced values — you get what you paid for.
failed
{
"data": {
"audit_id": "...",
"status": "failed",
"type": "seo",
"url": "https://example.com",
"failure_reason": "timeout",
"error": {
"code": "AUDIT_TIMEOUT",
"message": "Engine timed out fetching the target URL"
},
"credits": { "charged": 80, "refunded": 40 },
"created_at": "...",
"completed_at": "..."
}
}Refund amount follows the refund matrix.
cancelled
{
"data": {
"audit_id": "...",
"status": "cancelled",
"type": "seo",
"url": "https://example.com",
"credits": { "charged": 80, "refunded": 80 },
"created_at": "...",
"completed_at": "..."
}
}Polling recommendation
Poll every 5–10 seconds with exponential back-off. Most audits finish in 15–60 seconds. Webhooks remove the need to poll entirely — see Webhooks.
Polling is cheap (no credit cost) and rate limits are generous: 300 req/min for Starter, up to 6,000/min for Enterprise.
POST /audit/{audit_id}:cancel — cancel
Cancels an in-flight audit. Refund matrix:
| Current status | Refund |
|---|---|
queued | 100% |
processing | 50% |
complete / failed / cancelled | No-op — returns current state. |
Idempotent: calling twice on a queued audit returns the cancelled state from the second call.
curl -X POST \
"https://www.citeflow.io/api/v1/audit/vH4kZcLm9YxQrTpA2gWb:cancel" \
-H "Authorization: Bearer ckf_…"Response — 200
{
"data": {
"audit_id": "vH4kZcLm9YxQrTpA2gWb",
"status": "cancelled",
"credits": { "charged": 80, "refunded": 80 }
}
}The cancelled audit fires an audit.cancelled webhook so downstream
systems can clean up.