{
  "openapi": "3.0.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",
    "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"
      }
    },
    "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"
                }
              }
            }
          },
          "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"
                    }
                  }
                }
              }
            }
          },
          "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"
                    }
                  }
                }
              }
            }
          },
          "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"
                    }
                  }
                }
              }
            }
          }
        },
        "tags": [
          "Acceptance"
        ],
        "security": [
          {
            "bearer": []
          }
        ]
      },
      "options": {
        "operationId": "preflight",
        "parameters": [],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "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": ""
          }
        },
        "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": ""
          }
        },
        "tags": [
          "Identity"
        ]
      }
    },
    "/v1/click/identity/verify/{sessionId}/status": {
      "post": {
        "operationId": "checkStatus",
        "parameters": [
          {
            "name": "sessionId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "tags": [
          "Identity"
        ]
      }
    }
  }
}