> ## Documentation Index
> Fetch the complete documentation index at: https://docs.didit.me/llms.txt
> Use this file to discover all available pages before exploring further.

# Создание Step-Up | Didit Authentication API

> Didit: POST /step-up/ применяет ваши step-up правила перед чувствительным действием и возвращает required: false или ссылку на верификацию.

> [!WARNING]
>
> Аутентификация появилась недавно. Эти endpoint'ы обслуживаются эмитентом вашего приложения, например `https://<name>.auth.didit.me`, и никогда не принимают ваш API-ключ Didit.

Параметры запроса `step_up` и `status` в вашем `return_to` лишь сообщают вашему приложению, что нужно проверить результат. Прежде чем действовать, получите данные о процедуре усиленной аутентификации с помощью [Получить step-up](https://docs.didit.me/ru/authentication/api-reference/retrieve-step-up.md) и продолжайте только тогда, когда `status` равен `approved`.


## OpenAPI

````yaml ru/openapi-authentication.json POST /step-up/
openapi: 3.0.3
info:
  title: Didit Authentication API
  version: 1.0.0
  description: >-
    Серверные endpoints Didit Authentication, продукта для входа конечных
    пользователей вашего приложения. Authentication является **новым**
    продуктом, который выходит в продакшн в релизе 2026-11-01.


    ## Базовый URL


    Каждое приложение является собственным издателем (issuer) OpenID Connect, и
    каждый приведенный ниже endpoint обслуживается в корне этого издателя:


    - `https://<name>.auth.didit.me` для продакшн-приложения или
    `https://<name>.sandbox.auth.didit.me` для приложения в песочнице.

    - Ваш собственный кастомный домен после его активации. В этом случае он
    заменяет хост по умолчанию в качестве издателя: новые токены указывают его в
    `iss`, discovery указывает на него, а публичный ключ (publishable key)
    меняется. Access token, выпущенные под хостом по умолчанию, возвращают
    ошибку при вызове `/session/`, `/step-up/` и `/monitoring-token/` до тех
    пор, пока не будут обновлены.


    Продакшн и песочница являются раздельными приложениями, поэтому они
    представляют собой отдельных издателей с раздельными ключами. Публичный ключ
    состоит из префикса `pk_live_` (продакшн) или `pk_test_` (песочница), за
    которым следует base64url-кодировка издателя без паддинга и без завершающего
    слеша: декодируйте его, чтобы узнать издателя. Это публичный идентификатор,
    а не учетные данные.


    Те же JSON endpoints также обслуживаются по адресу
    `https://apx.didit.me/auth/v2/authentication/{application_id}/`. Токены
    всегда указывают издателя, описанного выше, независимо от адреса, через
    который они были выпущены.


    ## Учетные данные


    Эти endpoints никогда не принимают ваш API-ключ Didit или token консоли.


    - Discovery, JWKS и `POST /token/` не требуют учетных данных. Клиенты
    являются публичными: секрет клиента (client secret) отсутствует, а код
    авторизации привязан к верификатору PKCE (`S256`). `client_id` является
    идентификатором вашего приложения (application ID).

    - `/session/`, `/step-up/` и `/monitoring-token/` принимают access token
    пользователя: `Authorization: Bearer <access_token>`. Каждый успешный вызов
    считается активностью в сессии и сбрасывает таймаут неактивности сессии.


    ## Тела запросов


    Каждый endpoint, принимающий тело запроса, поддерживает JSON, form-encoded и
    multipart. В этом документе приведены JSON, а также form-encoded для `POST
    /token/`, как его отправляют OAuth-клиенты. Если endpoint не принимает поле,
    возвращается `400 {"<field>": "unknown_field"}`.


    ## Токены


    - **Access token**: JWT с алгоритмом ES256 и заголовком `typ: at+jwt`,
    действительный не более 5 минут и не дольше самой сессии. Утверждения:
    `AccessTokenClaims`.

    - **ID token**: JWT с алгоритмом ES256 и заголовком `typ: JWT`. Утверждения:
    `IDTokenClaims`. Он никогда не принимается в качестве access token.

    - **Refresh token**: случайная строка, которая ротируется при каждом
    использовании. Повторная отправка уже использованного refresh token приводит
    к отзыву сессии.


    Проверяйте token с помощью ключей из `GET /.well-known/jwks.json`: алгоритм
    должен быть `ES256`, `typ` должен соответствовать типу токена, `iss` должен
    совпадать с настроенным вами издателем, а `aud` с идентификатором вашего
    приложения. Офлайн-проверка распознает отозванную сессию только после
    истечения срока действия ее access token; `GET /session/` выполняет
    мгновенную проверку.


    ## Ошибки


    | Тело | Когда возвращается |

    | --- | --- |

    | `{"error": "<code>"}` | Ошибки от `POST /token/`, все со статусом `400`, в
    формате тела [RFC 6749 раздел
    5.2](https://www.rfc-editor.org/rfc/rfc6749#section-5.2): `invalid_grant`,
    `invalid_client` и Didit `mfa_required`. Ошибки сервиса:
    `temporarily_unavailable`, `monitoring_unavailable`, `monitoring_disabled`.
    |

    | `{"<field>": ["<message>"]}` или `{"<field>": "<code>"}` | Поле запроса не
    прошло валидацию. `non_field_errors` указывает на правило для нескольких
    полей, а `unknown_field` указывает на поле, которое endpoint не принимает. |

    | `{"detail": "<message>"}` | `401` (`invalid_token`), `403`
    (`origin_not_allowed`), `404` (неизвестное приложение или step-up) и `429`
    (лимит запросов). Также `400` для тела, которое невозможно распарсить (`JSON
    parse error - ...`), `405` для метода, который endpoint не поддерживает, и
    `415` для неподдерживаемого `Content-Type`. |


    Ответ `401` также содержит заголовок `WWW-Authenticate: Bearer`, а `429`
    содержит `Retry-After` в секундах.


    Два отказа не возвращают JSON. Запрос к адресу, не являющемуся издателем,
    отклоняется до попадания на эти endpoints, например, пустым ответом `404`
    для неиспользуемого имени `*.auth.didit.me`. Если `step_up_id` не является
    UUID, возвращается страница `404`.


    ## Лимиты запросов


    Запрос должен пройти два уровня проверок.


    **Лимиты endpoints**, рассчитываемые на IP-адрес клиента, на приложение и на
    endpoint:


    - Discovery и JWKS: 1 200 запросов в минуту и 12 000 в час.

    - Все остальные endpoints: 30 запросов в минуту и 300 в час. `GET` и `DELETE
    /session/` используют общий счетчик.


    Превышение лимита: `429 {"detail": "Too many requests from this IP address.
    Please wait before trying again. Expected available in 60 seconds."}`, или
    `3600 seconds` для часового лимита.


    **Защита от ботов**, применяется к каждому запросу `POST` и `DELETE`. Её
    лимитные корзины являются общими для всех запросов `POST` и `DELETE`
    приложения, включая размещённые шаги входа, и пополняются непрерывно:


    - 60 запросов в минуту на IP-адрес клиента.

    - 30 запросов в минуту на устройство для запросов, которые идентифицируют
    устройство, как это делают браузерные и нативные SDK.

    - 3 000 запросов в минуту для всего приложения со всех IP-адресов.
    Обновления токенов (`POST /token/` с `grant_type=refresh_token`) вместо
    этого используют отдельную корзину: 6 000 в минуту для всего приложения.


    Превышение корзины: `429 {"detail": "rate_limited Expected available in N
    seconds."}` (`1 second.`, когда N равно 1). Корзина на IP-адрес действует
    для всех endpoints, поэтому один адрес, отправляющий вперемешку запросы на
    получение токена, step-up и выход из системы, может исчерпать ее до
    достижения любого лимита endpoint. Корзина приложения учитывает каждого
    клиента приложения, включая браузеры.


    Оба уровня возвращают ответ до выполнения endpoint, поэтому запрос,
    получивший статус `429`, не был выполнен: повторите его по прошествии
    времени из `Retry-After`, включая запросы на обновление токена.


    ## Браузерные запросы


    Запрос, содержащий заголовок `Origin`, должен исходить из одного из
    собственных источников приложения или из списка его разрешённых источников,
    иначе он возвращает ошибку `403 origin_not_allowed`. Межсерверные запросы
    (server-to-server) не отправляют `Origin`.


    ## Не рассматривается в этом документе


    Эти маршруты обслуживают размещенные страницы, браузерные и нативные SDK, а
    также AI-агентов. Они не входят в серверный контракт, и серверные SDK их не
    вызывают:


    - Шаги входа: `POST /authorize/`, `POST /password/`, `/email/*`, `/phone/*`,
    `/password-reset/*`, `/passkeys/*`, `/mfa/*`, `/social/*` и
    `/protection/complete/`.

    - Размещенные страницы и обратные вызовы: `/sign-in`, `/magic`, `/invite`,
    `/reset`, `/verify/`, `/sso/*`, `/wallet/callback/`, `/logo/` и файлы
    ассоциации нативных приложений в `/.well-known/`.

    - Доступ для агентов: `/agents/*` и `/grants/`, включая `GET
    /agents/session/`, оперативную проверку access token AI-агента. Доступ для
    агентов не входит в эту версию контракта.

    - API управления в консоли для Authentication, принимающий сессии консоли.


    События Authentication пока не доставляются через webhook, поэтому в этом
    документе webhook не описан.
servers:
  - url: https://{issuer}
    description: 'Эмитент вашего приложения: его источник авторизации.'
    variables:
      issuer:
        default: your-app.auth.didit.me
        description: >-
          Хост эмитента: `<name>.auth.didit.me` (продакшн),
          `<name>.sandbox.auth.didit.me` (песочница) или ваш активный кастомный
          домен.
security: []
tags:
  - name: Issuer
    description: Ключи обнаружения и подписи для проверки токенов.
  - name: Tokens
    description: Гранты authorization code и refresh.
  - name: Sessions
    description: Проверить и завершить сессию, связанную с токеном доступа.
  - name: Step-ups
    description: Верификация перед выполнением конфиденциального действия.
  - name: Monitoring
    description: Учётные данные устройства для событий мониторинга транзакций.
paths:
  /step-up/:
    post:
      tags:
        - Step-ups
      summary: Создать усиленную проверку
      description: >-
        Запрашивает, должен ли пользователь пройти верификацию перед выполнением
        критического действия, на основе настроенных для приложения правил
        step-up.


        - `200 {"required": false}`: ни одно правило не применяется,
        продолжайте.

        - `201`: направьте пользователя на `verification_url`. Он вернётся на
        `return_to` с параметрами `step_up=<id>&status=approved`, однако эти
        параметры запроса ничего не доказывают: запросите step-up через `GET
        /step-up/{step_up_id}/` и действуйте только при статусе `approved`.


        Step-up никогда не открывает доступ при сбое: если верификация
        недоступна, действие остаётся заблокированным.
      operationId: authentication_create_step_up
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/StepUpRequest'
            examples:
              Payout:
                summary: Перед выплатой
                value:
                  action: payout
                  amount: '900.00'
                  currency: USD
                  return_to: https://app.example.com/payouts/confirm
              Bank:
                summary: Перед изменением банковского счёта
                value:
                  action: bank
                  return_to: https://app.example.com/settings/bank
      responses:
        '200':
          description: Ни одно правило не применимо.
          headers:
            Cache-Control:
              description: 'Всегда `no-store`: никогда не кэшируйте этот ответ.'
              schema:
                type: string
                example: no-store
            Pragma:
              description: Всегда `no-cache`.
              schema:
                type: string
                example: no-cache
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StepUpNotRequired'
              examples:
                NotRequired:
                  summary: Продолжить
                  value:
                    required: false
        '201':
          description: Человек должен сначала пройти верификацию.
          headers:
            Cache-Control:
              description: 'Всегда `no-store`: никогда не кэшируйте этот ответ.'
              schema:
                type: string
                example: no-store
            Pragma:
              description: Всегда `no-cache`.
              schema:
                type: string
                example: no-cache
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StepUpRequired'
              examples:
                Required:
                  summary: Селфи перед выплатой
                  value:
                    id: 94efc2c3-ca84-42fe-900b-6fb61669a7a1
                    rule: payout
                    method: selfie
                    status: pending
                    level: null
                    amount: '900.00'
                    currency: USD
                    created_at: '2026-10-17T10:41:14.894632Z'
                    completed_at: null
                    expires_at: '2026-10-17T11:11:14.894581Z'
                    required: true
                    verification_url: >-
                      https://your-app.auth.didit.me/verify/?verification=1nSX7HJCXAP9XPA9AeJfQxIuPk2GkG0dGSOzCA2Zpww
                    expires_in: 1800
        '400':
          description: >-
            Поле отсутствует или недействительно. `return_to:
            invalid_redirect_uri` означает, что применяется правило, а
            `return_to` не является одним из URI перенаправления приложения.
          headers:
            Cache-Control:
              description: 'Всегда `no-store`: никогда не кэшируйте этот ответ.'
              schema:
                type: string
                example: no-store
            Pragma:
              description: Всегда `no-cache`.
              schema:
                type: string
                example: no-cache
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FieldErrors'
              examples:
                MissingAmount:
                  summary: Выплата без указания суммы
                  value:
                    amount:
                      - required
                InvalidReturnTo:
                  summary: Незарегистрированный return_to
                  value:
                    return_to: invalid_redirect_uri
                UnknownAction:
                  summary: Неподдерживаемое действие
                  value:
                    action:
                      - '"withdraw" is not a valid choice.'
        '401':
          $ref: '#/components/responses/InvalidToken'
        '403':
          $ref: '#/components/responses/OriginNotAllowed'
        '404':
          $ref: '#/components/responses/ApplicationNotFound'
        '429':
          $ref: '#/components/responses/RateLimited'
        '503':
          $ref: '#/components/responses/TemporarilyUnavailable'
      security:
        - AccessToken: []
components:
  schemas:
    StepUpRequest:
      type: object
      description: Конфиденциальное действие, которое человек собирается совершить.
      required:
        - action
        - return_to
      additionalProperties: false
      properties:
        action:
          type: string
          enum:
            - payout
            - bank
            - contact
          description: >-
            `payout` (вывод средств или перевод), `bank` (добавление или
            изменение банковского счёта) или `contact` (изменение электронной
            почты или номера телефона). К выводу средств также применяется
            правило нового устройства.
        amount:
          type: string
          pattern: ^[0-9]{1,16}(\.[0-9]{1,2})?$
          description: >-
            Обязательно для `payout`: сумма с точностью до двух знаков после
            запятой. Число JSON также принимается.
          example: '900.00'
        currency:
          type: string
          pattern: ^[A-Z]{3}$
          description: >-
            Код ISO 4217 для `amount`. По умолчанию совпадает с валютой правила
            выплаты; выплата в другой валюте проверяется всегда.
          example: USD
        return_to:
          type: string
          maxLength: 2048
          description: >-
            Куда возвращается пользователь после прохождения верификации с
            добавлением параметров `step_up=<id>&status=approved`. Если
            действует правило, адрес должен входить в список redirect URI
            приложения; если правила нет, проверка не выполняется.
          example: https://app.example.com/payouts/confirm
    StepUpNotRequired:
      type: object
      description: 'Ни одно правило не применимо: выполните действие.'
      required:
        - required
      properties:
        required:
          type: boolean
          enum:
            - false
    StepUpRequired:
      description: >-
        Новая дополнительная проверка. Направьте пользователя по адресу
        `verification_url`.
      allOf:
        - $ref: '#/components/schemas/StepUp'
        - type: object
          required:
            - required
            - verification_url
            - expires_in
          properties:
            required:
              type: boolean
              enum:
                - true
            verification_url:
              type: string
              format: uri
              description: >-
                Размещённая страница, на которой пользователь проходит
                верификацию; откройте её в браузере пользователя. Она действует
                до тех пор, пока дополнительная проверка (step-up) не будет
                одобрена или не истечёт, поэтому пользователь, которому было
                отказано, может повторить попытку с неё.
              example: >-
                https://your-app.auth.didit.me/verify/?verification=1nSX7HJCXAP9XPA9AeJfQxIuPk2GkG0dGSOzCA2Zpww
            expires_in:
              type: integer
              description: >-
                Количество секунд, в течение которых дополнительная проверка
                остаётся открытой: 1800.
              example: 1800
    FieldErrors:
      title: Field errors
      type: object
      description: >-
        Ошибки валидации по полям. Значение представляет собой список сообщений
        или один код (`unknown_field`, `invalid_redirect_uri`). Поле
        `non_field_errors` содержит ошибки правил, охватывающих несколько полей.
      additionalProperties:
        oneOf:
          - type: string
          - type: array
            items:
              type: string
    StepUp:
      type: object
      description: Верификация, которую человек должен пройти перед совершением действия.
      required:
        - id
        - rule
        - method
        - status
        - level
        - amount
        - currency
        - created_at
        - completed_at
        - expires_at
      properties:
        id:
          type: string
          format: uuid
          example: 94efc2c3-ca84-42fe-900b-6fb61669a7a1
        rule:
          type: string
          enum:
            - payout
            - device
            - bank
            - contact
          description: >-
            Правило, которое запросило это действие. Если применимо несколько
            правил, выбирается правило с самым строгим методом.
          example: payout
        method:
          type: string
          enum:
            - liveness
            - selfie
            - full_id
          description: >-
            Что делает пользователь: `liveness`, `selfie` (проверка живости со
            сравнением с лицом, которое уже есть у Didit) или `full_id`
            (документ и селфи). Если у Didit ещё нет лица пользователя, `selfie`
            переходит в `full_id`, как только пользователь открывает
            `verification_url`.
          example: selfie
        status:
          type: string
          enum:
            - pending
            - review
            - approved
            - declined
            - expired
            - superseded
          description: >-
            Действуйте только при статусе `approved`. Статус `review` ожидает
            проверки вашей командой. Статус `declined` не является
            окончательным, пока действует `verification_url`: пользователь может
            повторить попытку, и повторная проверка вернётся в статус `pending`.
            Статус `superseded` означает, что другая проверка перехватила эту
            верификацию либо результат относился не к этой повторной проверке:
            создайте новую.
          example: pending
        level:
          type: string
          nullable: true
          enum:
            - liveness
            - liveness_face_match
            - full_id
            - null
          description: Уровень, достигнутый верификацией после её одобрения.
          example: null
        amount:
          type: string
          nullable: true
          description: Сумма выплаты, два знака после запятой.
          example: '900.00'
        currency:
          type: string
          nullable: true
          example: USD
        created_at:
          type: string
          format: date-time
          example: '2026-10-17T10:41:14.894632Z'
        completed_at:
          type: string
          format: date-time
          nullable: true
          example: null
        expires_at:
          type: string
          format: date-time
          description: >-
            30 минут после создания. При чтении step-up сначала запрашивается
            любой результат, которого достигла его верификация, поэтому по
            истечении этого времени он всё ещё может возвращать `approved`,
            `review` или `declined`; если результат всё ещё `pending`,
            возвращается `expired`.
          example: '2026-10-17T11:11:14.894581Z'
    Detail:
      type: object
      required:
        - detail
      properties:
        detail:
          type: string
          example: invalid_token
    OAuthError:
      title: OAuth error
      type: object
      description: Ошибка OAuth (RFC 6749, раздел 5.2) или ошибка сервиса.
      required:
        - error
      properties:
        error:
          type: string
          example: invalid_grant
  responses:
    InvalidToken:
      description: >-
        Токен доступа отсутствует, некорректен, истёк, подписан другим эмитентом
        или ключом, является ID-токеном, токеном агента или заменён токеном
        обновления; либо его сессия была отозвана, завершилась по неактивности,
        превысила срок жизни или больше не соответствует вашей политике MFA,
        либо пользователь был заблокирован или его email больше не подтверждён.
        Отправьте пользователя на повторный вход.
      headers:
        WWW-Authenticate:
          description: '`Bearer`.'
          schema:
            type: string
            example: Bearer
        Cache-Control:
          description: 'Всегда `no-store`: никогда не кэшируйте этот ответ.'
          schema:
            type: string
            example: no-store
        Pragma:
          description: Всегда `no-cache`.
          schema:
            type: string
            example: no-cache
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Detail'
          examples:
            InvalidToken:
              summary: Отклонённый access token
              value:
                detail: invalid_token
    OriginNotAllowed:
      description: >-
        Запрос содержал заголовок `Origin`, который не принадлежит приложению и
        не входит в его список разрешённых источников. Серверные запросы не
        отправляют `Origin`.
      headers:
        Cache-Control:
          description: 'Всегда `no-store`: никогда не кэшируйте этот ответ.'
          schema:
            type: string
            example: no-store
        Pragma:
          description: Всегда `no-cache`.
          schema:
            type: string
            example: no-cache
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Detail'
          examples:
            OriginNotAllowed:
              summary: Источник (origin) не разрешен
              value:
                detail: origin_not_allowed
    ApplicationNotFound:
      description: >-
        Адрес принадлежит приложению, но Authentication для него не активна; для
        адреса `apx.didit.me` идентификатор приложения неизвестен. Запрос к
        адресу, не принадлежащему ни одному приложению, отклоняется до того, как
        достигнет endpoint, и этот ответ возвращается не в формате JSON.
      headers:
        Cache-Control:
          description: 'Всегда `no-store`: никогда не кэшируйте этот ответ.'
          schema:
            type: string
            example: no-store
        Pragma:
          description: Всегда `no-cache`.
          schema:
            type: string
            example: no-cache
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Detail'
          examples:
            ApplicationNotFound:
              summary: Неизвестное приложение
              value:
                detail: No Configuration matches the given query.
    RateLimited:
      description: >-
        Слишком много запросов с этого IP-адреса для данного endpoint, либо при
        вызове `POST` или `DELETE` исчерпан лимит защиты от ботов. Ничего не
        было выполнено: подождите количество секунд, указанное в `Retry-After`,
        затем повторите попытку.
      headers:
        Retry-After:
          description: Количество секунд ожидания перед повторной попыткой.
          schema:
            type: integer
            example: 60
        Cache-Control:
          description: 'Всегда `no-store`: никогда не кэшируйте этот ответ.'
          schema:
            type: string
            example: no-store
        Pragma:
          description: Всегда `no-cache`.
          schema:
            type: string
            example: no-cache
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Detail'
          examples:
            RateLimited:
              summary: Лимит запросов к endpoint
              value:
                detail: >-
                  Too many requests from this IP address. Please wait before
                  trying again. Expected available in 60 seconds.
            BotProtection:
              summary: Лимит защиты от ботов (POST и DELETE)
              value:
                detail: rate_limited Expected available in 2 seconds.
    TemporarilyUnavailable:
      description: >-
        Сервис, от которого зависит запрос, временно недоступен. Повторите
        попытку с задержкой.
      headers:
        Cache-Control:
          description: 'Всегда `no-store`: никогда не кэшируйте этот ответ.'
          schema:
            type: string
            example: no-store
        Pragma:
          description: Всегда `no-cache`.
          schema:
            type: string
            example: no-cache
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/OAuthError'
          examples:
            TemporarilyUnavailable:
              summary: Повторить попытку позже
              value:
                error: temporarily_unavailable
  securitySchemes:
    AccessToken:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: >-
        Токен доступа человека из `POST /token/`: JWT с алгоритмом ES256 и
        заголовком `typ: at+jwt`, действующий не более 5 минут. Не ваш API-ключ
        Didit.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.