:::endpoint POST /v1/me/passkeys

Send the attestation the platform returned, together with a name for it. The
name is what the account will see in its own list of devices, so use something a
person recognises months later.

The ceremony has to be the one this device started: the challenge is kept against
the token, and it is gone after this call either way.

## Request

```bash
curl -X POST https://api.proppertrading.com/v1/me/passkeys \
  -H "Authorization: Bearer ptat_9f2c1a44_3b8e7d2f5c9a1b4e6d8f0a2c4e6b8d1f" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 1b8a6f0e-3c5d-4f7a-9e2b-0d4c6a8e1f30" \
  -d '{
    "name": "iPhone",
    "id": "AQIDBA",
    "rawId": "AQIDBA",
    "type": "public-key",
    "response": {
      "clientDataJSON": "eyJ0eXBlIjoid2ViYX...",
      "attestationObject": "o2NmbXRkbm9uZWdh..."
    }
  }'
```

| Field                        | Type   | Description                            |
| ---------------------------- | ------ | -------------------------------------- |
| `name`                       | string | Up to 64 characters. Required          |
| `id`, `rawId`, `type`        | string | From the platform, unchanged. Required |
| `response.clientDataJSON`    | string | From the platform, unchanged. Required |
| `response.attestationObject` | string | From the platform, unchanged. Required |

## Response

The passkey as [the list](/docs/api/apps/passkeys) shows it. Status is `201`.

```json
{
    "data": {
        "id": "890ad7f8-de78-4b88-b4b2-fc52715671e8",
        "object": "passkey",
        "name": "iPhone",
        "is_enabled": true,
        "created_at": "2026-08-20T09:12:44.000000Z",
        "last_used_at": "2026-08-20T09:12:44.000000Z"
    },
    "meta": { "request_id": "req_01kz4bkr1aj1gv63d8fv3133ey" }
}
```

## Errors

| Status | Code                 | Meaning                                                                                               |
| ------ | -------------------- | ----------------------------------------------------------------------------------------------------- |
| 400    | `invalid_passkey`    | The attestation did not verify, or answered a challenge that is no longer live. Ask for options again |
| 403    | `insufficient_scope` | This device does not hold `me:write`                                                                  |
| 422    | `validation_failed`  | A field is missing or malformed                                                                       |

:::note One reason for every failure inside the ceremony
`invalid_passkey` covers a wrong origin, a spent challenge, a bad signature and
several other things. The distinctions are in our logs, because out here they
only help somebody who is guessing.
:::