openapi: 3.1.0
info:
  title: Propper Click Accept API
  version: '1.0'
  description: >-
    The Propper Click Accept API records consent acceptances with idempotent
    writes.

    When an end user agrees to a clickwrap or consent flow, the client SDK posts
    the acceptance to this API,

    which stores the record along with a cryptographically signed evidence
    bundle.


    ---


    ## Base URL


    `https://api.propper.ai/v1/click/accept`


    ## Authentication


    OAuth 2.0 Bearer token:


    ```

    Authorization: Bearer <access_token>

    ```


    ## OAuth Scopes


    - `click:admin` — Full administrative access

    - `click:read` — Read-only access to acceptance records


    ## Key Endpoints


    - **Acceptance** — Record and query consent acceptances

    - **Identity** — Resolve and manage end-user identity for acceptance records


    ---


    ## Request correlation


    Every response (success and error) includes an `x-request-id` header (a
    UUID) and a `traceparent` header (W3C Trace Context). Error bodies also
    carry the same id as `requestId`. Quote `x-request-id` when contacting
    support to pinpoint the exact request, and use it to correlate the API with
    your own logs. Send your own `traceparent` to tie a multi-call workflow
    under one trace.
  contact:
    name: Propper Support
    url: https://propper.ai
    email: support@propper.ai
tags:
  - name: Acceptance
    description: Record and query consent acceptances
  - name: Identity
    description: Resolve and manage end-user identity for acceptance records
servers:
  - url: https://api.propper.ai
    description: Production server
security:
  - bearer: []
components:
  securitySchemes:
    bearer:
      scheme: bearer
      bearerFormat: JWT
      type: http
      description: OAuth 2.0 Bearer token
  headers:
    X-Request-Id:
      schema:
        type: string
        format: uuid
      description: >-
        Correlation id for this request, returned on every response (success and
        error). Quote it when contacting support to pinpoint the exact request,
        and use it to correlate your own logs. It is the same 128-bit id as the
        trace-id segment of the `traceparent` header.
    traceparent:
      schema:
        type: string
      description: >-
        W3C Trace Context identifier for this request, returned on every
        response. Send your own `traceparent` on a request to have it adopted,
        so a multi-call workflow shares one trace. Format: `00-<32-hex
        trace-id>-<16-hex span-id>-<2-hex flags>`.
  schemas:
    IdentityAssertionDto:
      type: object
      properties:
        level:
          type: string
          description: Identity assertion level/method
          example: email
        method:
          type: string
          description: Identity assertion method
          enum:
            - otp
            - sso
            - webauthn
            - email
            - simple
          example: email
        value:
          type: string
          description: Raw assertion data to be hashed (will not be stored)
          example: user@example.com:verification-code-123
        email:
          type: string
          description: User email
          example: user@example.com
        name:
          type: string
          description: User name
          example: John Doe
        company:
          type: string
          description: User company
          example: Acme Corp
        verifiedAt:
          type: number
          description: Verification timestamp
          example: 1234567890
        sessionId:
          type: string
          description: Verification session ID for OTP/2FA methods
          example: 550e8400-e29b-41d4-a716-446655440003
        verificationToken:
          type: string
          description: Verification token proving identity was verified
          example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
    AcceptConsentDto:
      type: object
      properties:
        templateVersionId:
          type: string
          description: Template version UUID
          example: 550e8400-e29b-41d4-a716-446655440000
        deploymentId:
          type: string
          description: Deployment ID that served the consent form
          example: 550e8400-e29b-41d4-a716-446655440002
        checksum:
          type: string
          description: Template version checksum (SHA-256 hash)
          example: a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3
        consentMethod:
          type: string
          description: Consent method used for acceptance
          enum:
            - BUTTON
            - CHECKBOX
            - SCROLL
            - SIGNIN_WRAP
          example: BUTTON
        sessionId:
          type: string
          description: Optional session ID
          example: 550e8400-e29b-41d4-a716-446655440001
        userId:
          type: string
          description: Optional user ID
          example: user123
        email:
          type: string
          description: Optional email address
          example: user@example.com
        identityAssertion:
          description: Identity assertion for proof of acceptance
          allOf:
            - $ref: '#/components/schemas/IdentityAssertionDto'
        identityAssertions:
          description: Identity assertions array for proof of acceptance
          type: array
          items:
            $ref: '#/components/schemas/IdentityAssertionDto'
        variant:
          type: string
          description: Optional variant identifier
          example: A
        capturedHtml:
          type: string
          description: Captured HTML from SDK for evidence generation
          example: <div class="propper-modal">...</div>
        templateSnapshot:
          type: object
          description: Template snapshot (HTML + CSS) for screenshot generation
          example:
            html: <div>...</div>
            css: .modal { ... }
        browserInfo:
          type: object
          description: Browser information for screenshot generation
          example:
            userAgent: Mozilla/5.0...
            viewport:
              width: 1920
              height: 1080
        metadata:
          type: object
          description: Additional metadata including optional container dimensions from SDK
          example:
            source: mobile-app
            version: 1.2.3
            containerDimensions:
              width: 800
              height: 600
            verificationSessionId: 550e8400-e29b-41d4-a716-446655440003
            verificationToken: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
      required:
        - templateVersionId
        - deploymentId
        - checksum
        - consentMethod
    AcceptConsentResponseDto:
      type: object
      properties:
        receiptId:
          type: string
          description: Receipt ID for the acceptance
          example: 550e8400-e29b-41d4-a716-446655440002
        acceptedAt:
          type: string
          description: Timestamp of acceptance in ISO 8601 format
          example: '2024-01-15T10:30:00.000Z'
        message:
          type: string
          description: Success message
          example: Acceptance recorded successfully
      required:
        - receiptId
        - acceptedAt
        - message
    StartVerificationDto:
      type: object
      properties: {}
    VerifyOTPDto:
      type: object
      properties: {}
paths:
  /v1/click/accept:
    post:
      operationId: acceptConsent
      summary: Accept consent
      description: Record consent acceptance with idempotent writes and Pub/Sub integration
      parameters:
        - name: X-Idempotency-Key
          in: header
          description: Unique key to prevent duplicate requests (UUID recommended)
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AcceptConsentDto'
      responses:
        '201':
          description: Consent acceptance recorded successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AcceptConsentResponseDto'
          headers:
            X-Request-Id: &ref_0
              $ref: '#/components/headers/X-Request-Id'
            traceparent: &ref_1
              $ref: '#/components/headers/traceparent'
        '400':
          description: Invalid request data or checksum mismatch
          content:
            application/json:
              schema:
                type: object
                properties:
                  statusCode:
                    type: number
                    example: 400
                  message:
                    type: string
                    example: Template version checksum mismatch
                  error:
                    type: string
                    example: Bad Request
          headers:
            X-Request-Id: *ref_0
            traceparent: *ref_1
        '401':
          description: Invalid authentication credentials
          content:
            application/json:
              schema:
                type: object
                properties:
                  statusCode:
                    type: number
                    example: 401
                  message:
                    type: string
                    example: Invalid credentials
                  error:
                    type: string
                    example: Unauthorized
          headers:
            X-Request-Id: *ref_0
            traceparent: *ref_1
        '409':
          description: Request already being processed or duplicate
          content:
            application/json:
              schema:
                type: object
                properties:
                  statusCode:
                    type: number
                    example: 409
                  message:
                    type: string
                    example: Request is already being processed
                  error:
                    type: string
                    example: Conflict
          headers:
            X-Request-Id: *ref_0
            traceparent: *ref_1
      tags:
        - Acceptance
      security:
        - bearer: []
    options:
      operationId: preflight
      parameters: []
      responses:
        '200':
          description: ''
          headers:
            X-Request-Id: *ref_0
            traceparent: *ref_1
      tags:
        - Acceptance
      security: []
  /v1/click/identity/verify/start:
    post:
      operationId: startVerification
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/StartVerificationDto'
      responses:
        '200':
          description: ''
          headers:
            X-Request-Id: *ref_0
            traceparent: *ref_1
      tags:
        - Identity
  /v1/click/identity/verify/{sessionId}/otp:
    post:
      operationId: verifyOTP
      parameters:
        - name: sessionId
          required: true
          in: path
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/VerifyOTPDto'
      responses:
        '200':
          description: ''
          headers:
            X-Request-Id: *ref_0
            traceparent: *ref_1
      tags:
        - Identity
  /v1/click/identity/verify/{sessionId}/status:
    post:
      operationId: checkStatus
      parameters:
        - name: sessionId
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: ''
          headers:
            X-Request-Id: *ref_0
            traceparent: *ref_1
      tags:
        - Identity
