Skip to main content
The registration flow enables users to create new accounts in Ory Kratos. It supports multiple registration methods and custom identity schemas.

Flow initialization

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

Browser flows

Initialize a registration flow for browser applications:
curl -X GET \
  'https://{project}.projects.oryapis.com/self-service/registration/browser' \
  -H 'Accept: application/json'
Query parameters:
  • return_to - URL to redirect to after successful registration
  • login_challenge - Hydra OAuth2 login challenge (when acting as an OAuth2 provider)
  • after_verification_return_to - URL to redirect to after email verification
  • organization - Organization ID for multi-tenant deployments
  • identity_schema - Specific identity schema to use for this flow
Response:
{
  "id": "a1b2c3d4-e5f6-4a5b-8c9d-0e1f2a3b4c5d",
  "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/registration/browser",
  "ui": {
    "action": "https://{project}.projects.oryapis.com/self-service/registration?flow=a1b2c3d4-e5f6-4a5b-8c9d-0e1f2a3b4c5d",
    "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/registration/api' \
  -H 'Accept: application/json'
Additional query parameters:
  • return_session_token_exchange_code - Request a code to exchange for a session token after registration
Registration can be disabled in the configuration. If disabled, this endpoint returns a 400 error with message “Registration is not allowed because it was disabled.”

Registration methods

The registration flow supports multiple strategies for creating accounts.

Password registration

Create an account with email/username and password:
curl -X POST \
  'https://{project}.projects.oryapis.com/self-service/registration?flow=<flow_id>' \
  -H 'Content-Type: application/json' \
  -d '{
    "method": "password",
    "traits": {
      "email": "user@example.com",
      "name": {
        "first": "John",
        "last": "Doe"
      }
    },
    "password": "your-secure-password"
  }'
The traits object must match your configured identity schema.

OIDC registration

Register using OAuth2/OIDC providers:
curl -X POST \
  'https://{project}.projects.oryapis.com/self-service/registration?flow=<flow_id>' \
  -H 'Content-Type: application/json' \
  -d '{
    "method": "oidc",
    "provider": "google",
    "traits": {
      "email": "user@example.com"
    }
  }'
Supported providers:
  • Google
  • GitHub
  • Microsoft
  • Apple
  • GitLab
  • Generic OIDC/OAuth2 providers

Passkey registration

Register with WebAuthn/FIDO2 credentials:
curl -X POST \
  'https://{project}.projects.oryapis.com/self-service/registration?flow=<flow_id>' \
  -H 'Content-Type: application/json' \
  -d '{
    "method": "passkey",
    "traits": {
      "email": "user@example.com"
    },
    "passkey_register": "<webauthn_credential>"
  }'

Code-based registration

Register using email or SMS verification codes:
curl -X POST \
  'https://{project}.projects.oryapis.com/self-service/registration?flow=<flow_id>' \
  -H 'Content-Type: application/json' \
  -d '{
    "method": "code",
    "traits": {
      "email": "user@example.com"
    }
  }'
A verification code is sent to the provided email or phone number.

Identity schemas

Customize the registration form using identity schemas:
1

Define identity schema

Create a JSON schema defining required traits:
{
  "$id": "https://example.com/user.schema.json",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "User",
  "type": "object",
  "properties": {
    "traits": {
      "type": "object",
      "properties": {
        "email": {
          "type": "string",
          "format": "email",
          "title": "Email",
          "ory.sh/kratos": {
            "credentials": {
              "password": {
                "identifier": true
              }
            },
            "verification": {
              "via": "email"
            }
          }
        },
        "name": {
          "type": "object",
          "properties": {
            "first": { "type": "string" },
            "last": { "type": "string" }
          },
          "required": ["first", "last"]
        }
      },
      "required": ["email", "name"]
    }
  }
}
2

Configure in Kratos

Reference the schema in your Kratos configuration:
identity:
  default_schema_id: default
  schemas:
    - id: default
      url: file:///path/to/user.schema.json
    - id: customer
      url: file:///path/to/customer.schema.json
3

Use specific schema

Request a specific schema during registration:
curl -X GET \
  'https://{project}.projects.oryapis.com/self-service/registration/api?identity_schema=customer'

Two-step registration

Enable two-step registration to separate profile and credential collection:
selfservice:
  flows:
    registration:
      two_steps: true
With two-step registration:
  1. Step 1: Collect identity traits (email, name, etc.)
  2. Step 2: Set up authentication method (password, passkey, etc.)

Fetching an existing flow

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

Error handling

Status: 400 Bad RequestThe user is already authenticated. Registration is not available for authenticated users.Solution: Redirect to the default return URL or logout first.

Complete flow example

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

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

# 2. Fetch the flow
curl -X GET \
  'https://{project}.projects.oryapis.com/self-service/registration/flows?id=<flow_id>'

# 3. Submit registration
curl -X POST \
  'https://{project}.projects.oryapis.com/self-service/registration?flow=<flow_id>' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'method=password&traits.email=user@example.com&traits.name.first=John&traits.name.last=Doe&password=secret&csrf_token=...'

# Browser is redirected with session cookie set

Post-registration hooks

Configure hooks to run after successful registration:
selfservice:
  flows:
    registration:
      after:
        password:
          hooks:
            - hook: session
            - hook: verify
Available hooks:
  • session - Create a session automatically (log in the user)
  • verify - Send verification email
  • web_hook - Call external webhook

API reference

EndpointMethodDescription
/self-service/registration/browserGETInitialize browser registration flow
/self-service/registration/apiGETInitialize API registration flow
/self-service/registration/flowsGETGet registration flow by ID
/self-service/registrationPOSTSubmit registration flow
All endpoints are defined in selfservice/flow/registration/handler.go:41-46

Build docs developers (and LLMs) love