Skip to main content
The recovery flow enables users to recover their accounts when they’ve lost access. Recovery typically works by sending a recovery link or code to the user’s verified email address.

Initialize recovery flow for browsers

curl -X GET 'https://your-project.projects.oryapis.com/self-service/recovery/browser' \
  -H 'Accept: application/json'

Endpoint

GET /self-service/recovery/browser
Initializes a browser-based account recovery flow. Once initialized, the browser is redirected to the recovery UI.

Query parameters

return_to
string
URL to redirect the browser to after successful recovery.

Response

id
string
required
The flow ID, used to fetch and submit the flow.
type
string
required
The flow type: browser or api.
expires_at
string
required
Time when this flow expires (RFC3339 format).
issued_at
string
required
Time when this flow was issued (RFC3339 format).
request_url
string
required
The original request URL.
state
string
required
Current state of the flow: choose_method, sent_email, or passed_challenge.
ui
object
required
UI container with form fields and messages.

Status codes

StatusDescription
200Recovery flow created (AJAX requests)
303Redirect to recovery UI with flow ID
400Invalid request

Initialize recovery flow for native apps

curl -X GET 'https://your-project.projects.oryapis.com/self-service/recovery/api' \
  -H 'Accept: application/json'

Endpoint

GET /self-service/recovery/api
Initializes a recovery flow for native apps. Use this for mobile apps, smart TVs, and other non-browser clients.
Do NOT use this endpoint in browser-based applications. Use /self-service/recovery/browser instead to prevent CSRF attacks.

Response

Returns the same recovery flow object as the browser endpoint.

Status codes

StatusDescription
200Recovery flow created successfully
400Invalid request

Get recovery flow

curl -X GET 'https://your-project.projects.oryapis.com/self-service/recovery/flows?id=flow-id' \
  -H 'Accept: application/json'

Endpoint

GET /self-service/recovery/flows
Returns a recovery flow’s context with error details and other information.

Query parameters

id
string
required
The recovery flow ID from the flow URL query parameter.

Headers

HTTP Cookie header for browser flows. Required for CSRF validation.

Response

Returns the recovery flow object.

Status codes

StatusDescription
200Recovery flow found
404Flow not found
410Flow expired

Submit recovery flow

The recovery flow has multiple states, each requiring different submissions:

Choose method state

Submit the user’s email address to send a recovery link or code.
curl -X POST 'https://your-project.projects.oryapis.com/self-service/recovery?flow=flow-id' \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -d '{
    "method": "link",
    "email": "[email protected]",
    "csrf_token": "token-from-flow"
  }'

Sent email state

Request another recovery email to be sent.
curl -X POST 'https://your-project.projects.oryapis.com/self-service/recovery?flow=flow-id' \
  -H 'Content-Type: application/json' \
  -d '{
    "method": "link",
    "email": "[email protected]",
    "csrf_token": "token-from-flow"
  }'

Endpoint

POST /self-service/recovery
Updates a recovery flow based on its current state.

Query parameters

flow
string
required
The recovery flow ID.
token
string
Recovery token from the recovery link (used in passed_challenge state).

Headers

HTTP Cookie header for browser flows.

Request body

method
string
required
Recovery method: link or code.
email
string
required
User’s email address for recovery.
csrf_token
string
CSRF token from the flow (required for browser flows).
For code method (after receiving code):
code
string
required
The recovery code sent to the user’s email.

Response

state
string
required
Updated flow state.
ui
object
required
Updated UI with messages and form fields.
continue_with
array
Next actions to take. When recovery succeeds, typically includes a settings flow to update the password.

Response (browser flows)

Browser flows behave differently: In choose_method state:
  • 200 OK with updated flow (API/AJAX)
  • 303 redirect to recovery UI (browser)
In sent_email state:
  • 200 OK with updated flow (API/AJAX)
  • 303 redirect to recovery UI with success message (browser)
In passed_challenge state (valid recovery link):
  • 303 redirect to settings UI to update password
In passed_challenge state (invalid recovery link):
  • 303 redirect to recovery UI with error message

Status codes

StatusDescription
200Flow updated successfully
303Redirect (browser flows)
400Form validation errors
410Flow expired
422Browser location change required

Recovery flow states

The recovery flow progresses through these states:
  1. choose_method - User selects recovery method and provides email
  2. sent_email - Recovery email sent, user can request another
  3. passed_challenge - User clicked recovery link, redirect to settings

Error responses

Common validation errors:
  • email is required - No email provided
  • Could not find email - Email not associated with any account
  • Recovery token is invalid - Token expired or already used
  • security_csrf_violation - CSRF token validation failed

Build docs developers (and LLMs) love