One request. One verdict.
Send an image, get a three-band verdict with the exact score, the provenance we found and the model version.
Anyone can request access, any time. Enabled within an hour.
$ curl https://perspicax.io/api/v1/scans \ -H "Authorization: Bearer $PERSPICAX_KEY" \ -H "Prefer: wait=10" \ -F [email protected]# 200 OK{ "status": "completed", "result": { "label": "ai_generated", "score": 0.97, "provenance": { "c2pa": null } }, "model": { "name": "TrueEye", "version": "2.1" }}At a glance
- Endpoint
POST /api/v1/scans- Authentication
Authorization: Bearer pcx_live_…- Wait
- Prefer: wait=N, up to 30 seconds
- Retries
- Idempotency-Key header
- Images
- Up to 20 MB, by file or by URL
Sync: wait for the answer
Send Prefer: wait=N (N up to 30). If the scan finishes in time, you get 200 with the result in the same call.
curl https://perspicax.io/api/v1/scans \
-H "Authorization: Bearer $PERSPICAX_KEY" \
-H "Prefer: wait=10" \
-H "Idempotency-Key: $(uuidgen)" \
-F [email protected]
# Or scan an image by URL:
curl https://perspicax.io/api/v1/scans \
-H "Authorization: Bearer $PERSPICAX_KEY" \
-H "Content-Type: application/json" \
-H "Prefer: wait=10" \
-d '{"url": "https://example.com/photo.jpg"}'Async: take a 202 and poll
If the scan is still running, you get 202 with a Location header. Poll GET /api/v1/scans/:id until status is completed.
Credits
GET /api/v1/usage returns your remaining credits, the end of the period and what you used in it.
Enterprise
A credit allowance for your team that refreshes every month or year, with top-ups any time, a live usage dashboard, alerts before you run out, API keys and retention options. Contact us and we'll set it up.
Contact us# 1. Send without waiting (or when your wait runs out): 202 Accepted
curl -i https://perspicax.io/api/v1/scans \
-H "Authorization: Bearer $PERSPICAX_KEY" \
-F [email protected]
# HTTP/1.1 202 Accepted
# Location: /api/v1/scans/<id>
# 2. Poll until status is "completed" (or "failed")
curl https://perspicax.io/api/v1/scans/<id> \
-H "Authorization: Bearer $PERSPICAX_KEY"
# Credits left in this period
curl https://perspicax.io/api/v1/usage \
-H "Authorization: Bearer $PERSPICAX_KEY"
# { "creditsRemaining": …, "periodEnd": "…", "usedThisPeriod": … }Read the result
| Field | Meaning |
|---|---|
| result.label | ai_generated, inconclusive or not_ai_generated. Build your flow on this. |
| result.score | The detector score from 0 to 1. Only API keys see it. It is not a probability. |
| result.thresholds | The two cut-offs of this model version. |
| result.inconclusiveReason | between_thresholds, or outside_scope for screenshots, documents and graphics. |
| result.provenance | Content Credentials (C2PA) and the IPTC digital source type, when present. |
| model.version | The model name and version (TrueEye 2.1), recorded on every scan. |
- Content Credentials (C2PA)Live
- SynthID watermark checkSupported
Errors to handle
Errors follow RFC 9457 problem details with a code field.
| Status | Code | What to do |
|---|---|---|
| 401 | unauthorized | Check the key in the Authorization header. |
| 402 | insufficient_credits | Your credits are used up. Top up, or wait for the next period. |
| 413 | file_too_large | Send an image of 20 MB or less. |
| 415 | unsupported_media_type | Send JPEG, PNG, WebP, HEIC, AVIF or a still GIF. |
| 422 | unprocessable_image | The image could not be decoded. Check the file. |
| 429 | rate_limited | Slow down and retry after the Retry-After header. |
| 503 | detector_unavailable | Retry with the same Idempotency-Key. |
Request API access
Anyone can request access, any time. Enabled within an hour.