PCIFIC PixelTrace

Record submitted photo evidence taken with the PixelTrace camera, and flag copies of those photos in your own shop.

Which photos PixelTrace compares against

Live PixelTrace groups only take photos from the seller's phone camera, in iPhone Safari or Android Chrome, so arrange a person with a phone first. Opening the link on a computer does not use it up. Test keys can upload and confirm with test-photos and test-confirm.

PixelTrace compares submitted photos against photos taken with the PixelTrace camera and published. Photos uploaded from a phone gallery or an existing catalogue cannot be published to a live group, so they never become one of your published photos. Photos a test key uploads stay in test groups and only match other test groups. That is by design: if businesses could register their own photos, anyone could claim stock photos as theirs. Sending such a photo to the check address can still show that it is a copy of a published camera photo.

Browser-only capture is submitted evidence. Its trust level is at most normal, never strong. Public badges say PixelTrace submitted evidence; demo badges say PixelTrace demo evidence. The signature covers the ordered photos, file fingerprints and trust levels, not proof of camera hardware.

PixelTrace lets a seller take a listing's photos on their own phone through a PCIFIC camera page, checks each photo for signs it was taken live, and finds photos that were used in this business before.

What a result means, and what it does not

  • PixelTrace cannot prove where a photo came from. No web page can. Someone with a modified browser can fake every sign the camera page records, and a real phone pointed at a screen or a printed photo can pass every check. A trust level is evidence, not proof that a camera produced the pixels.
  • The signed record proves something narrower: the photos, their order and their trust levels have not changed since the seller confirmed them.
  • A match means a similar photo was registered before. It can indicate image reuse; it is not, by itself, proof of who owns the photo, of fraud or of wrongdoing. Treat it as a cue for a person to review.
  • Matching compares submitted photos against photos taken with the PixelTrace camera and published inside this shop. Its photos are never shared with, or matched for, any other shop. PixelTrace will not detect photos copied from elsewhere. A result of no_match does not prove a photo is original.
  • For captures, send ?marketplaceId=<id> on POST /api/v1/pixel-trace/captures and every API-key call for the group. Camera links keep its shop. Hosted embeds are not available yet.
  • A test key and a live key never see each other's groups or matches.

How you can use it

Where PixelTrace fits
Use caseHow PixelTrace helps
Shops and classifiedsThe seller takes the listing photos on their phone, so buyers see photos taken now. Your server also checks photos against your earlier listings, so a stolen or reused photo goes to a moderator.
Resale and second hand (phones, watches, clothes, handbags)Condition photos taken now, with a certificate code buyers can open. A photo that already sits on another of your listings is found.
Car dealersWalk-around photos taken at the lot, on the day the advert goes live, with a certificate on the advert. An old advert's photo reused on a new one is found.
Insurance claimsThe claimant takes photos of the damaged item now, on their own phone, and you keep a signed record of the group. A photo that was already used in an earlier claim of yours is found.
Rentals and holiday letsCheck-in and check-out condition photos, each group with its own code and time. Hosts can also take their listing photos this way.
Stopping stolen photosSend any photo to the check address before a listing goes live. If it matches one you published, a person looks at both side by side.

Before you start

  • An API key (a secret password your server sends with each request) with the "Take and check photos with PixelTrace" permission (pixel-trace). Test keys take the permissions you tick, so tick that one. Read API keys and permissions first.
  • Use a test key while you build. Its groups are separate from live ones and spend no credits. A live key spends credits when you start a group or check a photo, and requires a live key activated by you on the API keys page.
  • PixelTrace must be on for your account (it is on by default). While it is off, starting a group or checking a photo is refused with PIXEL_TRACE_TURNED_OFF.
  • Your server makes every call. Never put the key in a web page or a mobile app.
  • A way to give the seller the camera link: a QR code (a square picture a phone scans) on a computer screen, or the link in a message or email. Nothing for the camera itself needs building: PCIFIC hosts it, in Safari on iPhone and Chrome on Android.
  • Settings you may want to set first (listed next).

Set these on the dashboard, or with a test key that has the settings permission. The Shop configuration page has the full tables.

  • minPhotos: how many photos a seller must take before they can confirm (1 to 12, default 1).
  • captureMinutes: how long the seller has once they open the link (5 to 120, default 30).
  • openWithinMinutes: how long the link waits to be opened (5 to 10,080, default 15 minutes for live listings).
  • For do-it-later links, use a test key with the settings permission to PUT {"openWithinMinutes": 1440} to /api/v1/pixel-trace/settings?marketplaceId=<shop id> for one day. Any whole number from 5 to 10080 is allowed. The saved shop setting applies to new links. Existing saved lifetimes stay in place. The photo session still lasts 30 minutes by default, and confirmed groups must still be published within 1 day.
  • photoSize: the longest side of each photo in pixels (1080, 1440, 1920 or 2560, default 1440).
  • keepPhotos: true keeps photo files until you retract the group. false deletes the files when you publish and keeps only fingerprints, hashes and the checks (default true).
  • publicLevels: which match levels the public certificate may show (none by default, so a certificate never says a photo was used before unless you choose).
  • codePrefix: the 2 to 5 letters your codes start with (PCF by default).
  • enabled: PixelTrace on or off (default on). While off, new groups and checks are refused.

How it works

A photo group, from start to certificate
  1. Your server starts a groupPOST /api/v1/pixel-trace/captures with your listing's id. The answer (201) has the group's id, its public code and the cameraUrl.
  2. You give the seller the camera linkShow it as a QR code or send it as a link. It opens on one phone only, and waits 15 minutes by default (openWithinMinutes) to be opened. To carry on with another phone, open the same link there and type the six-character code shown under "Switch phone" on the first phone; the first phone then stops working.
  3. The seller takes the photosOn their phone, in PCIFIC's camera page. Each photo is checked, cleaned of hidden details and stored while they take the next one. They can retry or delete a photo.
  4. The seller confirmsThey put the photos in order and confirm. The group becomes ready and PCIFIC signs a record of it. The link stops working.
  5. Your server reads the group until it is readyGET /api/v1/pixel-trace/captures/{id} every few seconds until status is ready. Each photo shows its trust level and its checks.
  6. You publish it when the listing is livePOST .../complete. Each photo is compared with your earlier published photos and the group gets its public certificate and badge.
  7. Buyers see the certificateLink the badge image to the certificateUrl on the listing page. If the listing comes down, retract the group.

A group's status moves capturing, ready, completed and, if you take it back, retracted. A capturing group can also move straight to retracted when cancelled. A group that is never confirmed, or confirmed and never published, is deleted when its time runs out.

Group statuses
StatusWhat it meansWhat happens next
capturingThe camera link is out. The seller is taking photos, or has not opened the link yet.If nobody confirms before expiresAt, the group is deleted.
readyThe seller confirmed. The record of the photos is signed.Publish it within a day, or it is deleted.
completedYou published it. Photos were compared and the certificate is public.Stays until you retract it.
retractedThe seller cancelled it or you took it back. Fingerprints and photo files are deleted.The certificate stays and says it was retracted.
What your seller sees on their phone
  1. Opens the linkOn a computer, the page shows a QR code to scan with the phone. On a phone it says "Take your photos on this phone" and asks them to tap Start taking photos.
  2. Allows motion (optional)The phone may ask to share its motion sensors. Tapping Allow lets the two motion checks run. Photos still count without it, and may then be normal instead of strong.
  3. Takes the photosThey press the shutter in the camera page. A photo that did not send shows Retry. They can remove a photo they do not want and move photos earlier or later.
  4. ConfirmsThey put the photos in order and confirm. The page shows the group's code. They go back to your shop to finish the listing.
  5. Switches browser (only if needed)If the link was opened inside a chat app, the page shows a six-character code under "Switch phone". Typing it in Safari or Chrome moves the group there with its photos.
Checking one photo (no group needed)
  1. Your server sends the photoPOST /api/v1/pixel-trace/check with the photo's bytes as the body and an image Content-Type. No JSON, no base64.
  2. PixelTrace fingerprints itIt looks at the picture, not the file name. Nothing is kept: the photo is fingerprinted, looked up and dropped.
  3. It looks in your published photosOnly photos published inside the selected shop, and only of the same kind of key (test or live). Other shops in the same business are not searched. A group that is not published yet is not searched.
  4. You get a level and the matcheslevel, message, up to 10 matches and searched. A person decides what a match means.

Quickstart

Every call needs your key in the Authorization header. These examples use a test key kept in $PCIFIC_TEST_KEY.

Step 1: start a group

Start a group
curl -X POST https://business.pcific.ai/api/v1/pixel-trace/captures \
  -H "Authorization: Bearer $PCIFIC_TEST_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"listingId":"listing-123","listingTitle":"Blue denim jacket"}'
The answer (201)
{
  "id": "7d1c5e0a-3b64-4f43-9d71-2f5a9c0e8b11",
  "status": "capturing",
  "code": "PCF-IMG-K7M2QX-R4TN9B",
  "cameraUrl": "https://business.pcific.ai/pixel-trace/capture?c=7d1c5e0a-3b64-4f43-9d71-2f5a9c0e8b11#t=<the ticket>",
  "expiresAt": "2026-10-20T13:55:02.118203Z",
  "captureMinutes": 30,
  "minPhotos": 1,
  "maxPhotos": 12
}

Send the seller cameraUrl. Keep id: you need it to read, publish and retract the group. The code is already final, so you can store it now. expiresAt is when the link stops working if nobody opens it. Opening it starts the seller's own captureMinutes.

Step 2: wait for the seller

Read the group every few seconds
curl -X GET https://business.pcific.ai/api/v1/pixel-trace/captures/7d1c5e0a-3b64-4f43-9d71-2f5a9c0e8b11 \
  -H "Authorization: Bearer $PCIFIC_TEST_KEY"
The answer once the seller confirmed (200, shortened)
{
  "id": "7d1c5e0a-3b64-4f43-9d71-2f5a9c0e8b11",
  "status": "ready",
  "code": "PCF-IMG-K7M2QX-R4TN9B",
  "listingId": "listing-123",
  "listingTitle": "Blue denim jacket",
  "test": true,
  "demo": false,
  "createdAt": "2026-10-19T13:55:02.118203Z",
  "expiresAt": "2026-10-20T14:02:11.482913Z",
  "sealedAt": "2026-10-19T14:02:11.482913Z",
  "publishedAt": null,
  "certificateUrl": null,
  "badgeUrl": null,
  "camera": {
    "opened": true,
    "openedAt": "2026-10-19T13:58:40.907112Z",
    "device": {
      "userAgent": "Mozilla/5.0 (iPhone; ...)",
      "touchPoints": 5,
      "coarsePointer": true
    },
    "refusedOpens": 0
  },
  "trust": {
    "strong": 0,
    "normal": 1,
    "weak": 0
  },
  "photos": [
    {
      "id": "0b6f3a52-91c8-4d0e-a3f4-6c21d8e7b9a0",
      "position": 0,
      "width": 1440,
      "height": 1080,
      "bytes": 412331,
      "sha256": "9f2b6c1e0d4a7385b1c9e2f06a4d83715bc0e9d2a64f1837c5b09e2d4a6f1c83",
      "trust": "normal",
      "checks": [
        {
          "check": "real_tap",
          "outcome": "pass",
          "detail": "The shutter was pressed by a finger on the screen (contact 14 by 14)."
        },
        {
          "check": "phone",
          "outcome": "pass",
          "detail": "The camera page ran in a phone browser with a touch screen."
        }
      ],
      "matches": null,
      "files": {
        "preview": "https://files.example/preview?signature=...",
        "photo": "https://files.example/photo.jpg?signature=..."
      }
    }
  ],
  "manifest": "{\"version\":1,\"test\":true,\"code\":\"PCF-IMG-K7M2QX-R4TN9B\",\"group\":\"7d1c5e0a-3b64-4f43-9d71-2f5a9c0e8b11\",\"listingId\":\"listing-123\",\"sealedAt\":\"2026-10-19T14:02:11.482913+00:00\",\"photos\":[{\"id\":\"0b6f3a52-91c8-4d0e-a3f4-6c21d8e7b9a0\",\"position\":0,\"sha256\":\"9f2b6c1e0d4a7385b1c9e2f06a4d83715bc0e9d2a64f1837c5b09e2d4a6f1c83\",\"trust\":\"normal\"}]}",
  "signature": "Qm9n...base64url...",
  "keyId": "test"
}

The example is shortened: a real photo lists all eight checks, and the file links are long. While status is capturing, the photos listed so far are the ones saved. Do not publish before status is ready. photos[].files.photo is a link to the stored JPEG that works for 10 minutes, so you can download it and compare its hash with sha256.

Step 3: publish when the listing is live

Publish the group
curl -X POST https://business.pcific.ai/api/v1/pixel-trace/captures/7d1c5e0a-3b64-4f43-9d71-2f5a9c0e8b11/complete \
  -H "Authorization: Bearer $PCIFIC_TEST_KEY" \
  -H "Content-Type: application/json" \
  -d '{"marketplaceName": "Bramble", "listingUrl": "https://bramble.example/listing-123"}'
The answer (200, shortened)
{
  "id": "7d1c5e0a-3b64-4f43-9d71-2f5a9c0e8b11",
  "status": "completed",
  "code": "PCF-IMG-K7M2QX-R4TN9B",
  "listingId": "listing-123",
  "listingTitle": "Blue denim jacket",
  "test": true,
  "demo": false,
  "createdAt": "2026-10-19T13:55:02.118203Z",
  "expiresAt": null,
  "sealedAt": "2026-10-19T14:02:11.482913Z",
  "publishedAt": "2026-10-19T14:20:45.330118Z",
  "certificateUrl": "https://business.pcific.ai/pixel-trace/certificates/PCF-IMG-K7M2QX-R4TN9B",
  "badgeUrl": "https://business.pcific.ai/api/v1/pixel-trace/certificates/PCF-IMG-K7M2QX-R4TN9B/badge.svg",
  "camera": {
    "opened": true,
    "openedAt": "2026-10-19T13:58:40.907112Z",
    "device": {
      "userAgent": "Mozilla/5.0 (iPhone; ...)",
      "touchPoints": 5,
      "coarsePointer": true
    },
    "refusedOpens": 0
  },
  "trust": {
    "strong": 0,
    "normal": 1,
    "weak": 0
  },
  "photos": [
    {
      "id": "0b6f3a52-91c8-4d0e-a3f4-6c21d8e7b9a0",
      "position": 0,
      "width": 1440,
      "height": 1080,
      "bytes": 412331,
      "sha256": "9f2b6c1e0d4a7385b1c9e2f06a4d83715bc0e9d2a64f1837c5b09e2d4a6f1c83",
      "trust": "normal",
      "checks": [
        {
          "check": "real_tap",
          "outcome": "pass",
          "detail": "The shutter was pressed by a finger on the screen (contact 14 by 14)."
        },
        {
          "check": "phone",
          "outcome": "pass",
          "detail": "The camera page ran in a phone browser with a touch screen."
        }
      ],
      "matches": {
        "level": "same_photo",
        "message": "This is the same photo as one published before.",
        "found": [
          {
            "level": "same_photo",
            "distance": 0,
            "code": "PCF-IMG-H3RWD8-N6VKA2",
            "photoId": "c41e7d90-5a2b-4e86-b0f3-8d19a6c2e754",
            "marketplaceName": "Bramble",
            "listingUrl": "https://bramble.example/listing-88",
            "preview": "https://files.example/preview?signature=..."
          }
        ]
      },
      "files": {
        "preview": "https://files.example/preview?signature=...",
        "photo": "https://files.example/photo.jpg?signature=..."
      }
    }
  ],
  "manifest": "{\"version\":1,\"test\":true,\"code\":\"PCF-IMG-K7M2QX-R4TN9B\",\"group\":\"7d1c5e0a-3b64-4f43-9d71-2f5a9c0e8b11\",\"listingId\":\"listing-123\",\"sealedAt\":\"2026-10-19T14:02:11.482913+00:00\",\"photos\":[{\"id\":\"0b6f3a52-91c8-4d0e-a3f4-6c21d8e7b9a0\",\"position\":0,\"sha256\":\"9f2b6c1e0d4a7385b1c9e2f06a4d83715bc0e9d2a64f1837c5b09e2d4a6f1c83\",\"trust\":\"normal\"}]}",
  "signature": "Qm9n...base64url...",
  "keyId": "test"
}

Here the photo matched one from an earlier listing. photos[].matches.level is the strongest match for that photo, and found lists up to 10 of them. Send the result to a person who looks at both photos. Publishing the same group again returns the same answer and finishes any photo that was not compared yet, so it is safe to retry. Send an Idempotency-Key header too.

Step 4: show the certificate

Put the badge on the listing page
<a href="https://business.pcific.ai/pixel-trace/certificates/PCF-IMG-K7M2QX-R4TN9B"><img src="https://business.pcific.ai/api/v1/pixel-trace/certificates/PCF-IMG-K7M2QX-R4TN9B/badge.svg" alt="PixelTrace submitted evidence"></a>
Anyone can read the certificate, with no key
curl https://business.pcific.ai/api/v1/pixel-trace/certificates/PCF-IMG-K7M2QX-R4TN9B

The certificate shows the listing, each photo's preview, trust level and checks, and the signed manifest. A match level appears on it only if the level is in your publicLevels setting (none are by default). A group made with a test key has a certificate too, and the page and the badge say it is a test. After a retraction, a previously published certificate says the group was retracted and its badge shows a cross. An unpublished group never gets a public certificate or badge.

Step 5: take a group back

Retract a group when the listing is removed
curl -X POST https://business.pcific.ai/api/v1/pixel-trace/captures/7d1c5e0a-3b64-4f43-9d71-2f5a9c0e8b11/retract \
  -H "Authorization: Bearer $PCIFIC_TEST_KEY"

Cancel a capturing group or take back a ready or published group with this call: its fingerprints leave the search, its photo files are deleted and status becomes retracted. Calling it again is safe. Its camera link immediately closes and refuses further photos with a cancellation message. Before confirming, the seller can also choose Cancel photo group below the camera page's photo controls. Starting a credit-billed live group is charged. Cancel or let it expire before any photo is accepted and processed by the server (checked, fingerprinted and stored), and the full creation charge is refunded. Once any photo was processed, or the group was confirmed, published or matched, there is no refund, even if all photos were deleted or the seller switched phones. The cancel response includes refunded (true/false) and refundReason in plain words. Test keys and unlimited accounts change no credits. Automatic refunds apply only to groups created after this fix; older live groups need PCIFIC support: contact support@pcific.co.uk with the group id for a refund review. Refunds restore the balance shown on Usage and GET /api/v1/usage, but original requests and gross spend still count toward rate limits, usage totals and spending limits.

Check one photo

Send the photo's bytes (not JSON)
curl -X POST https://business.pcific.ai/api/v1/pixel-trace/check \
  -H "Authorization: Bearer $PCIFIC_TEST_KEY" \
  -H "Content-Type: image/jpeg" \
  --data-binary @photo.jpg
A match (200)
{
  "level": "same_photo",
  "message": "This is the same photo as one published before.",
  "matches": [
    {
      "level": "same_photo",
      "distance": 0,
      "code": "PCF-IMG-H3RWD8-N6VKA2",
      "photoId": "c41e7d90-5a2b-4e86-b0f3-8d19a6c2e754",
      "marketplaceName": "Bramble",
      "listingUrl": "https://bramble.example/listing-88",
      "preview": "https://files.example/preview?signature=..."
    }
  ],
  "searched": "this shop only, same key kind (test or live)"
}
No match (200)
{
  "level": "no_match",
  "message": "No published photo matches this one.",
  "matches": [],
  "searched": "this shop only, same key kind (test or live)"
}

Set the Content-Type to image/jpeg, image/png, image/webp. curl's --data-binary alone sends a form content type, which makes the bytes unreadable on the way, so always add the header. With the Node fetch function, pass the file's bytes (a Buffer) as the body.

Verify the signed record

Test and live certificates use independent signing keys. Test key IDs are test and test-YYYY-MM-DD; production IDs are pixel-trace-1 and pixel-trace-YYYY-MM-DD. Both are published at the same JWKS address, with no shared key material. New signed manifests include test: true or test: false. For production, use the example with --production: it requires a production key and the signed test: false flag. For a test integration, use --test. Changing the outer test or keyId fields cannot change the signed environment.

Older certificates, including test certificates signed with a production key before this fix, keep their original signed text and signature. Their key stays published while the group exists, unless it leaks. Run the example without an environment option to check that legacy signature. It reports that there is no signed environment, so it confirms only who signed the text. Older records have no signed test flag and must be rejected for production use, even if the outer test field says false. Fetch the public certificate to see its test label, or create a new capture with the intended API key for a record with a signed environment. Existing test groups still expire 24 hours after they start.

When the seller confirms, PCIFIC signs the manifest with its private key (Ed25519 is the kind of signature). The group and the certificate both return three things: manifest (the exact signed text), signature (base64url, a URL-safe form of base64) and keyId. PCIFIC publishes the matching public key at https://business.pcific.ai/.well-known/jwks.json, as a JWKS (a list of public keys). Each key's x value is the key and its kid is its name, which a record carries as keyId: pixel-trace-1 for the first key, then pixel-trace- and the day a later key was added, like pixel-trace-2026-10-22. The newest key in the matching environment signs new records, and an older key stays in the list while records it signed are kept, so always pick the key by kid, never the first in the list. If a key ever leaks, PCIFIC stops publishing it and signs its records again with the newest key for each group's environment: read the group or certificate again for its new signature and keyId.

  • Take the manifest string exactly as returned. Do not parse it and write it out again: one changed space breaks the check.
  • Fetch the JWKS and pick the key whose kid equals keyId.
  • Check the signature (base64url) over the manifest's UTF-8 bytes with the Ed25519 key built from x.
  • A valid result means PCIFIC signed exactly this text, so the code, listing, photo order, file hashes and trust levels are as they were when the seller confirmed. It does not prove where the photos came from.
A complete verifier (Node 22, no packages). Save the group's JSON as group.json
// verify-pixeltrace.mjs. Run: node verify-pixeltrace.mjs group.json [--production|--test]
import { createPublicKey, verify } from "node:crypto";
import { readFile } from "node:fs/promises";

const group = JSON.parse(await readFile(process.argv[2], "utf8"));
const { keys } = await (await fetch("https://business.pcific.ai/.well-known/jwks.json")).json();
const jwk = keys.find((key) => key.kid === group.keyId);

if (!jwk) throw new Error("PCIFIC publishes no key called " + group.keyId + ". Fetch the certificate again for its current keyId and signature.");

const publicKey = createPublicKey({ key: jwk, format: "jwk" });
const signature = Buffer.from(group.signature, "base64url");
// The manifest is text. Check it exactly as it came, never parse it and write it again.
const signed = verify(null, Buffer.from(group.manifest, "utf8"), publicKey, signature);
const manifest = JSON.parse(group.manifest);
const testKey = jwk.kid === "test" || jwk.kid.startsWith("test-");
const mode = process.argv[3];
if (mode && !["--production", "--test"].includes(mode)) throw new Error("Unknown verification mode. Use --production for live records or --test for test records.");
const environmentMatches = mode === "--production" ? manifest.test === false && !testKey : mode === "--test" ? manifest.test === true && testKey : true;
const valid = signed && environmentMatches;

console.log(valid ? "Valid: PCIFIC signed exactly this manifest." : "NOT valid: do not trust this record. Fetch the certificate again and check its signature with the current published key.");
if (signed && !environmentMatches) console.log("Wrong signing environment for " + mode + ": the signing key and signed test flag on this certificate do not match this mode. Fetch a new certificate made with the intended API key.");
if (valid) console.log(manifest.test === true ? "Test certificate, never use as production evidence." : manifest.test === false && !testKey ? "Production certificate." : "Legacy signature only: no signed environment. Reject for production use.");
process.exitCode = valid ? 0 : 1;
Run it
curl https://business.pcific.ai/api/v1/pixel-trace/certificates/PCF-IMG-K7M2QX-R4TN9B > group.json
node verify-pixeltrace.mjs group.json

Request fields

Start a group: POST /api/v1/pixel-trace/captures
FieldTypeRequiredWhat it is
listingIdstringYesYour business's own listing id as text, not necessarily a UUID. After spaces at the ends are trimmed it must contain 1 to 120 characters.
listingTitlestringNoA title shown to the seller on the camera page and on the certificate. Longer than 120 characters is cut.
Publish a group: POST /api/v1/pixel-trace/captures/{id}/complete (optional body)
FieldTypeRequiredWhat it is
marketplaceNamestringNoYour shop's name, shown on the certificate and next to this group in later matches. Longer than 120 characters is cut.
listingUrlstringNoThe listing page, a full https:// address of up to 2,000 characters (a test key may use http://, including localhost). PCIFIC never opens this address: it only stores it and shows it as a link on the certificate and next to this group in later matches. Ask PCIFIC document and item lookup addresses must be public because PCIFIC fetches them. The whole body may be left out.
Check one photo: POST /api/v1/pixel-trace/check
FieldTypeRequiredWhat it is
(the request body)objectYesThe photo's raw bytes, not JSON and not base64. JPEG, PNG or WebP, up to 15 MB, at least 640 pixels on the longest side.

Reading a group (GET /api/v1/pixel-trace/captures/{id}) and retracting it (POST .../retract) take no body. Settings are changed with GET and PUT /api/v1/pixel-trace/settings, which needs a test key with the settings permission or the dashboard: a live key can read settings but never change them.

Response fields

Starting a group (201)
FieldTypeRequiredWhat it is
idstringYesThe group's id. Use it to read, publish and retract the group.
statusstringYesAlways capturing here. It then moves to ready, completed and, if taken back, retracted.
codestringYesThe group's public code, your code letters then IMG then two groups of six characters, for example PCF-IMG-K7M2QX-R4TN9B.
cameraUrlstringYesPCIFIC's camera page for this group. Send it to the seller. It opens on one phone only.
expiresAtstringYesWhen the link stops working if nobody opens it (an ISO 8601 date and time). Opening it moves this to captureMinutes later.
captureMinutesintegerYesHow long the seller has once they open the link.
minPhotosintegerYesPhotos the seller must take before they can confirm.
maxPhotosintegerYesThe most photos a group can hold, always 12.
A group: reading it, publishing it and retracting it (200)
FieldTypeRequiredWhat it is
idstringYesThe group's id.
statusstringYescapturing, ready, completed or retracted.
codestringYesThe public code, for example PCF-IMG-K7M2QX-R4TN9B.
listingId, listingTitlestringYesWhat you sent when you started the group. listingTitle is null if you sent none.
testbooleanYestrue when a test key made the group. Its certificate says it is a test.
demobooleanYesfalse for your groups. true only for PCIFIC's own demo.
createdAt, expiresAtstringYesISO 8601 dates and times. expiresAt is when the group is deleted if it is not finished: the link's end while capturing, a day after confirming while ready. It is null once published.
sealedAt, publishedAtstringYesWhen the seller confirmed and when you published. null until then.
certificateUrl, badgeUrlstringYesThe public certificate page and the badge image. null until the group is completed.
cameraobjectYesopened (true once a phone opened the link), openedAt, device (what the browser said about the phone) and refusedOpens (how many other devices tried to open the link after the first and were refused).
trustobjectYesHow many photos are strong, normal and weak.
photosobject[]YesIn the seller's order. Each has id, position, width, height, bytes, sha256 (of the stored file), trust, checks, matches and files.
photos[].checksobject[]YesThe eight checks. Each has check (its name), outcome (pass, fail or unknown) and detail (a sentence saying what was found).
photos[].matchesobjectYesnull until you publish. Then level (the strongest match), message, and found (up to 10 matches).
photos[].filesobjectYespreview and photo: links that work for 10 minutes. Both are null once the files are deleted.
manifest, signature, keyIdstringYesThe signed record. null until the seller confirms. manifest is the exact text that was signed.
A match, in photos[].matches.found and in the check answer
FieldTypeRequiredWhat it is
levelstringYessame_photo, likely_same or possibly_related.
distanceintegerYesHow many fingerprint bits differ. Smaller means closer. 0 is the same file.
codestringYesThe code of the earlier group that holds this photo.
photoIdstringYesThe earlier photo's id.
marketplaceName, listingUrlstringYesWhat you sent when you published the earlier group. null if you sent none.
previewstringNoA link (10 minutes) to the earlier photo's preview, so a person can look side by side. Left out if its files were deleted.
Checking one photo (200)
FieldTypeRequiredWhat it is
levelstringYesThe strongest match found: same_photo, likely_same, possibly_related or no_match.
messagestringYesA sentence you can show a reviewer.
matchesobject[]YesUp to 10 matches, strongest and closest first. Empty for no_match. Each has the fields in the match table.
searchedstringYesAlways "this shop only, same key kind (test or live)".
Match levels
levelWhat it meansWhat to do
same_photoThe same file, or the same picture shrunk or saved again.Very likely a copy. Show it to a person.
likely_sameThe same picture edited: cropped, turned, straightened or brightened.Probably a copy. Show it to a person.
possibly_relatedIt looks alike, for example another photo of the same item from the same spot.Worth a look. Not a finding.
no_matchNothing in your published photos is close.It does not prove the photo is original.

Each level comes from how close two photos' fingerprints are, so the same photo shrunk, cropped, turned, tilted or brightened is still found. Some edited copies are missed, and an unrelated photo can occasionally look similar, so a person always decides. A group is never matched with itself, and only published groups are searched.

The eight trust checks (in photos[].checks)
checkWhat a pass showsHow it can be faked
real_tapThe shutter was pressed by a finger on the touch screen, not by a script.A modified browser can report any tap.
phoneThe camera page ran in a phone or tablet browser with a touch screen.Desktop browser tools can pretend to be a phone.
camera_page_fileThe file has no camera app details (make, model, location). Photos made by the camera page never have them, so it was not taken in another app and uploaded.Anyone can remove those details from a photo.
live_cameraThe camera picture was live: it changed over time and arrived at 8 or more frames a second.A virtual camera program playing a video.
photo_from_cameraThe photo looks like what the live camera showed a moment before (75% alike or more).The same virtual camera showing a faked picture.
motion_sensorsThe phone's motion readings show the small shake of a hand. The seller has to allow motion for this one.A modified browser can make up readings.
real_cameraThe camera's name is not a program that pretends to be a camera (OBS Virtual Camera, ManyCam and similar).Renaming the program's camera.
motion_matches_pictureHow far the phone turned agrees with how far the picture moved. A picture that moves while the phone is still, or a phone that turns while the picture stays still, fails.The hardest to fake: it needs made-up sensor readings that agree with a made-up video.
  • strong: reserved for future independently attested captures. Browser-only evidence never receives this level.
  • normal: the highest level for browser-only submitted evidence, including when every check passed. Nothing failed, and at most one check could not be done. Many sellers do not allow motion. Without motion readings the two motion checks count as one check not done, so the photo can still be normal.
  • weak: any check failed, or more than one could not be done.
  • A weak photo is still saved and shown. The level is information for you, not a refusal.

Other things you can do

  • Read a group again at any time: GET /api/v1/pixel-trace/captures/{id}. Test keys see only test groups and live keys only live groups.
  • Publish again if an answer was lost: the same group returns the same answer.
  • Test without a phone: with a test key, upload JPEG, PNG or WebP photos to a test group with POST /api/v1/pixel-trace/captures/{id}/test-photos (the photo's bytes, Content-Type image/jpeg, image/png or image/webp), then confirm it with POST /api/v1/pixel-trace/captures/{id}/test-confirm. Each photo is marked weak with the check test_upload. A live key is refused, and a test key never reaches a live group. A business holds at most 200 test photos and 50 test groups at once; retracting a test group frees its room, and test groups are deleted 24 hours after they start.
  • Retract a group when its listing is removed: POST /api/v1/pixel-trace/captures/{id}/retract.
  • Read a public certificate: GET /api/v1/pixel-trace/certificates/{code}, in any letter case, with no key. The badge is at .../certificates/{code}/badge.svg.
  • Get the public keys: GET /.well-known/jwks.json, with no key. Fetch it again when a record names a keyId you have not seen.
  • Change how PixelTrace behaves: GET and PUT /api/v1/pixel-trace/settings. A "mode" setting no longer exists: sending anything but "isolated" is refused, so nobody believes photos are shared.
  • There is no route to download a photo from PCIFIC. A stored photo is the phone's own JPEG with its hidden details (camera, location, time) removed and PixelTrace's own record (the code and the certificate link) written in, not re-compressed and not encrypted. Use the 10 minute links in the group. Image tools that resize a photo often drop that record, which does not affect matching.

To try the test upload, set CAPTURE_ID to the id returned by Start a group. The PNG file must be 640 to 4096 pixels on its longest side and no more than 8 MB. Upload as many photos as your minPhotos setting requires, then confirm them in upload order.

Upload a test photo
curl -X POST "https://business.pcific.ai/api/v1/pixel-trace/captures/$CAPTURE_ID/test-photos" \
  -H "Authorization: Bearer $PCIFIC_TEST_KEY" \
  -H "Content-Type: image/png" \
  --data-binary @photo.png
Confirm the test group
curl -X POST "https://business.pcific.ai/api/v1/pixel-trace/captures/$CAPTURE_ID/test-confirm" \
  -H "Authorization: Bearer $PCIFIC_TEST_KEY"

Errors

Every error is JSON with error (what went wrong), code (a fixed name to branch on), tryThis (the next step) and sometimes problems (the exact fields at fault). A 4xx means fix the request. A 5xx means a problem on PCIFIC's side: send the same request again. The errors every address shares (UNAUTHORIZED, KEY_NOT_ALLOWED, RATE_LIMITED, BODY_TOO_LARGE, BACKEND_UNAVAILABLE and the rest) are on the Errors, limits and retries page. With a live key, starting a group and checking a photo can also be refused with OUT_OF_CREDITS or SPEND_LIMIT_REACHED. A key without the right permission is refused with KEY_NOT_ALLOWED: starting, reading, publishing, retracting and checking need pixel-trace, and settings need settings.

Most errors also have a docs link to their own section on PixelTrace errors, with the usual causes, how to fix it and a request that works. That page starts with the mistakes integrations make most often.

Orbit photo uploads and PixelTrace checks and camera uploads share a photo capacity limit per server: 16 requests and 128 MB of uploaded bytes, with at most 2 requests and 64 MB per business across its shops and keys. These limits include receiving and processing. Content-Length reserves bytes before the body is read; without it the call reserves its maximum body size. Actual streamed bytes are counted too. Uploads must arrive within 120 seconds and wait at most 20 seconds for a photo worker. Public demos use separate capacity: 2 requests, 16 MB and one photo worker. Demo traffic cannot take paid photo places. A busy refusal does not save photos. Wait Retry-After seconds before sending the same upload again.

Errors your server can get from PixelTrace
CodeHTTPWhy it happensHow to fix
PHOTO_UPLOAD_BUSINESS_BUSY429Your business has reached its photo request or byte capacity across Orbit and PixelTrace.Wait the 20 seconds in Retry-After, then send the photo upload again. Send fewer uploads at the same time.
PHOTO_UPLOAD_BUSY503The server's photo capacity is full, or a photo worker was not available within 20 seconds.Wait the 20 seconds in Retry-After, then send the photo upload again.
PHOTO_UPLOAD_TIMEOUT408The photo upload body did not finish arriving within 120 seconds.Check your connection, then send the photo upload again. Send fewer photos per upload if needed.
PIXEL_TRACE_TURNED_OFF403PixelTrace is switched off for this account (enabled is false). Groups already started carry on.Switch it on in the dashboard, or with a test key that has the settings permission send {"enabled": true} to PUT /api/v1/pixel-trace/settings.
PIXEL_TRACE_TOO_MANY_REQUESTS429More than 600 group starts and checks a minute for this account.Wait the number of seconds tryThis names (it is also in the Retry-After header), then send the request again.
INVALID_JSON400The body is not a JSON object.Send a JSON object with the header "Content-Type: application/json".
PIXEL_TRACE_LISTING_ID_INVALID400listingId is missing, empty, not text, or longer than 120 characters.Send your own id for the listing these photos are for, for example "listingId": "listing-123".
PIXEL_TRACE_LISTING_URL_INVALID400listingUrl is not a full https:// address (http:// only with a test key), or is over 2,000 characters.Send the listing page's address as buyers see it, starting https://, or leave listingUrl out.
NOT_FOUND404No group with this id in this shop for your kind of key (a test key reaches only test groups, a live key only live groups), the id is not a UUID, or the group expired and was deleted (its camera link ran out before the seller confirmed, or it was not published within a day of confirming).Check the id from POST /api/v1/pixel-trace/captures and use the same kind of key that started it. If the group was deleted, start a new one.
PIXEL_TRACE_NOT_CONFIRMED409The seller has not confirmed the group yet (status capturing), so it cannot be published.Wait until GET /api/v1/pixel-trace/captures/{id} shows status ready, then publish it.
PIXEL_TRACE_RETRACTED409The group was retracted, so it cannot be published.Start a new group with POST /api/v1/pixel-trace/captures.
PIXEL_TRACE_NO_PHOTO400The request body is empty.Send the photo's bytes as the request body with a Content-Type of image/jpeg, image/png or image/webp, for example curl --data-binary @photo.jpg -H "Content-Type: image/jpeg".
PIXEL_TRACE_CONTENT_TYPE415The Content-Type header for the check is missing or is not a supported image type.Send a JPEG, PNG or WebP photo with Content-Type: image/jpeg, image/png or image/webp, and the photo's bytes as the request body.
PIXEL_TRACE_PHOTO_REFUSED422The file is not a JPEG, PNG or WebP (HEIC is not accepted), is damaged or cut short, has fewer than 640 pixels on its longest side, is a JPEG over 60 megapixels, is a PNG or WebP over 25 megapixels, or is a CMYK or 16-bit JPEG. The message says which.Read the message, then send the photo as a JPEG, PNG or WebP within the size limits. A HEIC photo from an iPhone needs converting to JPEG first.
PIXEL_TRACE_TOO_LARGE413The photo is over the 15 MB limit for a PixelTrace check.Send one photo of 15 MB or less. Resize it or save it at a lower quality, then send it again.
PIXEL_TRACE_PHOTO_FAILED500Reading the photo failed on PCIFIC's side, not because of the photo.Send the photo again. If it keeps happening, contact PCIFIC support.
INVALID_SETTING400A setting has the wrong type or is out of range, or "mode" was sent with anything but "isolated". The message names it.Send the setting in the form the message shows. Remove "mode": there is nothing to switch on.
PIXEL_TRACE_PREFIX_RESERVED409codePrefix is kept for a brand, or for PCIFIC.Choose different letters, for example this business's initials.
PIXEL_TRACE_PREFIX_TAKEN409codePrefix is used, or was used, by another business.Choose different letters.
NOT_FOUND404No published or retracted group has this code.Check the code, for example PCF-IMG-ABCDEF-234567. A group shows here only once the shop has published it.
PIXEL_TRACE_TEST_KEY_ONLY403The call was made with a live key. Only a test key may add photos to a group or confirm it without the seller's phone.Use a test key to test your integration. For a live group, send the seller the cameraUrl so they take the photos on their phone.
PIXEL_TRACE_TEST_PHOTOS_FULL409The business already holds 200 test photos in its test groups that are not retracted, from uploads and phones together.Test photos are deleted 24 hours after their group starts. Retract a test group you no longer need with POST /api/v1/pixel-trace/captures/{id}/retract, or try again later.
PIXEL_TRACE_TEST_GROUPS_FULL409A test key was used, and the business already has 50 test groups that are not retracted.Retract test groups you no longer need with POST /api/v1/pixel-trace/captures/{id}/retract. Test groups are also deleted 24 hours after they start.
INTERNAL500Something went wrong on PCIFIC's side.Try again in a moment. If it keeps happening, contact PCIFIC support.

What your seller might see

These come from the camera page on the seller's phone, not from your server, and the page shows each one with its next step. They are listed so your support team knows what a seller means. Most are fixed by reloading the page or taking the photo again. If a seller is stuck, start a new group and send a new link.

Errors on the seller's phone
CodeHTTPWhy it happensHow to fix
PHOTO_UPLOAD_BUSINESS_BUSY429Your business has reached its photo request or byte capacity across Orbit and PixelTrace.Wait the 20 seconds in Retry-After, then send the photo upload again. Send fewer uploads at the same time.
PHOTO_UPLOAD_BUSY503The server's photo capacity is full, or a photo worker was not available within 20 seconds.Wait the 20 seconds in Retry-After, then send the photo upload again.
PHOTO_UPLOAD_TIMEOUT408The photo upload body did not finish arriving within 120 seconds.Check your connection, then send the photo upload again. Send fewer photos per upload if needed.
NOT_FOUND404This camera link does not exist, or has expired.Ask your shop for a new camera link, then open the whole link they send you.
INVALID_JSON400The camera page sent something that is not a JSON object.Reload the camera page. If it keeps happening, ask the shop for a new link.
PIXEL_TRACE_PHONE_ONLY403The browser is not on a phone or tablet.Scan the QR code with your phone's camera, or open the link on your phone.
PIXEL_TRACE_DEVICE_KEY_INVALID400The browser could not make its security key (deviceKey is not a P-256 public key), for example in a private window.Open the link in Safari on iPhone or Chrome on Android, and make sure it is not a private window.
PIXEL_TRACE_LINK_ALREADY_OPENED409Another browser already opened this link, and it works only there.To carry on here, type the six characters shown under "Switch phone" on the page where you first opened it (POST .../move). If that was not you, ask the shop for a new link.
PIXEL_TRACE_MOVE_CODE_WRONG403moveCode is not the code shown on the camera page where the link was first opened.Check the six characters under "Switch phone" on that page, and type them again.
PIXEL_TRACE_MOVE_LOCKED403Ten wrong move codes were typed for this camera link. Switching phones is locked for 15 minutes.Try the code shown under "Switch phone" on the first phone again at the UTC time given in the response. You can keep taking photos on that phone while you wait.
PIXEL_TRACE_CAMERA_NOT_OPENED409No camera cookie, or not the cookie of the phone that opened this link, or the seller already confirmed the group (the cookie is deleted then). The camera routes answer only the seller's phone browser that opened the camera link, never an API key on its own.Open the camera link again on the phone you are taking photos on. If you finished, your photos are saved: go back to the shop. From your own server, read the group with GET /api/v1/pixel-trace/captures/{captureId}, and with a test key add photos with POST .../test-photos and confirm with POST .../test-confirm.
PIXEL_TRACE_CAPTURE_CLOSED410The camera link expired, the group was cancelled or retracted, or the seller already confirmed the group.Ask the shop for a new link. If the photos were already confirmed, go back to the shop to finish the listing.
PIXEL_TRACE_SIGNATURE_INVALID403The signature was not made by the key of the phone the link is bound to.Reload the camera page and try again. If it keeps happening, open the camera link again on the phone you started on.
PIXEL_TRACE_SHOT_INVALID400The shutter press was sent without its id or signature (or the x-pixel-trace-shot header is missing or not a UUID).Reload the camera page and take the photo again.
PIXEL_TRACE_SHOT_INVALID403No unused shutter press in this group has this shot id and shot code.Take the photo with the camera page's shutter button.
PIXEL_TRACE_SHOT_USED409This shutter press was already used for a photo.Take the photo again. If the answer to a photo was lost, send the same photo again to get the saved one.
PIXEL_TRACE_SHOT_EXPIRED410The photo arrived more than 60 seconds after the shutter was pressed.Take the photo again. If your signal is weak, move somewhere with better signal.
PIXEL_TRACE_STILL_SENDING409Three other photos are still on their way to PixelTrace.Wait a moment for them to finish sending, then take the next photo.
PIXEL_TRACE_GROUP_FULL409The group already holds 12 photos.Delete a photo you do not need, then take the new one.
PIXEL_TRACE_UPLOAD_CUT_SHORT400The photo upload was cut short, so the form could not be read to the end.Check your phone's signal and tap Retry.
PIXEL_TRACE_UPLOAD_INCOMPLETE400The upload is missing the photo or its details.Reload the camera page and take the photo again.
PIXEL_TRACE_TOO_LARGE413The photo is over 8 MB, or its details are over 128 KB.Reload the camera page and take the photo again.
PIXEL_TRACE_EVIDENCE_INVALID400The camera page sent the photo's details in a form PixelTrace cannot read (not JSON, or too many live copies, frame times or motion readings).Reload the camera page and take the photo again.
PIXEL_TRACE_NOT_JPEG422The photo is not a JPEG, which is what the camera page makes.Take the photo with the camera page's shutter button.
PIXEL_TRACE_PHOTO_REFUSED422The photo is damaged, outside 640 to 4096 pixels on its longest side, over the pixel limit (60 megapixels for JPEG, 25 for PNG and WebP), or uses an unsupported colour format. The message says which.Read the message, then take the photo again with the camera page's shutter button.
PIXEL_TRACE_PHOTO_FAILED500Reading the photo failed on PCIFIC's side, not because of the photo.Send the photo again. If it keeps happening, contact PCIFIC support.
PIXEL_TRACE_STORAGE_FAILED502The photo could not be saved. This is a problem on PCIFIC's side.Tap Retry in a moment. If it keeps happening, contact the shop.
PIXEL_TRACE_SIGNING_KEY_UNAVAILABLE503The PixelTrace signing key on this server is no longer available.Your photos are still saved. Wait a minute and confirm again. If this keeps happening, contact PCIFIC support.
PIXEL_TRACE_CONFIRM_INVALID400photoIds is missing, or holds something that is not a UUID.Reload the camera page and tap confirm again.
PIXEL_TRACE_PHOTOS_CHANGED409photoIds is not exactly the photos saved in the group, each once.Reload the camera page, check your photos and confirm again.
PIXEL_TRACE_TOO_FEW_PHOTOS409The group has fewer photos than the shop's minPhotos setting.Take more photos of the item, then confirm.
NOT_FOUND404The photo is not in this group, or was already deleted.Reload the camera page to see the photos saved.
PIXEL_TRACE_TOO_MANY_REQUESTS429More than 240 camera calls a minute from this network.Wait the number of seconds tryThis names (it is also in the Retry-After header), then send the request again.

Limits

PixelTrace limits
WhatLimit
Photos in a group12 at most, and at least your minPhotos (1 by default).
A camera link waiting to be openedopenWithinMinutes, 15 minutes by default.
The seller's time once they open the linkcaptureMinutes, 30 minutes by default. Reloading the page does not restart it.
A confirmed group waiting to be published1 day. Then it is deleted.
Wrong codes when moving to another browser10 per link, then it can no longer move.
A camera photoA JPEG of up to 8 MB, from 640 to 4096 pixels on its longest side, up to 60 megapixels.
A shutter codeWorks once, for 60 seconds. At most 3 photos can be on their way at once.
A photo sent to the check addressAt least 640 pixels on the longest side, up to 15 MB. JPEG up to 60 megapixels, PNG or WebP up to 25 megapixels. HEIC is not accepted: convert it to JPEG first.
listingIdYour business's own listing id as text, not necessarily a UUID. After spaces at the ends are trimmed, 1 to 120 characters. listingTitle and marketplaceName are cut at 120.
listingUrlUp to 2,000 characters, https:// (a test key may use http://).
Links to photo filesWork for 10 minutes. Read the group again for new ones.
Matches per photo10 at most.
Starting groups and checking photos, per account600 a minute across all keys (PIXEL_TRACE_TOO_MANY_REQUESTS). Photo checks have their own 600-per-minute key allowance. Group starts still share the 120-per-minute work allowance with other tools.
Photo-check requests, per key600 a minute (RATE_LIMITED), separate from AI work starts. Invalid photos also count. One key can use all 600 account requests for checks when no groups are started.
Camera calls, per network240 a minute. 20 links opened a minute.
Shutter presses and uploads, per group40 a minute each.
Reading certificates, per network120 a minute.
Badge images, per network600 a minute. Browsers keep a badge for 5 minutes.
Time the website waits for PCIFICUp to 60 seconds for a photo check, publishing and camera uploads, 15 seconds for the rest.

Words used on this page

Words
WordMeaning
groupThe photos of one listing, taken together. It has an id and a public code.
camera linkThe address of PCIFIC's camera page for one group. It opens on one phone (the first one to open it).
QR codeA square picture a phone camera scans to open a link. Show the camera link as one on a computer screen.
trust levelstrong, normal or weak, from eight checks of how a photo was taken. Evidence, not proof.
manifestThe signed record of a group: its code, its listing, when it was confirmed, and each photo's id, order, file hash and trust level.
signatureA value only PCIFIC's secret key can make for exactly this manifest. Anyone can check it with the public key.
JWKS (JSON Web Key Set)A list of public keys, here every key that checks PixelTrace signatures, at /.well-known/jwks.json.
Ed25519The kind of signature used. Node can check it with no extra package.
SHA-256 hash (sha256)A fingerprint of a file's exact bytes. Change one byte and the hash changes.
fingerprintA short number made from how a picture looks, so a shrunk, cropped or brightened copy still lands close to the original.
publishCalling complete once the listing is live. It compares the photos and opens the public certificate.
retractTaking a group back. Its fingerprints and photo files are deleted and its certificate says it was retracted.
certificateThe public page for a code: the listing, each photo's preview and trust level, and the signed manifest.
idempotency key (a header that makes a retry safe)Send Idempotency-Key on every POST, PUT and DELETE, including photo checks and camera actions, so a retry after a timeout does not repeat work or credits. See Errors, limits and retries.
test key and live keyA test key only sees test groups, which match only other test groups, spend no credits, get a certificate marked as a test and are deleted 24 hours after they start. A live key only sees live groups and spends credits.