> ## Documentation Index
> Fetch the complete documentation index at: https://docs.peaq.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# POST /v1/verify/chip/evidence

> Submit signed chip evidence for a Verify challenge and get an intake receipt.

## Endpoint

```http theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
POST /v1/verify/chip/evidence
```

The submission step of [chip verification](/peaqos/functions/verify#verify-a-chip-end-to-end). Takes the `evidence.json` that [`peaqos verify chip finalize`](/peaqos/cli#peaqos-verify-chip) (or the SDK) built from a [challenge](/peaqos/api-reference/post-verify-chip-challenge), checks it, and consumes the challenge.

The server rebuilds the machine context from the chain (machine ID, DID, current DID controller, chain ID) and checks that the leaf certificate chains to the Infineon CA306 intermediate and the pinned Infineon root, that the chip signature verifies under the certificate's key, that the controller signature recovers to the current DID controller, and that every fixed field and derived hash matches. The token authenticates the submitting service; it replaces neither proof.

<Warning>
  The route requires peaq's onboarding token (`Authorization: Bearer <token>`). Without a valid token every request answers `401 ONBOARDING_AUTH_REQUIRED`, before the body is read.
</Warning>

## Headers

| Header | Value |
| :- | :- |
| `Authorization` | Exactly one `Bearer <onboarding token>` |
| `Content-Type` | `application/json`, optionally with `charset=utf-8` |
| `Accept` | Omit, or a range that accepts `application/json` |
| `Content-Encoding` | Must be absent |

## Request body

The body is the evidence file, byte for byte: RFC 8785 canonical JSON of a `peaq.verify.chip-evidence/1` object, at most 16,384 bytes. Send the file as written (`curl --data-binary @evidence.json`). Do not pretty-print, reserialize, wrap it in another object or add fields; the server rejects any byte that differs from the canonical form.

| Object | Members |
| :- | :- |
| Root | `certificate`, `chipRef`, `controllerProof`, `evidenceSchema`, `profile`, `proof`, `revocationStatus`, `transcript`, `trustBundle` |
| `certificate` | `fingerprintSha256`, `leafDerBase64url`, `publicKey` |
| `controllerProof` | `scheme`, `signature` |
| `proof` | `chipSignature` |
| `transcript` | The nine fields of the challenge response plus `certificateFingerprintSha256` |

Every scalar value is a string; `certificate`, `controllerProof`, `proof` and `transcript` are objects. Fixed values: `evidenceSchema` is `peaq.verify.chip-evidence/1`, `profile` is `infineon-optiga-trust-m-express-ca306/1`, `trustBundle` is `infineon-optiga-trust-m-express-ca306-roots/1`, `controllerProof.scheme` is `eip191-secp256k1` and `revocationStatus` is `not_evaluated`. Missing, unknown or `null` members return an error.

## Response

**202 Accepted**, `Content-Type: application/json; charset=utf-8`, `Cache-Control: no-store`.

```json theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
{ "receiptId": "4f05bf79-4f69-41b2-a21d-fc833d44f159", "status": "accepted" }
```

`accepted` means the evidence passed every check, the challenge is consumed and the evidence is stored for attestation. It is not a verified status and not an on-chain record, and there is no route to look up a receipt. The machine's chip status reads `verified` on [`GET /v1/verify/machines/{machineId}`](/peaqos/api-reference/get-verify-machine) once peaq records the chip attestation in the `AttestationRegistry`.

## Error responses

Errors use the coded envelope `{ "detail": { "code": "...", "message": "..." } }`.

| Status | `code` | Condition |
| :- | :- | :- |
| 400 | `INVALID_REQUEST` | Wrong headers, body over 16,384 bytes, invalid or non-canonical JSON, or a missing, extra or wrongly typed member. The challenge is not consumed |
| 400 | `EVIDENCE_REJECTED` | A check failed: certificate chain, chip signature, controller signature, a wrong fixed value (such as `evidenceSchema`), or the machine context changed since the challenge (for example a new DID controller). Final for this challenge |
| 401 | `ONBOARDING_AUTH_REQUIRED` | Missing, malformed, repeated or invalid token |
| 404 | `CHALLENGE_NOT_FOUND` | No challenge with this nonce exists: it was never issued, or it expired unused and was cleaned up |
| 404 | `VERIFY_ROUTE_NOT_FOUND` | Unknown path under `/v1/verify/` |
| 405 | `METHOD_NOT_ALLOWED` | Any method other than `POST` |
| 406 | `NOT_ACCEPTABLE` | `Accept` excludes JSON |
| 409 | `CHALLENGE_EXPIRED` | The challenge expired before it was consumed |
| 409 | `NONCE_REPLAY` | Different evidence for a challenge that already has a submission |
| 409 | `SUBMISSION_IN_PROGRESS` | The same evidence is being checked right now. `Retry-After` gives the seconds to wait (1 to 120) |
| 413 | `REQUEST_TOO_LARGE` | Rejected as too large before parsing |
| 429 | `RATE_LIMITED` | Per-IP limit for this route, or the API-wide per-IP limit |
| 500 | `INTERNAL_ERROR` | Unhandled server error |
| 503 | `CHAIN_UNAVAILABLE` | The machine context could not be read from the chain. Retry the same file |
| 503 | `VERIFY_STORE_UNAVAILABLE` | The submission could not be stored. Retry the same file |
| 503 | `VERIFY_CLOCK_INVALID` | The server clock is invalid |

Branch on `code`, never on `message`. Errors never echo the token, the evidence or any identifier.

## Retries

Each challenge takes one evidence file. Sending the identical bytes again is safe:

* After `202`, the same bytes return the same receipt, even after the challenge has expired.
* After `400 EVIDENCE_REJECTED`, the same bytes return the same error, and after `409 CHALLENGE_EXPIRED` the challenge can no longer be used. In both cases, and after `404 CHALLENGE_NOT_FOUND`, start over with a new challenge.
* After a `503`, retry the same bytes. Once the server has recorded a submission for a challenge, a different file for it returns `409 NONCE_REPLAY`.

## Example

```bash theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
curl --request POST "https://mcr.peaq.xyz/v1/verify/chip/evidence" \
  --header "Authorization: Bearer $VERIFY_ONBOARDING_TOKEN" \
  --header "Content-Type: application/json" \
  --header "Accept: application/json" \
  --data-binary @evidence.json
```

## Related endpoints

* [POST /v1/verify/chip/challenge](/peaqos/api-reference/post-verify-chip-challenge) issues the challenge this evidence answers.
* [GET /v1/verify/machines/\{machineId}](/peaqos/api-reference/get-verify-machine) reads the machine's chip status.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.