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

# Twins

> Create, retrieve and list twins, and download their content.

A `twin` is the synthetic copy of one trace. Create one per trace, or many at once with a [batch](https://docs.metaphi.ai/kennet/api/batches.md).

Each twin draws its own synthetic values: consistent within the twin, unlinked across twins.

## The twin object

```json theme={"dark"}
{
  "id": "twin_4FFTGxX_b40dXo8F-ObejckZj1DsFKPhqvJFo25CNH0",
  "object": "kennet.twin",
  "status": "completed",
  "created": 1760054400,
  "started": 1760054410,
  "completed": 1760054580,
  "filename": "trace.jsonl",
  "end_user": "cust_8812",
  "batch_id": null,
  "custom_id": null,
  "error": null,
  "livemode": true,
  "progress": null
}
```

| Field | Type | Description |
| - | - | - |
| `id` | string | Unique identifier, prefixed `twin_` |
| `object` | string | `kennet.twin` |
| `status` | enum | `queued`, `running`, `paused`, `completed`, `failed` or `cancelled`. See [statuses](#statuses) |
| `created` | integer | Time the twin was created, in Unix seconds |
| `started` | integer or null | Time the twin started running, in Unix seconds. `null` until a run is under way |
| `completed` | integer or null | Time the twin completed, failed or was cancelled, in Unix seconds |
| `filename` | string or null | Name of the uploaded file |
| `end_user` | string or null | The `end_user` set at creation |
| `batch_id` | string or null | The batch that created the twin |
| `custom_id` | string or null | The `custom_id` of the batch request that created the twin |
| `error` | object or null | Set when `status` is `failed`: `{type, code, message, retryable, action_url}`. See [twin failures](https://docs.metaphi.ai/kennet/api/errors.md#twin-failures) |
| `livemode` | boolean | `false` for a test-mode twin |
| `progress` | object or null | `{stage}` while `running`: `reading`, `mapping`, `writing`, `checking` or `finishing`. Set on [retrieve](#retrieve-a-twin) only; `null` in lists and events, and in any other status |

## Statuses

| Status | Meaning |
| - | - |
| `queued` | Created; waiting to start |
| `running` | In progress |
| `paused` | Waiting for credit: what the organization can spend (balance plus credit limit, less twins in progress) does not cover the twin. Starts by itself when credit is added or other twins finish. Checked on a backoff, at most 15 minutes apart |
| `completed` | Content is ready to download. Final |
| `failed` | The trace cannot be twinned; `error.code` gives the reason. Final |
| `cancelled` | Ended before it completed, for example when its batch is [cancelled](https://docs.metaphi.ai/kennet/api/batches.md#cancel-a-batch) or [expires](https://docs.metaphi.ai/kennet/api/batches.md#statuses). Final |

A twin reaches `completed` unless its input causes a failure. Errors on our side are retried automatically. Failed twins are not charged, and a twin is not charged while paused. A batch's twins do not pause; their [batch](https://docs.metaphi.ai/kennet/api/batches.md#statuses) does.

## Create a twin

`POST /v1/kennet/twins`

Uploads one trace and creates its twin. Send `multipart/form-data` with an [`Idempotency-Key`](https://docs.metaphi.ai/kennet/api/idempotency) header.

| Parameter | Type | Required | Description |
| - | - | - | - |
| `file` | file | yes | The trace, in a [supported format](https://docs.metaphi.ai/kennet/api/files.md#formats). Max 50 MiB (2 MiB in test mode). Name: 1 to 200 letters, digits, `.`, `-` and `_` |
| `end_user` | string | no | Your ID for the customer the trace belongs to; not a name or email. 1 to 128 letters, digits, `.`, `_`, `:` and `-` |
| `confidential` | string | no | A public organisation to treat as confidential. Repeat for each |

```sh theme={"dark"}
curl https://api.metaphi.ai/v1/kennet/twins \
  -H "Authorization: Bearer $API_KEY" \
  -H "Idempotency-Key: 5d3e1c1a-..." \
  -F file=@trace.jsonl \
  -F end_user=cust_8812 \
  -F confidential="Example Holdings"
```

**Returns** `202` with a `twin` object, `status: queued`, and a `Location` header. If what the organization can spend (balance plus credit limit, less twins in progress) does not cover the twin, the request still succeeds: the twin moves to `paused`, sends `kennet.twin.paused`, and starts by itself when credit is added or other twins finish, sending `kennet.twin.resumed`.

| Status | Code | Cause |
| - | - | - |
| 400 | `invalid_filename`, `file_empty`, `invalid_end_user` | Invalid `file` or `end_user` |
| 400 | `file_unsupported` | Not JSON, JSON Lines or UTF-8 text |
| 400 | `parameter_unknown` | An unknown field |
| 403 | `test_quota_exhausted` | Test mode: 5 twins per organization per 24 hours used |
| 409 | `idempotency_key_reused`, `idempotency_key_in_use` | See [Idempotency](https://docs.metaphi.ai/kennet/api/idempotency.md) |
| 413 | `file_too_large` | `file` is over 50 MiB (2 MiB in test mode) |

## Retrieve a twin

`GET /v1/kennet/twins/{id}`

Retrieves a twin.

**Returns** a `twin` object, or `404 resource_missing` if this key's organization and mode have no twin with that ID.

## List twins

`GET /v1/kennet/twins`

Lists twins, newest first, including twins created by batches.

| Parameter | Type | Required | Description |
| - | - | - | - |
| `limit` | integer | no | 1 to 100. Default 10 |
| `starting_after` | string | no | A twin ID. Returns the page after it |
| `end_user` | string | no | Only twins with this `end_user` |

**Returns** `{object: "list", data, has_more, url}`, with `twin` objects in `data`. If `has_more` is `true`, pass the last `id` as `starting_after` for the next page.

## Download a twin's content

`GET /v1/kennet/twins/{id}/content`

Downloads the twinned file of a completed twin.

**Returns** `200` with the file as an attachment, under the uploaded file's name, in its format:

| Extension | Content-Type |
| - | - |
| `.json` | `application/json` |
| `.jsonl`, `.ndjson` | `application/x-ndjson` |
| Other | `text/plain; charset=utf-8` |

| Status | Code | Cause |
| - | - | - |
| 409 | `twin_not_completed` | `status` is not `completed` yet |
| 409 | `twin_failed` | The twin failed and has no content |
| 410 | `content_expired` | More than 30 days since the twin completed |


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