CiteFlow API

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" }
}
FieldTypeRequiredNotes
urlstringyeshttp:// or https://. Max ~2,000 chars.
typeenumyesall · seo · aeo · geo.
metadataobjectnoFree-form tags echoed back in webhook events (future).

Idempotency-Key (header) is strongly recommended — see Idempotency.

Pricing

typeCreditsUSD
all150$1.50
seo80$0.80
aeo80$0.80
geo80$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

StatusCodeWhen
400INVALID_URLBody isn't valid JSON or url isn't http(s).
400INVALID_TYPEtype not in all/seo/aeo/geo.
402INSUFFICIENT_CREDITSBalance below the required credits. Response includes error.required.
409IDEMPOTENCY_CONFLICTSame Idempotency-Key reused with a different body.
413BODY_TOO_LARGEBody > 1MB.
429RATE_LIMITEDPer-key rate limit hit. Honor Retry-After.
503ENGINE_BUSYEngine 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 statusRefund
queued100%
processing50%
complete / failed / cancelledNo-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.

On this page