{
  "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.\nWhen an end user agrees to a clickwrap or consent flow, the client SDK posts the acceptance to this API,\nwhich stores the record along with a cryptographically signed evidence bundle.\n\n---\n\n## Base URL\n\n`https://api.propper.ai/v1/click/accept`\n\n## Authentication\n\nOAuth 2.0 Bearer token:\n\n```\nAuthorization: Bearer <access_token>\n```\n\n## OAuth Scopes\n\n- `click:admin` — Full administrative access\n- `click:read` — Read-only access to acceptance records\n\n## Key Endpoints\n\n- **Acceptance** — Record and query consent acceptances\n- **Identity** — Resolve and manage end-user identity for acceptance records\n\n---\n\n## Request correlation\n\nEvery 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": "#/components/headers/X-Request-Id"
              },
              "traceparent": {
                "$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": "#/components/headers/X-Request-Id"
              },
              "traceparent": {
                "$ref": "#/components/headers/traceparent"
              }
            }
          },
          "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": "#/components/headers/X-Request-Id"
              },
              "traceparent": {
                "$ref": "#/components/headers/traceparent"
              }
            }
          },
          "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": "#/components/headers/X-Request-Id"
              },
              "traceparent": {
                "$ref": "#/components/headers/traceparent"
              }
            }
          }
        },
        "tags": [
          "Acceptance"
        ],
        "security": [
          {
            "bearer": []
          }
        ]
      },
      "options": {
        "operationId": "preflight",
        "parameters": [],
        "responses": {
          "200": {
            "description": "",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "traceparent": {
                "$ref": "#/components/headers/traceparent"
              }
            }
          }
        },
        "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": "#/components/headers/X-Request-Id"
              },
              "traceparent": {
                "$ref": "#/components/headers/traceparent"
              }
            }
          }
        },
        "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": "#/components/headers/X-Request-Id"
              },
              "traceparent": {
                "$ref": "#/components/headers/traceparent"
              }
            }
          }
        },
        "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": "#/components/headers/X-Request-Id"
              },
              "traceparent": {
                "$ref": "#/components/headers/traceparent"
              }
            }
          }
        },
        "tags": [
          "Identity"
        ]
      }
    }
  }
}