openapi: 3.0.4 info: title: Private Captcha - OpenAPI 3.0 description: |- Private Captcha is an independent, privacy-first, self-hostable Proof-of-Work CAPTCHA service made in EU. Instead of asking users to solve complex puzzles or track their behavior, Private Captcha solves an invisible cryptographic task in the background. The system automatically adjusts the task difficulty, ensuring smooth access for real users while making it too costly for bots to attempt. Cryptographic task provides equal security regardless of bot's intelligence level, making it effective even as AI technology improves. Some useful links: - [Private Captcha repository](https://github.com/PrivateCaptcha/PrivateCaptcha) - [Official Documentation](https://docs.privatecaptcha.com) termsOfService: https://privatecaptcha.com/legal/terms-and-conditions/ contact: email: hello@privatecaptcha.com license: name: PolyForm Noncommercial License 1.0.0 url: https://polyformproject.org/licenses/noncommercial/1.0.0 version: 1.0.0 externalDocs: description: Find out more about Private Captcha url: https://privatecaptcha.com servers: - url: https://api.privatecaptcha.com - url: https://api.eu.privatecaptcha.com tags: - name: puzzle description: Fetch Puzzle for client widget - name: verify description: Verify puzzle solutions externalDocs: description: Find out more about Verify API url: https://docs.privatecaptcha.com/docs/reference/verify-api/ - name: org description: Organization management - name: properties description: Property management - name: task description: Async task management paths: /puzzle: get: tags: - puzzle summary: Retrieve a new puzzle description: Returns a unique serialized signed puzzle for the widget operationId: get-puzzle parameters: - name: sitekey in: query description: Property id for which the puzzle is requested required: true schema: type: string example: "aaaaaaaabbbbccccddddeeeeeeeeeeee" - name: Origin in: header description: Domain that corresponds to the Property sitekey schema: type: string example: "example.com" responses: "200": description: Puzzle created content: text/plain: schema: type: string example: "Aaqqqqq7u8zM3d3u7u7u7u4AAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAA=.AQCiRYnFLBXoqfEYUz7Up+ktTXhxXgw=" headers: X-Rate-Limit: description: calls per second allowed to the user schema: type: integer format: int32 X-RateLimit-Remaining: description: number of operations remaining in the given time slot schema: type: integer format: int32 X-RateLimit-Reset: description: number of seconds until rate limit is reset schema: type: integer format: int32 Retry-After: description: recommended number of seconds to wait until retrying schema: type: integer format: int32 "400": description: Invalid sitekey value or Origin header is missing "403": description: Sitekey does not exist, Origin does not correspond to property "429": description: Rate limited "500": description: Unexpected internal error /verify: post: tags: - verify summary: Verify puzzle solution (official API) description: API to verify form field with client solution used by SDKs and API clients operationId: post-verify parameters: - name: X-PC-Sitekey in: header description: "(optional) Sitekey of the property to ensure the solution is for" required: false schema: type: string requestBody: description: Solution content: text/plain: schema: type: string required: true responses: "200": description: Successful operation content: application/json: schema: $ref: "#/components/schemas/VerifyResponse" headers: X-Rate-Limit: description: calls per second allowed to the API key schema: type: integer format: int32 X-RateLimit-Remaining: description: number of operations remaining in the given time slot schema: type: integer format: int32 X-RateLimit-Reset: description: number of seconds until rate limit is reset schema: type: integer format: int32 Retry-After: description: recommended number of seconds to wait until retrying schema: type: integer format: int32 "400": description: Invalid API key format "403": description: API key not found "429": description: API key rate limited security: - ApiKeyAuth: [] /siteverify: post: tags: - verify summary: Verify puzzle solution (reCAPCHA-compatible) description: reCAPCHA-compatible API to verify form field with client solution operationId: post-siteverify requestBody: content: application/x-www-form-urlencoded: schema: type: object required: - secret - response properties: secret: description: API key (auth) type: string response: description: Solution of the solved captcha type: string sitekey: description: (optional) Sitekey of the property to ensure the solution is for type: string required: true responses: "200": description: Successful operation content: application/json: schema: $ref: "#/components/schemas/SiteVerifyResponse" headers: X-Rate-Limit: description: calls per second allowed to the API key schema: type: integer format: int32 X-RateLimit-Remaining: description: number of operations remaining in the given time slot schema: type: integer format: int32 X-RateLimit-Reset: description: number of seconds until rate limit is reset schema: type: integer format: int32 Retry-After: description: recommended number of seconds to wait until retrying schema: type: integer format: int32 "400": description: Invalid API key format "403": description: API key not found "429": description: API key rate limited /asynctask/{id}: get: tags: - task summary: Get async task status operationId: get-async-task parameters: - name: id in: path required: true schema: type: string responses: "200": description: Task status content: application/json: schema: allOf: - $ref: "#/components/schemas/APIResponse" - type: object properties: data: $ref: "#/components/schemas/AsyncTaskResultOutput" "403": description: API key not valid or user does does not have right to access this async task "429": description: API key rate limited security: - ApiKeyAuth: [] /orgs: get: tags: - org summary: Get user organizations operationId: get-user-orgs responses: "200": description: List of organizations content: application/json: schema: allOf: - $ref: "#/components/schemas/APIResponse" - type: object properties: data: type: array items: $ref: "#/components/schemas/OrgOutput" "400": description: Invalid API key format "403": description: API key not found "429": description: API key rate limited security: - ApiKeyAuth: [] /org: post: tags: - org summary: Create new organization operationId: create-org requestBody: content: application/json: schema: $ref: "#/components/schemas/OrgInput" responses: "200": description: Organization created content: application/json: schema: allOf: - $ref: "#/components/schemas/APIResponse" - type: object properties: data: $ref: "#/components/schemas/OrgOutput" "400": description: Invalid API key format "403": description: API key not found "429": description: API key rate limited security: - ApiKeyAuth: [] put: tags: - org summary: Update organization operationId: update-org requestBody: content: application/json: schema: $ref: "#/components/schemas/OrgInput" responses: "200": description: Organization updated content: application/json: schema: allOf: - $ref: "#/components/schemas/APIResponse" - type: object properties: data: $ref: "#/components/schemas/OrgOutput" "400": description: Invalid API key format or invalid organization ID "403": description: API key not found or user is not organization owner "429": description: API key rate limited security: - ApiKeyAuth: [] delete: tags: - org summary: Delete organization operationId: delete-org requestBody: content: application/json: schema: $ref: "#/components/schemas/OrgInput" responses: "200": description: Organization deleted content: application/json: schema: $ref: "#/components/schemas/APIResponse" "400": description: Invalid API key format or invalid organization ID "403": description: API key not found or user is not organization owner "429": description: API key rate limited security: - ApiKeyAuth: [] /org/{org_id}/properties: get: tags: - properties summary: Get organization properties operationId: get-org-properties parameters: - name: org_id in: path required: true schema: type: string - name: page in: query schema: type: integer - name: per_page in: query schema: type: integer responses: "200": description: List of properties content: application/json: schema: allOf: - $ref: "#/components/schemas/APIResponse" - type: object properties: data: type: array items: $ref: "#/components/schemas/OrgPropertyOutput" "400": description: Invalid API key format or invalid organization ID "403": description: API key not found or user is not a member or owner of organization "429": description: API key rate limited security: - ApiKeyAuth: [] post: tags: - properties summary: Create properties operationId: create-properties parameters: - name: org_id in: path required: true schema: type: string requestBody: content: application/json: schema: type: array items: $ref: "#/components/schemas/CreatePropertyInput" responses: "200": description: Creation task started content: application/json: schema: allOf: - $ref: "#/components/schemas/APIResponse" - type: object properties: data: $ref: "#/components/schemas/AsyncTaskOutput" "400": description: Invalid API key format or invalid organization ID "403": description: API key not found or user is not an owner of organization "429": description: API key rate limited security: - ApiKeyAuth: [] /properties: delete: tags: - properties summary: Delete properties operationId: delete-properties requestBody: content: application/json: schema: type: array items: type: string responses: "200": description: Deletion task started content: application/json: schema: allOf: - $ref: "#/components/schemas/APIResponse" - type: object properties: data: $ref: "#/components/schemas/AsyncTaskOutput" "400": description: Invalid API key format or invalid body payload "403": description: API key not found "429": description: API key rate limited security: - ApiKeyAuth: [] put: tags: - properties summary: Update properties operationId: update-properties requestBody: content: application/json: schema: type: array items: $ref: "#/components/schemas/UpdatePropertyInput" responses: "200": description: Update task started content: application/json: schema: allOf: - $ref: "#/components/schemas/APIResponse" - type: object properties: data: $ref: "#/components/schemas/AsyncTaskOutput" "400": description: Invalid API key format or invalid body payload "403": description: API key not found "429": description: API key rate limited security: - ApiKeyAuth: [] /org/{org_id}/property/{property_id}: get: tags: - properties summary: Get property details operationId: get-property parameters: - name: org_id in: path required: true schema: type: string - name: property_id in: path required: true schema: type: string responses: "200": description: Property details content: application/json: schema: allOf: - $ref: "#/components/schemas/APIResponse" - type: object properties: data: $ref: "#/components/schemas/PropertyOutput" "400": description: Invalid API key format, organization or property IDs "403": description: API key not found or user does not have access to this property in this organization "429": description: API key rate limited security: - ApiKeyAuth: [] components: schemas: SiteVerifyResponse: type: object required: - success - error-codes - challenge_ts - hostname properties: success: type: boolean error-codes: type: array items: $ref: "#/components/schemas/VerifyErrorCode" hostname: type: string example: example.com challenge_ts: type: string format: date-time example: "2009-11-10T23:00:00Z" score: type: number action: type: string VerifyErrorCode: type: string enum: - no-error - error-other - solution-duplicates - solution-invalid - solution-bad-format - puzzle-expired - property-invalid - property-owner-mismatch - solution-verified-before - property-test - maintenance-mode - integrity-error - org-scope-error VerifyResponse: type: object required: - success - code - timestamp - origin properties: success: type: boolean code: type: number origin: type: string example: example.com timestamp: type: string format: date-time example: "2009-11-10T23:00:00Z" APIResponse: type: object properties: meta: $ref: "#/components/schemas/ResponseMetadata" data: type: object pagination: $ref: "#/components/schemas/Pagination" required: - meta - data ResponseMetadata: type: object properties: code: type: integer example: 1000 request_id: type: string example: 9m4e2mr0ui3e8a215n4g description: type: string example: OK Pagination: type: object properties: page: type: integer example: 1 per_page: type: integer example: 50 has_more: type: boolean OrgInput: type: object properties: id: type: string example: ueRWrHqlki name: type: string example: "My Organization" OrgOutput: type: object properties: id: type: string example: XGfmWT7ZPI name: type: string example: "My Organization" PropertyGrowth: type: string enum: - constant - slow - medium - fast PropertySettings: type: object properties: name: type: string example: "Company Website" level: type: integer example: 95 growth: $ref: "#/components/schemas/PropertyGrowth" validity_seconds: type: integer example: 21600 allow_subdomains: type: boolean allow_localhost: type: boolean max_replay_count: type: integer example: 1 CreatePropertyInput: allOf: - type: object properties: domain: type: string example: "example.com" name: type: string example: "Company Website" UpdatePropertyInput: allOf: - $ref: "#/components/schemas/PropertySettings" - type: object properties: id: type: string example: t3hlMTu0XX PropertyOutput: allOf: - $ref: "#/components/schemas/PropertySettings" - type: object properties: id: type: string example: 0VgGggmbGa domain: type: string example: example.com sitekey: type: string example: 525e0ef5b9bc489f882274b3ca24b710 OrgPropertyOutput: type: object properties: id: type: string example: vDWtASYqrB name: type: string example: "Company Website" sitekey: type: string example: 288a919fa0424bc09ed0d935fdc93433 AsyncTaskOutput: type: object properties: id: type: string example: e3e6854e06944cf48f49f93abb5a527e AsyncTaskResultOutput: type: object properties: id: type: string example: e3e6854e06944cf48f49f93abb5a527e finished: type: boolean result: type: object securitySchemes: ApiKeyAuth: type: apiKey in: header name: X-Api-Key