# Certification call flow

This guide describes how to create a certification via the Public API. You have **two modes** available:

1. **Hash certification** — A single call: you send file names and pre-computed SHA-256 hashes. TrueScreen certifies the hashes without receiving the original files.
2. **File certification** — Three calls in sequence: register the files, upload them to temporary URLs, then start the certification. TrueScreen receives the original files and computes their hashes.


For basic concepts (produced artifacts, asynchronous process, credits, metadata), see the [certification overview](/certification-overview).

## Quick Reference

| Scenario | Calls |
|  --- | --- |
| [Hash certification](#1-hash-certification) | `POST /v1/hash-certifications` |
| [File certification](#2-file-certification) | `POST /v1/file-certifications-attachments` → `PUT upload_url` → `POST /v1/file-certifications` |
| [Check status](#3-checking-certification-status) | `GET /v1/certifications/{reportId}` |


In all cases requests must include [authentication](/#authentication) with an API key.

## Certification through MCP

The same certification flows are available through MCP with curated tools instead of raw HTTP calls.

- On both MCP servers you can use `truescreen_create_hash_certification`, `truescreen_get_certification`, and `truescreen_wait_for_certification`.
- File certification is available only on the local MCP server, which also exposes `truescreen_create_file_certification_attachments`, `truescreen_upload_file`, and `truescreen_create_file_certification`.


See [MCP integration](/mcp-integration) for installation and channel selection.

## Use cases

### 1. Hash certification

You already have the files and their SHA-256 hashes. You want to certify that those hashes existed at a given time, without uploading the original files.

**Endpoint:** `POST /v1/hash-certifications`

**Body:**


```json
{
  "title": "Project Alpha documents certification",
  "files": [
    {
      "file_name": "contract.pdf",
      "hash": "2661f88efc456652aa9f65f6340fe0213e5bde437e3c613b2a235de81581161e"
    },
    {
      "file_name": "technical-attachment.pdf",
      "hash": "5c5ec4792053e87788d0be3f6c31c77f7e48e02466407da5c16ac1962a00e368"
    }
  ],
  "webhook_url": "https://example.com/webhook/certification",
  "generate_pdf_report": true,
  "metadata": {
    "case_number": "2024/001",
    "client_name": "John Doe"
  }
}
```

| Field | Required | Description |
|  --- | --- | --- |
| `title` | yes | Certification title |
| `files` | yes | Array of objects with `file_name` and `hash` (SHA-256, 64 hex characters) |
| `webhook_url` | no | URL for callback on completion |
| `generate_pdf_report` | no | Whether to generate a PDF report (defaults to `true`) |
| `metadata` | no | Key-value object with custom data to include in jsonData and, when generated, in the PDF report |


**Response (201 Created):**


```json
{
  "report_id": "d8c2aef3-72a7-4a5f-b0e7-4308a88c6cff",
  "status": "pending",
  "credits_amount": 2,
  "title": "Project Alpha documents certification",
  "created_at": "2026-03-06T14:30:00Z"
}
```

- **`report_id`** — Unique identifier of the certification. Use it to check status with `GET /v1/certifications/{reportId}`.
- **`status`** — Initial status `"pending"`: certification is being processed asynchronously.
- **`credits_amount`** — Credits consumed: 1 per hash sent (in this example, 2 hashes = 2 credits).


### 2. File certification

You want to upload the original files so that TrueScreen computes their hashes and certifies them. The process requires **three steps** in sequence.

#### Step 1 — Register files and get upload URLs

**Endpoint:** `POST /v1/file-certifications-attachments`

**Body:**


```json
{
  "files": [
    { "file_name": "contract.pdf" },
    {
      "file_name": "site-inspection-photo.jpg",
      "creation_datetime": "2026-04-08T14:30:00.000Z"
    }
  ]
}
```

| Field | Required | Description |
|  --- | --- | --- |
| `files` | yes | Non-empty array. |
| `files[].file_name` | yes | File name. |
| `files[].creation_datetime` | no | ISO 8601 `date-time` (not in the future). Optional: when present and valid, used as creation date in jsonData for that attachment. |


**Response (201 Created):**


```json
[
  {
    "file_name": "contract.pdf",
    "upload_session_token": "sess_abc123def456",
    "upload_url": "https://s3.amazonaws.com/bucket/contract.pdf?X-Amz-Signature=..."
  },
  {
    "file_name": "site-inspection-photo.jpg",
    "upload_session_token": "sess_abc123def456",
    "upload_url": "https://s3.amazonaws.com/bucket/site-inspection-photo.jpg?X-Amz-Signature=..."
  }
]
```

- **`upload_session_token`** — Unique token for the upload session. It is the same for all files in the same request. You will use it in step 3.
- **`upload_url`** — Temporaray presigned URL to upload each file. It has a time limit of 120 seconds.


#### Step 2 — Upload the files

For each file, send an **HTTP PUT** to the received `upload_url`, with the request body equal to the binary content of the file.


```http
PUT https://s3.amazonaws.com/bucket/contract.pdf?X-Amz-Signature=... HTTP/1.1
Content-Type: application/pdf

<binary file content>
```

The client must use exactly the received URL without adding TrueScreen authentication headers (the signature is in the URL). The only header needed is `Content-Type` with the file’s MIME type.

Repeat for each file. **All files must be uploaded** before proceeding to step 3; otherwise creation will fail with error `TS-013`.

#### Step 3 — Create the certification

**Endpoint:** `POST /v1/file-certifications`

**Body:**


```json
{
  "title": "Site inspection certification",
  "upload_session_token": "sess_abc123def456",
  "webhook_url": "https://example.com/webhook/certification",
  "generate_pdf_report": true,
  "metadata": {
    "site_id": "SITE-042",
    "inspector": "Jane Smith"
  }
}
```

| Field | Required | Description |
|  --- | --- | --- |
| `title` | yes | Certification title |
| `upload_session_token` | yes | Token received in step 1 |
| `webhook_url` | no | URL for callback on completion |
| `generate_pdf_report` | no | Whether to generate a PDF report (defaults to `true`) |
| `metadata` | no | Key-value object with custom data |


**Response (201 Created):**


```json
{
  "report_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "status": "pending",
  "credits_amount": 2,
  "title": "Site inspection certification",
  "created_at": "2026-03-06T15:00:00Z"
}
```

- **`credits_amount`** — Credits consumed: 1 per file uploaded (in this example, 2 files = 2 credits).


#### File certification sequence summary

1. `POST /v1/file-certifications-attachments` with file names (and optional per-file `creation_datetime`) → get `upload_session_token` and `upload_url` for each file.
2. `PUT upload_url` for each file → upload binary content.
3. `POST /v1/file-certifications` with `upload_session_token` → start certification.


### 3. Checking certification status

The process is **asynchronous**: after creation, the certification is in `"pending"` status. You can know when it is complete in two ways.

#### Polling

**Endpoint:** `GET /v1/certifications/{reportId}`

Poll this endpoint periodically, passing the `report_id` received in the creation response.

**Response (certification in progress):**


```json
{
  "report_id": "d8c2aef3-72a7-4a5f-b0e7-4308a88c6cff",
  "status": "pending",
  "created_at": "2026-03-06T14:30:00Z",
  "title": "Project Alpha documents certification",
  "files": []
}
```

**Response (certification completed):**


```json
{
  "report_id": "d8c2aef3-72a7-4a5f-b0e7-4308a88c6cff",
  "status": "completed",
  "created_at": "2026-03-06T14:30:00Z",
  "title": "Project Alpha documents certification",
  "files": [
    {
      "type": "data",
      "url": "https://s3.example.com/d8c2aef3.json?X-Amz-Signature=..."
    },
    {
      "type": "report",
      "url": "https://s3.example.com/d8c2aef3.pdf?X-Amz-Signature=..."
    },
    {
      "type": "xml",
      "url": "https://s3.example.com/d8c2aef3.xml?X-Amz-Signature=..."
    }
  ]
}
```

Files in the `files` array have a `type` field that identifies the artifact:

| `type` | Artifact | Description |
|  --- | --- | --- |
| `data` | jsonData | Machine-readable JSON document with hashes and metadata |
| `report` | PDF report | Human-readable PDF with key data (only if report generation is enabled in configuration) |
| `xml` | Signed XML | Digitally signed and timestamped XML envelope |
| `media` | Original files | The uploaded files (file certification only) |


URLs are **signed** (presigned) and expire after 60 seconds: download the files within the validity period.

**Response (certification failed after async processing):**

If the creation `POST` succeeded but later processing fails, **`GET /v1/certifications/{reportId}`** returns **`500`**, **`Content-Type: application/problem+json`**, and this RFC 9457 problem body:


```http
HTTP/1.1 500 Internal Server Error
Content-Type: application/problem+json
```


```json
{
  "type": "https://truescreen.redocly.app/errors/server-error",
  "title": "Certification processing error",
  "status": 500,
  "detail": "Digital sign error.",
  "code": "TS-014"
}
```

#### Webhook

If you passed a `webhook_url` in the creation request, TrueScreen sends an **HTTP POST callback** to that URL when processing **finishes — success or failure**.

The callback payload uses the **Standard Webhooks** envelope format:

- **`certification.completed`** — `data` matches the **200** `GET` response (certification object with `files`).
- **`certification.error`** — `data` contains the **`application/problem+json`** document the `GET` would return for that outcome.


Every callback is signed with Standard Webhooks headers (`webhook-id`, `webhook-timestamp`, `webhook-signature`). See [Certification — Overview](/certification-overview#signature-verification) for verification details.

## Common errors

| Code | Situation | Action |
|  --- | --- | --- |
| `TS-001` | Malformed payload | Check the request JSON structure |
| `TS-002` | Missing required field | Ensure `title`, `files`, or `upload_session_token` are present |
| `TS-008` | Insufficient credits | Check balance with `GET /v1/credits` and purchase credits from the TrueScreen portal |
| `TS-010` | Certification not found | Verify the `reportId` passed to `GET /v1/certifications/{reportId}` |
| `TS-012` | Upload session token already used | Each `upload_session_token` can create only one certification |
| `TS-013` | Not all files uploaded | Complete upload of all files before calling `POST /v1/file-certifications` |
| `TS-014` | Certification processing failed after creation | See [Server errors](/errors/server-error#certification-processing-failure); webhook sends `certification.error` event |


For the full error response format, see [API errors](/errors).