ClearStaq API

Bank statement analysis over HTTPS

Submit a PDF, receive structured revenue, fraud, and debt analysis via signed webhook. Credentials are generated at app.clearstaq.com.

Overview

Submit a bank-statement PDF to https://app.clearstaq.com/api/v1/analyses. The endpoint returns 202 Accepted with an analysis id; the full parsed result is delivered asynchronously to your callback_url as a signed webhook.

API access is available on StaqCore and above. Free-tier orgs cannot generate API keys.

Authentication

Every request must include a bearer token issued from your Integrations settings page. Keep both the cg_live_* key and the whsec_* webhook secret out of version control.

Authorization: Bearer cg_live_YOUR_KEY_HERE

Submit a statement

Multipart upload. Maximum size 25 MB. Only application/pdf is accepted.

cURL
Node.js
Python
curl -X POST https://app.clearstaq.com/api/v1/analyses \
  -H "Authorization: Bearer cg_live_YOUR_KEY_HERE" \
  -F "file=@./statement.pdf" \
  -F "callback_url=https://your-app.example.com/hooks/clearstaq" \
  -F "client_ref=customer-123" \
  -F 'metadata={"loan_id":"LN-999"}'

Receive the result

When the analysis completes, ClearStaq POSTs a signed JSON envelope to your callback_url. Respond with any 2xx status within 10s to acknowledge. Non-2xx responses are retried up to 5 times with exponential backoff (1m, 5m, 30m, 2h, 12h).

POST /hooks/clearstaq HTTP/1.1
Content-Type: application/json
X-ClearStaq-Event: analysis.completed
X-ClearStaq-Delivery: 2f8b0...
X-ClearStaq-Signature: sha256=<hex hmac>

{
  "id": "cb_...",
  "event": "analysis.completed",
  "client_ref": "customer-123",
  "status": "completed",
  "result": { "bank_name": "Chase", "true_revenue": 84250.12, ... }
}

Verify the signature

Compute HMAC-SHA256 over the raw request body using your webhook signing secret and compare (timing-safe) to the X-ClearStaq-Signature header.

Node.js
import crypto from "node:crypto"

// In your webhook handler:
export default function handler(req, res) {
  const signature = req.headers["x-clearstaq-signature"]
  const raw = req.rawBody // the exact JSON bytes ClearStaq sent
  const expected =
    "sha256=" + crypto.createHmac("sha256", process.env.CLEARSTAQ_WEBHOOK_SECRET).update(raw).digest("hex")
  const ok = crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature ?? ""))
  if (!ok) return res.status(400).send("bad signature")
  // req.body is the WebhookEnvelope — act on it, then respond 2xx.
  res.status(200).send("ok")
}

Error codes

HTTPCodeMeaning
401unauthorizedMissing or unrecognised API key.
402plan_excludedOrg is on the Free plan.
402insufficient_creditsNo credits remaining and auto top-up is off.
413file_too_largePDF exceeds 25 MB.
415unsupported_media_typeNon-PDF upload.
422invalid_callback_urlcallback_url could not be parsed.
502parser_unavailableDownstream parser could not accept the job.

OpenAPI spec

Download the machine-readable spec to generate SDKs or import into Postman/Insomnia. openapi.yaml