TRACE API v1

Trace API v1

Reverse face search,
from your own code

Upload a face photo. Get back the public profiles it appears on, with a confidence score for each. One credit per search, no subscription, and the same engine the panel uses.

Quick start

1

Start a scan

curl -X POST https://traceaifacescan.app/api/v1/scans \
  -H "Authorization: Bearer trk_live_YOUR_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -F [email protected]

202 Accepted

{
  "id": "01m0jr1j5cbhwqsnt5qjx3zyd8",
  "number": 1,
  "status": "queued",
  "progress": 0,
  "locked": true,
  "match_count": 0,
  "credits_remaining": 9
}
2

Poll until it finishes

A search takes 25-45 seconds. Poll every second or two until status is done or failed.

curl https://traceaifacescan.app/api/v1/scans/SCAN_ID \
  -H "Authorization: Bearer trk_live_YOUR_KEY"

200 OK

{
  "id": "01m0jr1j5cbhwqsnt5qjx3zyd8",
  "status": "done",
  "progress": 100,
  "locked": false,
  "match_count": 2,
  "matches": [
    {
      "score": 88,
      "tier": "strong",
      "platform": "x",
      "handle": "@alexrivers88",
      "url": "https://x.com/alexrivers88",
      "preview_url": "https://traceaifacescan.app/api/v1/scans/01m0.../previews/0"
    },
    {
      "score": 86,
      "tier": "strong",
      "platform": "instagram",
      "handle": null,
      "url": "https://www.instagram.com/p/DaAPjbsDTxV/",
      "preview_url": "https://traceaifacescan.app/api/v1/scans/01m0.../previews/1"
    }
  ]
}

handle is null when the URL points at a post rather than an account. Two posts on one platform are two different results, so they are not merged.

Authentication

Every request carries a key from the panel. There is no session, no cookie and no CSRF token — the key is the whole credential.

Authorization: Bearer trk_live_9F4KQ2M7…

A missing, malformed, revoked or unknown key all return the same 401. That is deliberate: telling them apart would let anyone test whether a key exists.

Credits and previews

A scan started with credits available runs the search and returns real profile links. With no credits the scan is created but no search runs: it comes back locked: true with match_count: 0 and an empty matches array. Reveal it to spend a credit and run the real thing.

The panel shows a signed-in visitor with no credits a static sample result, so they can see what a finished case looks like. The API never returns it — a placeholder is something a script would build on.

Revealing a locked scan is a separate call, never automatic: a script walking a list of scans should not be able to empty your balance by accident.

curl -X POST https://traceaifacescan.app/api/v1/scans/SCAN_ID/reveal \
  -H "Authorization: Bearer trk_live_YOUR_KEY"

The credit is reserved when the search starts and returned automatically if it fails. A scan that has already been revealed returns 200 and costs nothing.

Scans

POST /scans Start a scan. multipart, field name image.
GET /scans List your scans, newest first. Matches omitted.
GET /scans/{id} One scan, with its matches.
POST /scans/{id}/reveal Spend a credit and reveal the sources.
GET /scans/{id}/previews/{n} The thumbnail of one match.
DELETE /scans/{id} Delete the scan, its image and its previews.

The image

  • jpeg, png or webp — at most 8 MB, at least 200×200 px.
  • Crop to the face. A front-on, sharp, well-lit face is what makes a search work.
  • There is no image_url parameter and there will not be one in v1 — fetching an arbitrary address on your behalf would make this endpoint an SSRF proxy.

Retries

Send an Idempotency-Key header when starting a scan. The same key within 24 hours returns the original scan instead of starting a second one — so a request that times out on your side can be retried without paying twice.

Previews

preview_url needs the same Authorization header. It is not a public link and not a signed one: a shareable URL for a face image would outlive the key it came from.

Account

GET /account Your credit balance and this key's limits.

200 OK

{
  "account_id": "TRC-4K7F-9QX2",
  "credits": 9,
  "scan_cost": 1,
  "api_key": {
    "name": "production server",
    "prefix": "trk_live_9F4KQ2",
    "rate_limit_per_min": 0
  }
}

Errors

Errors are application/problem+json (RFC 9457). Branch on code — it is part of the contract. detail is written for humans and may change without warning.

402 Payment Required

{
  "type": "https://traceaifacescan.app/docs#insufficient_credits",
  "title": "insufficient credits",
  "status": 402,
  "code": "insufficient_credits",
  "detail": "Not enough credits to run the full search.",
  "credits_remaining": 0
}
STATUS CODE WHEN
401 unauthenticated Missing, malformed, revoked or unknown key.
402 insufficient_credits Reveal was called without enough credits.
404 not_found No scan with that id on your account.
409 not_found The query image was already deleted, so it cannot be revealed.
422 invalid_image Wrong format, too large, or too small.
429 rate_limited Over the limit. See the Retry-After header.
500 server_error Our fault. Logged on our side.

Failed searches

A search that starts and then fails is not an HTTP error — the scan comes back with status: "failed" and an error_code. The reserved credit is always returned. Only no_face is something you can fix, by sending a clearer photo.

Rate limits

There is no request rate limit. Call the API as fast as your code can. What actually costs something is a scan, and its limit is your credit balance — reads cost nothing and are not counted.

One ceiling remains and it is a security one, not a usage one: repeated failed authentication attempts from the same address are throttled, so guessing keys stays expensive. A valid key never sees it. If a single key ever has to be capped we can set a per-key limit; when we do, rate_limit_per_min on GET /v1/account stops being 0 and responses start carrying X-RateLimit-Limit and X-RateLimit-Remaining.

Retention and rules

  • Trace runs the search on its own engine, which queries public image search engines on your behalf. To do that the image is served from an unguessable address for up to 10 minutes while the search runs. Those engines keep their own caches, which we do not control.
  • Trace keeps the image and the results for 30 days, then deletes both. DELETE /scans/{id} does it immediately.
  • Images are stored outside the web root and served only through this API, under your own key.
  • Only search photos you have the right to use, and follow the law where you are. By calling this API you take responsibility for that — see the Terms.