Skip to main content
The recovery flow allows users to regain access to their accounts when they’ve lost their credentials. Kratos supports email-based and code-based recovery strategies.

Flow initialization

Recovery flows can be initiated for browser-based applications or API clients.

Browser flows

Initialize a recovery flow for browser applications:
curl -X GET \
  'https://{project}.projects.oryapis.com/self-service/recovery/browser' \
  -H 'Accept: application/json'
Query parameters:
  • return_to - URL to redirect to after successful recovery
Response:
{
  "id": "d4e5f6a7-b8c9-4d0e-1f2a-3b4c5d6e7f8a",
  "type": "browser",
  "expires_at": "2026-03-03T12:00:00Z",
  "issued_at": "2026-03-03T11:00:00Z",
  "request_url": "https://{project}.projects.oryapis.com/self-service/recovery/browser",
  "ui": {
    "action": "https://{project}.projects.oryapis.com/self-service/recovery?flow=d4e5f6a7-b8c9-4d0e-1f2a-3b4c5d6e7f8a",
    "method": "POST",
    "nodes": [...]
  },
  "state": "choose_method"
}

API flows

For native applications (mobile, desktop, server-to-server):
curl -X GET \
  'https://{project}.projects.oryapis.com/self-service/recovery/api' \
  -H 'Accept: application/json'
Recovery can be disabled in the configuration. If disabled, this endpoint returns a 400 error with message “Recovery is not allowed because it was disabled.”
Recovery flows are only available for unauthenticated users. Authenticated users receive a 400 error.

Recovery strategies

Kratos supports two recovery strategies that can be used independently or together.

Code strategy

Send a one-time recovery code via email:
1

Request recovery code

Submit the user’s email address:
curl -X POST \
  'https://{project}.projects.oryapis.com/self-service/recovery?flow=<flow_id>' \
  -H 'Content-Type: application/json' \
  -d '{
    "method": "code",
    "email": "[email protected]"
  }'
A recovery code is sent to the email address if an account exists.
2

Submit recovery code

Enter the code received via email:
curl -X POST \
  'https://{project}.projects.oryapis.com/self-service/recovery?flow=<flow_id>' \
  -H 'Content-Type: application/json' \
  -d '{
    "method": "code",
    "code": "123456"
  }'
3

Update credentials

After successful code verification, the flow transitions to a settings flow where the user can update their password or other credentials.
Send a magic recovery link via email:
curl -X POST \
  'https://{project}.projects.oryapis.com/self-service/recovery?flow=<flow_id>' \
  -H 'Content-Type: application/json' \
  -d '{
    "method": "link",
    "email": "[email protected]"
  }'
The user receives an email with a recovery link. Clicking the link:
  1. Validates the token
  2. Authenticates the user
  3. Redirects to a settings flow to update credentials

Configuration

Enable and configure recovery in your Kratos configuration:
selfservice:
  methods:
    link:
      enabled: true
      config:
        lifespan: 1h
    code:
      enabled: true
      config:
        lifespan: 1h
  
  flows:
    recovery:
      enabled: true
      lifespan: 1h
      ui_url: https://your-app.com/recovery
      after:
        default_browser_return_url: https://your-app.com/

Flow states

The recovery flow progresses through several states:
StateDescription
choose_methodInitial state - user selects recovery method
sent_emailRecovery email has been sent
passed_challengeRecovery code/link verified successfully

Fetching an existing flow

Retrieve a recovery flow by its ID:
curl -X GET \
  'https://{project}.projects.oryapis.com/self-service/recovery/flows?id=<flow_id>'

Error handling

Status: 400 Bad RequestThe user is already authenticated. Recovery is only available for unauthenticated users.Solution: User should logout first or use the settings flow to change credentials.

Complete flow example

# 1. Initialize the flow
curl -X GET 'https://{project}.projects.oryapis.com/self-service/recovery/browser'

# Browser is redirected to UI with flow ID
# User visits: https://your-app.com/recovery?flow=<flow_id>

# 2. Request recovery code
curl -X POST \
  'https://{project}.projects.oryapis.com/self-service/recovery?flow=<flow_id>' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'method=code&[email protected]&csrf_token=...'

# 3. Submit code from email
curl -X POST \
  'https://{project}.projects.oryapis.com/self-service/recovery?flow=<flow_id>' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'method=code&code=123456&csrf_token=...'

# User is redirected to settings flow to update password

Security considerations

Recovery flows can be used to enumerate email addresses. Consider:
  • Always show a success message even if the email doesn’t exist
  • Rate limit recovery requests
  • Monitor for suspicious patterns
  • Use CAPTCHAs for additional protection

Email templates

Customize recovery emails in your Kratos configuration:
courier:
  templates:
    recovery:
      valid:
        email:
          body:
            html: /path/to/recovery.html.tmpl
            plaintext: /path/to/recovery.txt.tmpl
          subject: Recover your account
Template variables:
  • RecoveryURL - The recovery link (link strategy)
  • RecoveryCode - The recovery code (code strategy)
  • Identity - The user’s identity traits

API reference

EndpointMethodDescription
/self-service/recovery/browserGETInitialize browser recovery flow
/self-service/recovery/apiGETInitialize API recovery flow
/self-service/recovery/flowsGETGet recovery flow by ID
/self-service/recoveryPOSTSubmit recovery flow
All endpoints are defined in selfservice/flow/recovery/handler.go:30-35

Build docs developers (and LLMs) love