# Certification — Overview

**Certification** is the process by which one or more digital files are cryptographically certified to attest:

- their **existence** at a given time (timestamp),
- their **integrity** (files have not been altered after certification),
- their **provenance** (the user who performed the certification).


The result is a set of digitally signed artifacts that constitute proof of certification.

## The two modes

The Public API offers **two modes** to create a certification, depending on how files are provided:

### Hash certification

The client sends a list of **file names and hashes** (SHA-256) already computed. TrueScreen certifies the hashes without receiving the original files.

- **Endpoint:** `POST /v1/hash-certifications`
- **Calls required:** 1
- **Security level:** lower — the system cannot verify that the hashes correspond to real files.
- **Cost:** **1 credit per hash** sent.


### File certification

The client **uploads the files** via temporary upload URLs. TrueScreen receives the original files, computes their hashes, and performs the certification.

- **Endpoint:** `POST /v1/file-certifications-attachments` + upload + `POST /v1/file-certifications`
- **Calls required:** 3 (file registration → upload → certification creation)
- **Security level:** higher — original files are processed by the system.
- **Cost:** **1 credit per file** uploaded.


On each `files` item in **`POST /v1/file-certifications-attachments`**, **`creation_datetime`** is optional (ISO 8601 `date-time`, same object as `file_name`). When present and valid, it is used as creation date in **jsonData** for that attachment. See [Certification call flow](/certification-workflow#2-file-certification).

### Quick comparison

| Aspect | Hash certification | File certification |
|  --- | --- | --- |
| **Input** | File names + hash (SHA-256) | Files to upload |
| **File upload** | No | Yes (presigned URL) |
| **API calls** | 1 | 3 |
| **Security** | Lower | Higher |
| **Credit cost** | 1 per hash | 1 per file |


## Certification through MCP

TrueScreen also exposes certification workflows through MCP.

- `truescreen_create_hash_certification`, `truescreen_get_certification`, and `truescreen_wait_for_certification` are available on both the **remote** and **local** MCP server.
- File certification is available only on the **local** MCP server through `truescreen_create_file_certification_attachments`, `truescreen_upload_file`, and `truescreen_create_file_certification`.


See [MCP integration](/mcp-integration) to choose the right server and install it.

## Produced artifacts

When certification completes, the system produces three types of files:

| Artifact | Format | Readability | Description |
|  --- | --- | --- | --- |
| **jsonData** | JSON | Machine-readable | Hashes of certified files, file metadata, and user metadata. Contains all information needed to verify integrity. |
| **PDF report** (optional) | PDF | Human-readable | Readable report with key data from jsonData. Useful for direct consultation (lawyers, auditors, etc.). Generated only if enabled in configuration. |
| **Signed XML** | XML + XAdES | Both | Contains hashes of jsonData and, when present, of the PDF report. Digitally signed and timestamped. This is what gives probative value to the certification. |


The **signed XML** guarantees:

- **Integrity** — any change to jsonData or the PDF report (when present) invalidates the signature.
- **Authenticity** — the digital signature attests that the certification was issued by the TrueScreen system.
- **Certain date** — the timestamp proves that the data existed at the time of certification.


## Asynchronous process

Certification generation is **asynchronous**: the creation response returns `status: "pending"` and a `report_id`. Completion happens later.

You have **two options** to know when the certification is ready:

### Webhook

Pass a **`webhook_url`** in the creation request body. When processing **finishes** (success or failure), TrueScreen sends an **HTTP POST** callback to that URL.

The callback payload follows the **[Standard Webhooks](https://www.standardwebhooks.com)** envelope format — a JSON object with three top-level fields:

| Field | Type | Description |
|  --- | --- | --- |
| `type` | string | Event type: `certification.completed` or `certification.error` |
| `timestamp` | string | ISO 8601 timestamp of when the event occurred |
| `data` | object | Event payload (see below) |


- **`certification.completed`** — `data` matches the **200** `GET /v1/certifications/{reportId}` response (`status: "completed"`, `files` array with signed URLs).
- **`certification.error`** — `data` contains an **`application/problem+json`** (RFC 9457) document with the same shape as the error from that `GET`.


The `Content-Type` is always `application/json`; distinguish success from failure via the `type` field.

#### Signature verification

Every callback includes three **Standard Webhooks** headers for signature verification:

| Header | Description |
|  --- | --- |
| `webhook-id` | Unique event identifier (idempotency key) |
| `webhook-timestamp` | Unix timestamp (seconds since epoch) of the delivery attempt |
| `webhook-signature` | HMAC-SHA256 signature(s) in format `v1,<base64>` |


The signature is computed over `{webhook-id}.{webhook-timestamp}.{raw_body}` using a **webhook signing secret** — a dedicated key (prefixed `whsec_`) separate from your API key, obtained from the TrueScreen portal. To verify:

1. Reconstruct the signed content: `"{webhook-id}.{webhook-timestamp}.{body}"`
2. Compute `HMAC-SHA256` with your decoded signing secret
3. Compare (constant-time) against each `v1,...` signature in the header
4. Reject if `|now - webhook-timestamp| > 300s` (replay protection)


### Polling

Poll **`GET /v1/certifications/{reportId}`** periodically using the `report_id` from the creation response. When the certification is complete, the response is **200** with `status: "completed"` and the `files` array with signed URLs. If async processing fails, the API returns an **error status code** and **`application/problem+json`**—see OpenAPI and [Certification call flow](/certification-workflow).

## Additional metadata

In both creation endpoints you can pass an optional **`metadata`** field: a free-form key-value object with custom data (e.g. case number, client name, contract reference).

Metadata keys and values are included in **jsonData** and, when generated, in the **PDF report**.

Example:


```json
{
  "metadata": {
    "case_number": "2024/001",
    "client_name": "John Doe",
    "contract_ref": "CTR-20240315"
  }
}
```

## Credits

Each certification has a cost in **credits** (units purchasable from the TrueScreen portal).

| Mode | Cost |
|  --- | --- |
| **Hash certification** | 1 credit per hash sent |
| **File certification** | 1 credit per file uploaded |


Credits are **deducted at creation time**, before asynchronous processing starts. If the credit balance is insufficient, the request is rejected with an error and no credits are deducted.

You can check the balance at any time with **`GET /v1/credits`**:


```json
{
  "purchased": 100,
  "used": 35,
  "available": 65,
  "expires_at": "2026-12-31"
}
```

## References

- [Certification call flow](/certification-workflow) — Operational guide with API call sequences
- [API errors](/errors) — RFC 9457 format, code list, and detail pages for each error type
- [OpenAPI spec](/openapi) — Technical reference for endpoints