openapi: 3.1.0
info:
  title: Payrix Partner API
  version: 1.0.0-early-access
  description: |
    Универсальный API для подачи и отслеживания заявок из CRM, агентских платформ
    и агрегаторов. Доступ выдаётся индивидуально для тестового и боевого контуров.
  x-api-status: early-access
servers:
  - url: https://api-staging.payrix.ru
    description: Тестовый контур
  - url: https://api.payrix.ru
    description: Боевой контур
tags:
  - name: Offers
    description: Офферы, разрешённые конкретному партнёру
  - name: Applications
    description: Создание и чтение заявок
paths:
  /partner/v1/offers:
    get:
      tags: [Offers]
      operationId: listPartnerOffers
      summary: Получить доступные офферы
      security:
        - PartnerId: []
          ApiKey: []
      responses:
        '200':
          description: Список офферов
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Offer'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /partner/v1/applications:
    post:
      tags: [Applications]
      operationId: createPartnerApplication
      summary: Создать заявку
      description: |
        Создаёт одну публичную заявку и внутренние заявки по выбранным offer_id.
        Повтор с тем же external_id и тем же телом безопасен; изменённое тело вернёт 409.
      security:
        - PartnerId: []
          ApiKey: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateApplication'
      responses:
        '201':
          description: Заявка создана
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Application'
        '200':
          description: Идемпотентный повтор ранее принятого запроса
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Application'
        '400':
          $ref: '#/components/responses/ValidationError'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '409':
          description: external_id уже использован с другим телом
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '413':
          description: Тело запроса превышает 1 МиБ
        '422':
          description: Один или несколько офферов недоступны
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          $ref: '#/components/responses/TooManyRequests'
  /partner/v1/applications/{application_id}:
    get:
      tags: [Applications]
      operationId: getPartnerApplication
      summary: Получить заявку и статусы офферов
      security:
        - PartnerId: []
          ApiKey: []
      parameters:
        - name: application_id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Заявка
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Application'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          description: Заявка не найдена или принадлежит другому партнёру
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          $ref: '#/components/responses/TooManyRequests'
components:
  securitySchemes:
    PartnerId:
      type: apiKey
      in: header
      name: X-Partner-Id
    ApiKey:
      type: apiKey
      in: header
      name: X-Api-Key
  responses:
    Unauthorized:
      description: Ключи отсутствуют или неверны
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Forbidden:
      description: Недостаточно scope или нет доступа к офферу
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    ValidationError:
      description: Ошибка валидации запроса
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    TooManyRequests:
      description: Превышен лимит запросов; повторите запрос позже
  schemas:
    Offer:
      type: object
      required: [id, name, product, provider]
      properties:
        id:
          type: string
          examples: [working-capital]
        name:
          type: string
        product:
          type: string
        provider:
          type: string
        min_amount:
          type: integer
          format: int64
          nullable: true
        max_amount:
          type: integer
          format: int64
          nullable: true
        min_term:
          type: integer
          nullable: true
        max_term:
          type: integer
          nullable: true
    CreateApplication:
      type: object
      required: [external_id, offer_ids, borrower, financing, consents]
      properties:
        external_id:
          type: string
          maxLength: 120
          description: Уникальный идентификатор заявки в системе партнёра
        offer_ids:
          type: array
          minItems: 1
          maxItems: 10
          uniqueItems: true
          items:
            type: string
        borrower:
          $ref: '#/components/schemas/Borrower'
        financing:
          $ref: '#/components/schemas/Financing'
        consents:
          $ref: '#/components/schemas/Consents'
        fields:
          type: object
          maxProperties: 100
          additionalProperties:
            type: string
            maxLength: 4000
    Borrower:
      type: object
      required: [inn, name]
      properties:
        inn:
          type: string
          pattern: '^(?:[0-9]{10}|[0-9]{12})$'
        name:
          type: string
          maxLength: 300
        email:
          type: string
          format: email
        phone:
          type: string
    Financing:
      type: object
      required: [amount]
      properties:
        amount:
          type: integer
          minimum: 1
          maximum: 2147483647
          description: Сумма в рублях
        term_months:
          type: integer
          minimum: 1
          maximum: 600
        purpose:
          type: string
    Consents:
      type: object
      required: [personal_data]
      properties:
        personal_data:
          type: boolean
          const: true
        credit_history:
          type: boolean
          default: false
    Application:
      type: object
      required: [application_id, external_id, status, created_at, updated_at, idempotent_replay, offers]
      properties:
        application_id:
          type: string
          format: uuid
        external_id:
          type: string
        status:
          $ref: '#/components/schemas/ApplicationStatus'
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
        idempotent_replay:
          type: boolean
        offers:
          type: array
          items:
            type: object
            required: [offer_id, status]
            properties:
              offer_id:
                type: string
              status:
                $ref: '#/components/schemas/ApplicationStatus'
    ApplicationStatus:
      type: string
      enum:
        - draft
        - processing
        - documents_required
        - offer_available
        - signing
        - completed
        - declined
        - withdrawn
        - action_required
    Error:
      type: object
      required: [error, message]
      properties:
        error:
          type: string
        message:
          type: string
        field:
          type: string
          nullable: true
