---
title: "Start 2FA"
method: POST
path: "/api/v1/me/2fa/start"
tags: ["2FA"]
---

# Start 2FA

`POST /api/v1/me/2fa/start`

## Request

- Base URL: `https://api.proof.holdings`
- URL: `https://api.proof.holdings/api/v1/me/2fa/start`
- Auth: API key in cookie `auth_token`

Start a 2FA verification for a sensitive operation.

## Request body

- Start2FARequest: Request body for starting 2FA verification
  - `action_type` 'api_key_view' | 'api_key_create' | 'api_key_revoke' | 'api_key_regenerate' | 'phone_add' | 'phone_remove' | 'email_add' | 'email_remove' | 'account_delete' | 'master_key_change' | 'hitl_key_rotate' | 'revocation_bulk' | 'settings_write' | 'profile_update' | 'templates_write' | 'webhook_write' | 'delegation_lifecycle' | 'domain_remove' | 'profile_delete' | 'account_delete_cancel', required: Action type requiring 2FA. Destructive actions (api_key_*, account_delete, account_delete_cancel, phone_remove, email_remove, domain_remove, profile_delete, master_key_change, hitl_key_rotate, revocation_bulk, delegation_lifecycle) are capped at 5 min TTL and forced single-use by server policy. `revocation_bulk` is the ONE action type for every proof revocation by the owner — phone, email or domain, one proof or a batch of up to 25, from the assets routes or a signed-in call on the proofs API; a grant is bound to the `targets` named at start and is refused for any other ids. `domain_remove` gates `DELETE /me/domains/{id}`, `profile_delete` gates `DELETE /me/profiles/{profileId}` for a session, `account_delete` gates scheduling the account deletion and `account_delete_cancel` gates cancelling it; each takes the single target id as its one `targets` entry. Configuration scopes (settings_write, profile_update, templates_write, webhook_write) allow up to 24h TTL with caller-chosen single_use. `master_key_change` gates a change of the HITL account encryption password. `hitl_key_rotate` gates a JWT dashboard session replacing the encryption keypair (a new `kid`) of an active HITL config — an API-key caller is unaffected, and the owner is emailed about every rotation from either path. `delegation_lifecycle` gates a JWT dashboard session revoking, suspending, or unsuspending a delegation (`ph_dlg_*` handle) — an API-key caller is unaffected, gated instead by the `delegations:write` scope. `phone_add` / `email_add` are preserved for backwards-compat with existing dashboard flows but no longer gate any backend route — the add-phone / add-email flows self-authenticate via reverse-OTP / OTP verification. `api_key_view` is reserved for UI surfaces that re-reveal an API key secret; `webhook_write` is reserved for future per-resource webhook mutations.
  - `channel` 'telegram' | 'whatsapp' | 'sms' | 'email', required
  - `email_id` string: Optional: specify which email to use for email 2FA
  - `phone_id` string: Optional: specify which phone to use for phone-channel 2FA
  - `ttl_seconds` integer: Requested grant lifetime in seconds (60-86400). Server clamps to per-action-type maximum (300s for destructive actions, 86400s for config mutations). Defaults to 300s if omitted.
  - `single_use` boolean: Whether the grant is consumed on first use. Server forces true for destructive actions regardless of this value. Defaults to true.
  - `targets` string[]: The ids this step-up is for (1-25): asset ids for the assets routes, `ph_ctl_*` handles for the proofs API, the domain / profile / account id for a single-target action. The grant is bound to a digest of exactly these ids and the gated route refuses it with `2fa_required` (`reason: target_mismatch`) when the request names different ids. Omit for an untargeted action such as settings_write.

## Response `200`

2FA session started

- SuccessResponse: Generic success response
  - `success` boolean, required
  - `message` string

## Other responses

- `400`: Validation error

---

[API](https://skmtc.dev/proof/apis/proof-holdings-api.md) · [All operations](https://skmtc.dev/proof/apis/proof-holdings-api/llms.txt) · [OpenAPI document](https://skmtc.dev/proof/apis/proof-holdings-api/revisions/b15f506de696?raw)
