{"openapi":"3.1.0","jsonSchemaDialect":"https://json-schema.org/draft/2020-12/schema","info":{"title":"Proofwell API","version":"1.0.0","description":"JSON over HTTPS. Authenticate with an API key or an OAuth 2.0 access token in the Authorization header (Bearer); credentials anywhere else (query string, body) are refused with 400 credentials_in_url.\n\nAccess tokens: POST /v1/oauth/token with grant_type=client_credentials; client_id is the key's client id (pwc_…) and client_secret the key itself (pk_live_…), as HTTP Basic or form fields. Tokens last 60 minutes and die when the key is revoked, blocked, rotated or expires.\n\nKeys can be limited to IP addresses or CIDR ranges (up to 20); other addresses get 403 ip_not_allowed. New keys expire after 365 days unless the company Owner chooses never.\n\nLimits: 10 requests per second per key; per month Pro 100000, Enterprise 1000000 (or a custom limit). 20 failed authentications per minute from one address → 429 for that address. Request bodies up to 64 KB, application/json only."},"servers":[{"url":"https://api.proofwell.io"}],"tags":[{"name":"Authentication"},{"name":"Businesses"},{"name":"Reviews"},{"name":"Invitations"},{"name":"Products"},{"name":"Webhooks"},{"name":"Meta"}],"security":[{"ApiKey":[]},{"OAuth2":[]}],"paths":{"/v1/oauth/token":{"post":{"operationId":"createAccessToken","tags":["Authentication"],"summary":"OAuth 2.0 client credentials (RFC 6749 §4.4): swap client_id + client_secret (the API key) for a 1-hour access token.","security":[],"requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"grant_type":{"type":"string","const":"client_credentials"},"scope":{"description":"Space-separated scopes; must be a subset of the key's. Default: all of the key's scopes.","type":"string","maxLength":500},"client_id":{"description":"With client_secret, if HTTP Basic is not used.","type":"string","maxLength":64},"client_secret":{"description":"The API key (pk_live_…).","type":"string","maxLength":128}},"required":["grant_type"]}}}},"responses":{"200":{"description":"Access token issued.","headers":{"Cache-Control":{"schema":{"type":"string","const":"no-store"}},"Pragma":{"schema":{"type":"string","const":"no-cache"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenResponse"}}}},"400":{"description":"invalid_request, invalid_grant, unauthorized_client, unsupported_grant_type or invalid_scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"401":{"description":"invalid_client (with WWW-Authenticate: Basic)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"415":{"description":"invalid_request, invalid_grant, unauthorized_client, unsupported_grant_type or invalid_scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"429":{"description":"Too many failed authentications from this address, or too many tokens for this key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}}}}},"/v1/openapi.json":{"get":{"operationId":"getOpenApi","tags":["Meta"],"summary":"This OpenAPI 3.1 document.","security":[],"responses":{"200":{"description":"The document.","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/v1/businesses/me":{"get":{"operationId":"getMe","tags":["Businesses"],"summary":"The business(es) this key or token can use, and its permissions.","security":[{"ApiKey":[]},{"OAuth2":[]}],"responses":{"200":{"description":"The first business, the key and every business.","headers":{"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"RateLimit-Monthly-Limit":{"$ref":"#/components/headers/RateLimit-Monthly-Limit"},"RateLimit-Monthly-Remaining":{"$ref":"#/components/headers/RateLimit-Monthly-Remaining"},"Request-Id":{"$ref":"#/components/headers/Request-Id"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Me"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/v1/businesses/{id}/score":{"get":{"operationId":"getScore","tags":["Businesses"],"summary":"ProofScore, star distribution and proof share of one business.","security":[{"ApiKey":["score:read"]},{"OAuth2":["score:read"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Business id (biz_…).","schema":{"type":"string"}}],"responses":{"200":{"description":"The score.","headers":{"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"RateLimit-Monthly-Limit":{"$ref":"#/components/headers/RateLimit-Monthly-Limit"},"RateLimit-Monthly-Remaining":{"$ref":"#/components/headers/RateLimit-Monthly-Remaining"},"Request-Id":{"$ref":"#/components/headers/Request-Id"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Score"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/v1/reviews":{"get":{"operationId":"listReviews","tags":["Reviews"],"summary":"Published reviews of your businesses, newest first, in their original language.","security":[{"ApiKey":["reviews:read"]},{"OAuth2":["reviews:read"]}],"parameters":[{"name":"stars","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":5}},{"name":"proof","in":"query","required":false,"schema":{"type":"string","enum":["transaction","invited","identity","after_review","imported","unverified"]}},{"name":"since","in":"query","required":false,"schema":{"type":"string","format":"date-time"}},{"name":"language","in":"query","required":false,"schema":{"type":"string","pattern":"^[a-z]{2,3}(-[A-Za-z0-9]{2,8})?$"}},{"name":"limit","in":"query","required":false,"description":"Page size (default 20, at most 100).","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","required":false,"description":"next_cursor from the previous page.","schema":{"type":"string","maxLength":200}},{"name":"business","in":"query","required":false,"description":"Business id (biz_…); needed when the key can use several.","schema":{"type":"string","maxLength":200}}],"responses":{"200":{"description":"A page of reviews.","headers":{"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"RateLimit-Monthly-Limit":{"$ref":"#/components/headers/RateLimit-Monthly-Limit"},"RateLimit-Monthly-Remaining":{"$ref":"#/components/headers/RateLimit-Monthly-Remaining"},"Request-Id":{"$ref":"#/components/headers/Request-Id"}},"content":{"application/json":{"schema":{"type":"object","required":["data","next_cursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Review"}},"next_cursor":{"type":["string","null"],"description":"Pass as cursor for the next page; null at the end."}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/v1/reviews/{id}":{"get":{"operationId":"getReview","tags":["Reviews"],"summary":"One published review.","security":[{"ApiKey":["reviews:read"]},{"OAuth2":["reviews:read"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Public id with its prefix (e.g. rev_1042) or the number alone.","schema":{"type":"string"}}],"responses":{"200":{"description":"The review.","headers":{"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"RateLimit-Monthly-Limit":{"$ref":"#/components/headers/RateLimit-Monthly-Limit"},"RateLimit-Monthly-Remaining":{"$ref":"#/components/headers/RateLimit-Monthly-Remaining"},"Request-Id":{"$ref":"#/components/headers/Request-Id"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Review"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/v1/reviews/{id}/replies":{"post":{"operationId":"replyToReview","tags":["Reviews"],"summary":"Post a public reply as the business (recorded for the key creator).","security":[{"ApiKey":["replies:write"]},{"OAuth2":["replies:write"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Public id with its prefix (e.g. rev_1042) or the number alone.","schema":{"type":"string"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"text":{"type":"string","minLength":2,"maxLength":4000}},"required":["text"]}}}},"responses":{"201":{"description":"Reply posted.","headers":{"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"RateLimit-Monthly-Limit":{"$ref":"#/components/headers/RateLimit-Monthly-Limit"},"RateLimit-Monthly-Remaining":{"$ref":"#/components/headers/RateLimit-Monthly-Remaining"},"Request-Id":{"$ref":"#/components/headers/Request-Id"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Reply"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"415":{"$ref":"#/components/responses/UnsupportedMediaType"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/v1/invitations":{"post":{"operationId":"createInvitation","tags":["Invitations"],"summary":"Invite a customer to review (email or WhatsApp; there is no SMS). Every invitation rule applies.","security":[{"ApiKey":["invitations:write"]},{"OAuth2":["invitations:write"]}],"parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120},"email":{"anyOf":[{"type":"string","maxLength":254},{"type":"null"}]},"phone":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}]},"channel":{"default":"email","description":"\"email\" (default) or \"whatsapp\". There is no SMS.","type":"string"},"reference":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}]},"products":{"maxItems":20,"type":"array","items":{"type":"string","minLength":1,"maxLength":64}},"send_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"language":{"anyOf":[{"type":"string","pattern":"^[a-z]{2,3}(-[A-Za-z0-9]{2,8})?$"},{"type":"null"}]},"business":{"anyOf":[{"type":"string","maxLength":200,"description":"Business id (biz_…); needed when the key can use several."},{"type":"null"}]}},"required":["name"]}}}},"responses":{"201":{"description":"Invitation created (scheduled or sent).","headers":{"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"RateLimit-Monthly-Limit":{"$ref":"#/components/headers/RateLimit-Monthly-Limit"},"RateLimit-Monthly-Remaining":{"$ref":"#/components/headers/RateLimit-Monthly-Remaining"},"Request-Id":{"$ref":"#/components/headers/Request-Id"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Invitation"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"415":{"$ref":"#/components/responses/UnsupportedMediaType"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}}},"get":{"operationId":"listInvitations","tags":["Invitations"],"summary":"Invitations, newest first.","security":[{"ApiKey":["invitations:read"]},{"OAuth2":["invitations:read"]}],"parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["scheduled","sent","delivered","opened","clicked","reviewed","bounced","failed","unsubscribed","cancelled"]}},{"name":"limit","in":"query","required":false,"description":"Page size (default 20, at most 100).","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","required":false,"description":"next_cursor from the previous page.","schema":{"type":"string","maxLength":200}},{"name":"business","in":"query","required":false,"description":"Business id (biz_…); needed when the key can use several.","schema":{"type":"string","maxLength":200}}],"responses":{"200":{"description":"A page of invitations.","headers":{"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"RateLimit-Monthly-Limit":{"$ref":"#/components/headers/RateLimit-Monthly-Limit"},"RateLimit-Monthly-Remaining":{"$ref":"#/components/headers/RateLimit-Monthly-Remaining"},"Request-Id":{"$ref":"#/components/headers/Request-Id"}},"content":{"application/json":{"schema":{"type":"object","required":["data","next_cursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Invitation"}},"next_cursor":{"type":["string","null"],"description":"Pass as cursor for the next page; null at the end."}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/v1/invitations/{id}":{"get":{"operationId":"getInvitation","tags":["Invitations"],"summary":"One invitation.","security":[{"ApiKey":["invitations:read"]},{"OAuth2":["invitations:read"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Public id with its prefix (e.g. rev_1042) or the number alone.","schema":{"type":"string"}}],"responses":{"200":{"description":"The invitation.","headers":{"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"RateLimit-Monthly-Limit":{"$ref":"#/components/headers/RateLimit-Monthly-Limit"},"RateLimit-Monthly-Remaining":{"$ref":"#/components/headers/RateLimit-Monthly-Remaining"},"Request-Id":{"$ref":"#/components/headers/Request-Id"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Invitation"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}}},"delete":{"operationId":"cancelInvitation","tags":["Invitations"],"summary":"Cancel a scheduled invitation.","security":[{"ApiKey":["invitations:write"]},{"OAuth2":["invitations:write"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Public id with its prefix (e.g. rev_1042) or the number alone.","schema":{"type":"string"}}],"responses":{"200":{"description":"The cancelled invitation.","headers":{"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"RateLimit-Monthly-Limit":{"$ref":"#/components/headers/RateLimit-Monthly-Limit"},"RateLimit-Monthly-Remaining":{"$ref":"#/components/headers/RateLimit-Monthly-Remaining"},"Request-Id":{"$ref":"#/components/headers/Request-Id"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Invitation"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/v1/products":{"get":{"operationId":"listProducts","tags":["Products"],"summary":"Active products of one business.","security":[{"ApiKey":["products:write"]},{"OAuth2":["products:write"]}],"parameters":[{"name":"limit","in":"query","required":false,"description":"Page size (default 20, at most 100).","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","required":false,"description":"next_cursor from the previous page.","schema":{"type":"string","maxLength":200}},{"name":"business","in":"query","required":false,"description":"Business id (biz_…); needed when the key can use several.","schema":{"type":"string","maxLength":200}}],"responses":{"200":{"description":"A page of products.","headers":{"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"RateLimit-Monthly-Limit":{"$ref":"#/components/headers/RateLimit-Monthly-Limit"},"RateLimit-Monthly-Remaining":{"$ref":"#/components/headers/RateLimit-Monthly-Remaining"},"Request-Id":{"$ref":"#/components/headers/Request-Id"}},"content":{"application/json":{"schema":{"type":"object","required":["data","next_cursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Product"}},"next_cursor":{"type":["string","null"],"description":"Pass as cursor for the next page; null at the end."}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}}},"post":{"operationId":"createProduct","tags":["Products"],"summary":"Add a product (sku and name are required).","security":[{"ApiKey":["products:write"]},{"OAuth2":["products:write"]}],"parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sku":{"type":"string","minLength":1,"maxLength":64},"name":{"type":"string","minLength":1,"maxLength":200},"url":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}]},"image_url":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}]},"gtin":{"anyOf":[{"type":"string","maxLength":32},{"type":"null"}]},"group":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}]},"business":{"anyOf":[{"type":"string","maxLength":200,"description":"Business id (biz_…); needed when the key can use several."},{"type":"null"}]}}}}}},"responses":{"201":{"description":"Product created.","headers":{"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"RateLimit-Monthly-Limit":{"$ref":"#/components/headers/RateLimit-Monthly-Limit"},"RateLimit-Monthly-Remaining":{"$ref":"#/components/headers/RateLimit-Monthly-Remaining"},"Request-Id":{"$ref":"#/components/headers/Request-Id"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Product"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"$ref":"#/components/responses/Conflict"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"415":{"$ref":"#/components/responses/UnsupportedMediaType"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/v1/products/{sku}":{"patch":{"operationId":"updateProduct","tags":["Products"],"summary":"Change a product by SKU.","security":[{"ApiKey":["products:write"]},{"OAuth2":["products:write"]}],"parameters":[{"name":"sku","in":"path","required":true,"description":"The product SKU.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sku":{"type":"string","minLength":1,"maxLength":64},"name":{"type":"string","minLength":1,"maxLength":200},"url":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}]},"image_url":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}]},"gtin":{"anyOf":[{"type":"string","maxLength":32},{"type":"null"}]},"group":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}]},"business":{"anyOf":[{"type":"string","maxLength":200,"description":"Business id (biz_…); needed when the key can use several."},{"type":"null"}]}}}}}},"responses":{"200":{"description":"The product.","headers":{"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"RateLimit-Monthly-Limit":{"$ref":"#/components/headers/RateLimit-Monthly-Limit"},"RateLimit-Monthly-Remaining":{"$ref":"#/components/headers/RateLimit-Monthly-Remaining"},"Request-Id":{"$ref":"#/components/headers/Request-Id"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Product"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"415":{"$ref":"#/components/responses/UnsupportedMediaType"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/v1/webhooks":{"get":{"operationId":"listWebhooks","tags":["Webhooks"],"summary":"Webhook endpoints of the company.","security":[{"ApiKey":["webhooks:manage"]},{"OAuth2":["webhooks:manage"]}],"responses":{"200":{"description":"Endpoints.","headers":{"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"RateLimit-Monthly-Limit":{"$ref":"#/components/headers/RateLimit-Monthly-Limit"},"RateLimit-Monthly-Remaining":{"$ref":"#/components/headers/RateLimit-Monthly-Remaining"},"Request-Id":{"$ref":"#/components/headers/Request-Id"}},"content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WebhookEndpoint"}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}}},"post":{"operationId":"createWebhook","tags":["Webhooks"],"summary":"Add an endpoint. The signing secret is returned only in this answer.","security":[{"ApiKey":["webhooks:manage"]},{"OAuth2":["webhooks:manage"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","maxLength":500,"description":"Public HTTPS address (port 443 or 8443)."},"events":{"minItems":1,"maxItems":8,"type":"array","items":{"type":"string","enum":["review.created","review.updated","review.removed","reply.created","invitation.sent","invitation.completed","score.changed","proof.requested"]}}},"required":["url","events"]}}}},"responses":{"201":{"description":"Endpoint created.","headers":{"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"RateLimit-Monthly-Limit":{"$ref":"#/components/headers/RateLimit-Monthly-Limit"},"RateLimit-Monthly-Remaining":{"$ref":"#/components/headers/RateLimit-Monthly-Remaining"},"Request-Id":{"$ref":"#/components/headers/Request-Id"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointCreated"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"$ref":"#/components/responses/Conflict"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"415":{"$ref":"#/components/responses/UnsupportedMediaType"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/v1/webhooks/{id}":{"delete":{"operationId":"deleteWebhook","tags":["Webhooks"],"summary":"Delete an endpoint.","security":[{"ApiKey":["webhooks:manage"]},{"OAuth2":["webhooks:manage"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Endpoint id (we_…).","schema":{"type":"string"}}],"responses":{"204":{"description":"Deleted.","headers":{"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"RateLimit-Monthly-Limit":{"$ref":"#/components/headers/RateLimit-Monthly-Limit"},"RateLimit-Monthly-Remaining":{"$ref":"#/components/headers/RateLimit-Monthly-Remaining"},"Request-Id":{"$ref":"#/components/headers/Request-Id"}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}}}}},"webhooks":{"review.created":{"post":{"summary":"Event review.created, POSTed to your endpoint and signed.","parameters":[{"name":"Proofwell-Signature","in":"header","required":true,"description":"t=<unix time>,v1=<hex HMAC-SHA256 of \"<t>.<raw body>\" with the endpoint secret>. Reject if t is more than 5 minutes old.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Event"}}}},"responses":{"2XX":{"description":"Received. Answer within 10 s; otherwise the delivery is retried 8 times."}}}},"review.updated":{"post":{"summary":"Event review.updated, POSTed to your endpoint and signed.","parameters":[{"name":"Proofwell-Signature","in":"header","required":true,"description":"t=<unix time>,v1=<hex HMAC-SHA256 of \"<t>.<raw body>\" with the endpoint secret>. Reject if t is more than 5 minutes old.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Event"}}}},"responses":{"2XX":{"description":"Received. Answer within 10 s; otherwise the delivery is retried 8 times."}}}},"review.removed":{"post":{"summary":"Event review.removed, POSTed to your endpoint and signed.","parameters":[{"name":"Proofwell-Signature","in":"header","required":true,"description":"t=<unix time>,v1=<hex HMAC-SHA256 of \"<t>.<raw body>\" with the endpoint secret>. Reject if t is more than 5 minutes old.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Event"}}}},"responses":{"2XX":{"description":"Received. Answer within 10 s; otherwise the delivery is retried 8 times."}}}},"reply.created":{"post":{"summary":"Event reply.created, POSTed to your endpoint and signed.","parameters":[{"name":"Proofwell-Signature","in":"header","required":true,"description":"t=<unix time>,v1=<hex HMAC-SHA256 of \"<t>.<raw body>\" with the endpoint secret>. Reject if t is more than 5 minutes old.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Event"}}}},"responses":{"2XX":{"description":"Received. Answer within 10 s; otherwise the delivery is retried 8 times."}}}},"invitation.sent":{"post":{"summary":"Event invitation.sent, POSTed to your endpoint and signed.","parameters":[{"name":"Proofwell-Signature","in":"header","required":true,"description":"t=<unix time>,v1=<hex HMAC-SHA256 of \"<t>.<raw body>\" with the endpoint secret>. Reject if t is more than 5 minutes old.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Event"}}}},"responses":{"2XX":{"description":"Received. Answer within 10 s; otherwise the delivery is retried 8 times."}}}},"invitation.completed":{"post":{"summary":"Event invitation.completed, POSTed to your endpoint and signed.","parameters":[{"name":"Proofwell-Signature","in":"header","required":true,"description":"t=<unix time>,v1=<hex HMAC-SHA256 of \"<t>.<raw body>\" with the endpoint secret>. Reject if t is more than 5 minutes old.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Event"}}}},"responses":{"2XX":{"description":"Received. Answer within 10 s; otherwise the delivery is retried 8 times."}}}},"score.changed":{"post":{"summary":"Event score.changed, POSTed to your endpoint and signed.","parameters":[{"name":"Proofwell-Signature","in":"header","required":true,"description":"t=<unix time>,v1=<hex HMAC-SHA256 of \"<t>.<raw body>\" with the endpoint secret>. Reject if t is more than 5 minutes old.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Event"}}}},"responses":{"2XX":{"description":"Received. Answer within 10 s; otherwise the delivery is retried 8 times."}}}},"proof.requested":{"post":{"summary":"Event proof.requested, POSTed to your endpoint and signed.","parameters":[{"name":"Proofwell-Signature","in":"header","required":true,"description":"t=<unix time>,v1=<hex HMAC-SHA256 of \"<t>.<raw body>\" with the endpoint secret>. Reject if t is more than 5 minutes old.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Event"}}}},"responses":{"2XX":{"description":"Received. Answer within 10 s; otherwise the delivery is retried 8 times."}}}}},"components":{"securitySchemes":{"ApiKey":{"type":"http","scheme":"bearer","bearerFormat":"pk_live_<32 hex>","description":"An API key from Settings → Developers → API keys, sent as \"Authorization: Bearer pk_live_…\"."},"OAuth2":{"type":"oauth2","description":"Client credentials: client_id = the key's client id (pwc_…), client_secret = the key. The token is sent as \"Authorization: Bearer pwt_…\".","flows":{"clientCredentials":{"tokenUrl":"https://api.proofwell.io/v1/oauth/token","scopes":{"reviews:read":"Read published reviews","score:read":"Read ProofScore and star distribution","replies:write":"Post public replies to reviews","invitations:write":"Create and cancel review invitations","invitations:read":"Read invitations and their status","products:write":"Read, add and change products","webhooks:manage":"Manage webhook endpoints"}}}}},"parameters":{"IdempotencyKey":{"name":"Idempotency-Key","in":"header","required":false,"description":"Up to 128 visible ASCII characters. The same key with the same request returns the first answer for 24 hours; with a different request → 409 idempotency_conflict.","schema":{"type":"string","maxLength":128}}},"headers":{"RateLimit-Limit":{"description":"Requests allowed per second for this key.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in this second.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the per-second window resets.","schema":{"type":"integer"}},"RateLimit-Monthly-Limit":{"description":"The company's monthly request limit.","schema":{"type":"integer"}},"RateLimit-Monthly-Remaining":{"description":"Requests left this calendar month (UTC).","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}},"Request-Id":{"description":"Quote it when you contact support.","schema":{"type":"string"}},"WWW-Authenticate":{"description":"RFC 6750: Bearer realm=\"…\", error=\"invalid_token\" or error=\"insufficient_scope\" (with scope).","schema":{"type":"string"}}},"responses":{"BadRequest":{"description":"invalid_request, credentials_in_url, business_required, …","headers":{"Request-Id":{"$ref":"#/components/headers/Request-Id"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthorized":{"description":"invalid_key, invalid_token, key_expired or token_expired.","headers":{"Request-Id":{"$ref":"#/components/headers/Request-Id"},"WWW-Authenticate":{"$ref":"#/components/headers/WWW-Authenticate"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"insufficient_scope (with WWW-Authenticate), ip_not_allowed, key_blocked, plan_required, company_suspended, https_required.","headers":{"Request-Id":{"$ref":"#/components/headers/Request-Id"},"WWW-Authenticate":{"$ref":"#/components/headers/WWW-Authenticate"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"not_found (also for other companies' data).","headers":{"Request-Id":{"$ref":"#/components/headers/Request-Id"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Conflict":{"description":"duplicate_invitation, duplicate_reference, unsubscribed, duplicate_sku, idempotency_conflict, …","headers":{"Request-Id":{"$ref":"#/components/headers/Request-Id"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"PayloadTooLarge":{"description":"payload_too_large: the body is over 64 KB.","headers":{"Request-Id":{"$ref":"#/components/headers/Request-Id"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"UnsupportedMediaType":{"description":"unsupported_media_type: send Content-Type: application/json.","headers":{"Request-Id":{"$ref":"#/components/headers/Request-Id"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"TooManyRequests":{"description":"rate_limited, monthly_limit_reached or too_many_auth_failures.","headers":{"Request-Id":{"$ref":"#/components/headers/Request-Id"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ServerError":{"description":"internal_error: safe to retry.","headers":{"Request-Id":{"$ref":"#/components/headers/Request-Id"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message","request_id"],"properties":{"code":{"type":"string","description":"Machine-readable: invalid_key, invalid_token, key_expired, token_expired, key_blocked, ip_not_allowed, credentials_in_url, https_required, plan_required, company_suspended, insufficient_scope, invalid_request, unsupported_media_type, payload_too_large, not_found, rate_limited, too_many_auth_failures, monthly_limit_reached, idempotency_conflict, internal_error, …"},"message":{"type":"string"},"request_id":{"type":"string","examples":["req_4Hq1x2"]},"fields":{"type":"array","items":{"type":"string"}},"details":{"type":"object","additionalProperties":true}}}}},"OAuthError":{"type":"object","required":["error"],"properties":{"error":{"type":"string","enum":["invalid_request","invalid_client","invalid_grant","unauthorized_client","unsupported_grant_type","invalid_scope","too_many_requests"]},"error_description":{"type":"string"}}},"TokenResponse":{"type":"object","required":["access_token","token_type","expires_in","scope"],"properties":{"access_token":{"type":"string","description":"Opaque, \"pwt_\" + 43 characters."},"token_type":{"type":"string","const":"Bearer"},"expires_in":{"type":"integer","description":"Seconds (at most 3600)."},"scope":{"type":"string","description":"Granted scopes, space-separated."}}},"Business":{"type":"object","properties":{"id":{"type":"string","examples":["biz_example-coffee"]},"name":{"type":"string"},"url":{"type":"string","format":"uri"},"score":{"type":["number","null"]},"review_count":{"type":"integer"},"proof_share":{"type":"number"}}},"Me":{"allOf":[{"$ref":"#/components/schemas/Business"},{"type":"object","properties":{"key":{"type":"object","properties":{"name":{"type":"string"},"permissions":{"type":"array","items":{"type":"string","enum":["reviews:read","score:read","replies:write","invitations:write","invitations:read","products:write","webhooks:manage"]}}}},"businesses":{"type":"array","items":{"$ref":"#/components/schemas/Business"}}}}]},"Score":{"type":"object","properties":{"business_id":{"type":"string"},"score":{"type":["number","null"]},"stars":{"type":"object","additionalProperties":{"type":"integer"}},"review_count":{"type":"integer"},"proof_share":{"type":"number"},"updated_at":{"type":["string","null"],"format":"date-time"}}},"Reply":{"type":"object","properties":{"id":{"type":"string","examples":["rpl_88"]},"review_id":{"type":"string"},"from":{"type":"string"},"text":{"type":"string"},"created_at":{"type":"string","format":"date-time"}}},"Review":{"type":"object","properties":{"id":{"type":"string","examples":["rev_1042"]},"business_id":{"type":"string"},"stars":{"type":"integer","minimum":1,"maximum":5},"title":{"type":["string","null"]},"text":{"type":"string"},"language":{"type":"string","description":"Original language; never translated."},"proof":{"type":"string","enum":["transaction","invited","identity","after_review","imported","unverified"]},"reviewer":{"type":"object","properties":{"name":{"type":["string","null"]}}},"product":{"type":["object","null"],"properties":{"sku":{"type":["string","null"]},"name":{"type":["string","null"]}}},"experience_date":{"type":["string","null"],"format":"date"},"resolved":{"type":"boolean"},"replies":{"type":"array","items":{"$ref":"#/components/schemas/Reply"}},"url":{"type":"string","format":"uri"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"Invitation":{"type":"object","properties":{"id":{"type":"string","examples":["inv_48213"]},"business_id":{"type":"string"},"status":{"type":"string"},"channel":{"type":"string","enum":["email","whatsapp"]},"name":{"type":"string"},"contact":{"type":"string","description":"Masked."},"reference":{"type":["string","null"]},"kind":{"type":"string"},"send_at":{"type":["string","null"],"format":"date-time"},"sent_at":{"type":["string","null"],"format":"date-time"},"review_id":{"type":["string","null"]},"created_at":{"type":"string","format":"date-time"}}},"Product":{"type":"object","properties":{"sku":{"type":"string"},"name":{"type":"string"},"business_id":{"type":"string"},"url":{"type":["string","null"]},"image_url":{"type":["string","null"]},"gtin":{"type":["string","null"]},"group":{"type":["string","null"]},"active":{"type":"boolean"},"updated_at":{"type":"string","format":"date-time"}}},"WebhookEndpoint":{"type":"object","properties":{"id":{"type":"string","examples":["we_12"]},"url":{"type":"string"},"events":{"type":"array","items":{"type":"string","enum":["review.created","review.updated","review.removed","reply.created","invitation.sent","invitation.completed","score.changed","proof.requested"]}},"status":{"type":"string","enum":["active","paused"]},"health":{"type":"string"},"secret_hint":{"type":"string"},"created_at":{"type":"string","format":"date-time"}}},"WebhookEndpointCreated":{"type":"object","properties":{"id":{"type":"string"},"url":{"type":"string"},"events":{"type":"array","items":{"type":"string","enum":["review.created","review.updated","review.removed","reply.created","invitation.sent","invitation.completed","score.changed","proof.requested"]}},"secret":{"type":"string","description":"Signing secret, shown only here."}}},"Event":{"type":"object","required":["id","type","created_at","data"],"properties":{"id":{"type":"string","examples":["evt_3kq9ZyC1b2x7Lm0P"]},"type":{"type":"string","enum":["review.created","review.updated","review.removed","reply.created","invitation.sent","invitation.completed","score.changed","proof.requested"]},"created_at":{"type":"string","format":"date-time"},"data":{"type":"object","additionalProperties":true,"description":"Ids and facts only; never review text or customer details."}}}}}}