{"components":{"parameters":{"cursor":{"in":"query","name":"cursor","schema":{"maxLength":1024,"type":"string"}},"limit":{"in":"query","name":"limit","schema":{"default":20,"maximum":100,"minimum":1,"type":"integer"}}},"responses":{"directory":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/list"}}},"description":"Page of reachable resources"},"error":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/error"}}},"description":"Stable API error. Rate-limit responses include Retry-After. Request-Id identifies the request."}},"schemas":{"error":{"properties":{"doc_url":{"type":"string"},"error":{"type":"string"},"message":{"type":"string"},"request_id":{"type":"string"},"resets_at":{"description":"Monthly allowance reset for pack_exhausted; Retry-After gives seconds until this time.","format":"date-time","type":"string"}},"required":["error","message","request_id","doc_url"],"type":"object"},"list":{"properties":{"data":{"items":{"$ref":"#/components/schemas/resource"},"type":"array"},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]},"object":{"const":"list"}},"required":["object","data","has_more","next_cursor"],"type":"object"},"resource":{"properties":{"business_id":{"type":"string"},"created_at":{"format":"date-time","type":"string"},"id":{"type":"string"},"language":{"type":"string"},"name":{"type":"string"},"object":{"enum":["business","location"]},"status":{"type":"string"},"timezone":{"type":"string"}},"required":["object","id","name","status","timezone","created_at"],"type":"object"},"review":{"properties":{"author_name":{"type":"string"},"body":{"type":"string"},"business_id":{"type":"string"},"created_at":{"format":"date-time","type":"string"},"excluded_from_rating":{"type":"boolean"},"id":{"pattern":"^rev_[0-9A-HJKMNP-TV-Z]{26}$","type":"string"},"language":{"type":"string"},"location_id":{"type":"string"},"object":{"const":"review"},"owner_reply":{"properties":{"at":{"format":"date-time","type":["string","null"]},"author":{"type":["string","null"]},"body":{"type":"string"}},"type":["object","null"]},"posted_at":{"format":"date-time","type":["string","null"]},"rating":{"description":"Normalized rating.","type":"number"},"rating_scale":{"description":"The source's own scale.","type":"number"},"recommends":{"type":["boolean","null"]},"removed_at":{"description":"Set when the review was removed at the source.","format":"date-time","type":["string","null"]},"source":{"description":"The review site's name.","type":"string"},"source_url":{"type":"string"},"updated_at":{"format":"date-time","type":"string"}},"required":["object","id","business_id","location_id","rating","rating_scale","recommends","author_name","body","language","source","source_url","posted_at","owner_reply","excluded_from_rating","removed_at","created_at","updated_at"],"type":"object"},"reviewList":{"properties":{"data":{"items":{"$ref":"#/components/schemas/review"},"type":"array"},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]},"object":{"const":"list"}},"required":["object","data","has_more","next_cursor"],"type":"object"},"reviewRequest":{"properties":{"business_id":{"type":"string"},"first_send_at":{"format":"date-time","type":["string","null"]},"id":{"pattern":"^rreq_[0-9A-HJKMNP-TV-Z]{26}$","type":["string","null"]},"location_id":{"type":["string","null"]},"object":{"const":"review_request"},"recipient":{"properties":{"id":{"pattern":"^rcpt_[0-9A-HJKMNP-TV-Z]{26}$","type":["string","null"]},"object":{"const":"recipient"},"status":{"description":"scheduled, skipped_recent, skipped_unsubscribed, skipped_suppressed, or another skipped_ reason. scheduled means queued; delivery is asynchronous.","type":"string"}},"required":["object","id","status"],"type":"object"},"validate_only":{"type":"boolean"}},"required":["object","id","location_id","recipient","first_send_at","validate_only"],"type":"object"},"reviewRequestBatch":{"properties":{"accepted":{"type":"integer"},"business_id":{"type":"string"},"first_send_at":{"description":"When the first email of the list may go; later people follow the daily pacing.","format":"date-time","type":["string","null"]},"id":{"pattern":"^rreq_[0-9A-HJKMNP-TV-Z]{26}$","type":["string","null"]},"location_id":{"type":["string","null"]},"object":{"const":"review_request_batch"},"recipients":{"items":{"properties":{"id":{"pattern":"^rcpt_[0-9A-HJKMNP-TV-Z]{26}$","type":["string","null"]},"index":{"description":"Position in the request's recipients array.","type":"integer"},"object":{"const":"recipient"},"status":{"description":"scheduled, or a skipped_ reason such as skipped_recent, skipped_duplicate, skipped_unsubscribed, skipped_suppressed.","type":"string"}},"required":["object","index","id","status"],"type":"object"},"type":"array"},"skipped":{"type":"integer"},"validate_only":{"type":"boolean"}},"required":["object","id","location_id","first_send_at","validate_only","accepted","skipped","recipients"],"type":"object"},"reviewRequestBatchInput":{"additionalProperties":false,"anyOf":[{"required":["location_id"]},{"required":["business_id"]}],"description":"Target a business with business_id, or an explicit location with location_id. When both are supplied they must match. Business requests lead to the existing location picker.","properties":{"business_id":{"pattern":"^biz_[0-9A-HJKMNP-TV-Z]{26}$","type":"string"},"location_id":{"pattern":"^loc_[0-9A-HJKMNP-TV-Z]{26}$","type":"string"},"recipients":{"items":{"additionalProperties":false,"properties":{"email":{"type":"string"},"language":{"enum":["","en","pt","fr","lt"],"type":"string"},"name":{"type":"string"},"phone":{"type":"string"}},"type":"object"},"maxItems":100,"minItems":1,"type":"array"},"sms_consent":{"default":false,"description":"Applies to every person with a mobile number: confirm each gave you their number and agreed to texts from your business, including a review request.","type":"boolean"},"sms_consent_statement":{"description":"Required as sms_consent_v1 when sms_consent is true.","type":"string"},"validate_only":{"default":false,"type":"boolean"}},"required":["recipients"],"type":"object"},"reviewRequestInput":{"additionalProperties":false,"anyOf":[{"required":["location_id"]},{"required":["business_id"]}],"description":"Target a business with business_id, or an explicit location with location_id. When both are supplied they must match. Business requests lead to the existing location picker.","properties":{"business_id":{"pattern":"^biz_[0-9A-HJKMNP-TV-Z]{26}$","type":"string"},"location_id":{"pattern":"^loc_[0-9A-HJKMNP-TV-Z]{26}$","type":"string"},"recipient":{"additionalProperties":false,"properties":{"email":{"description":"Email address. Provide email, mobile number, or both.","type":"string"},"language":{"description":"Empty or omitted follows the location's language.","enum":["","en","pt","fr","lt"],"type":"string"},"name":{"description":"Optional recipient name.","type":"string"},"phone":{"description":"Mobile number. Include the international calling code; local numbers use the location's country.","type":"string"}},"type":"object"},"send_now":{"default":false,"description":"Queue the first step immediately, otherwise follow the location's schedule.","type":"boolean"},"sms_consent":{"default":false,"description":"Confirm this person gave you their mobile number and agreed to receive texts from your business about their visit, including a request for a review. Without consent no text is sent; email may still be used.","type":"boolean"},"sms_consent_statement":{"description":"Required as sms_consent_v1 when sms_consent is true.","type":"string"},"validate_only":{"default":false,"type":"boolean"}},"required":["recipient"],"type":"object"},"webhookEndpoint":{"properties":{"api_version":{"type":"string"},"created_at":{"format":"date-time","type":"string"},"description":{"type":"string"},"event_types":{"items":{"type":"string"},"type":"array"},"id":{"pattern":"^wep_[0-9A-HJKMNP-TV-Z]{26}$","type":"string"},"object":{"const":"webhook_endpoint"},"status":{"type":"string"},"url":{"type":"string"}},"required":["object","id","url","event_types","status","created_at"],"type":"object"},"webhookEndpointCreated":{"properties":{"endpoint":{"$ref":"#/components/schemas/webhookEndpoint"},"secret":{"description":"Shown once.","type":"string"}},"required":["endpoint","secret"],"type":"object"},"webhookEndpointInput":{"additionalProperties":false,"properties":{"description":{"maxLength":500,"type":"string"},"event_types":{"items":{"type":"string"},"minItems":1,"type":"array"},"status":{"description":"Ignored on create (endpoints start enabled).","enum":["enabled","disabled"]},"url":{"description":"HTTPS URL. Private and internal addresses are refused.","format":"uri","type":"string"}},"required":["url","event_types"],"type":"object"},"webhookEndpointList":{"properties":{"data":{"items":{"$ref":"#/components/schemas/webhookEndpoint"},"type":"array"},"object":{"const":"list"}},"required":["object","data"],"type":"object"}},"securitySchemes":{"apiKey":{"description":"Organization API key, rvk_live_…; never send in a URL or body.","scheme":"bearer","type":"http"}}},"info":{"description":"Scoped organization keys, business/location listings, single-recipient review requests and outbound webhook endpoints. Sending review requests and managing webhook endpoints require Growth or above; reading reviews requires Pro or above.","title":"Public API","version":"1.0.0"},"openapi":"3.1.0","paths":{"/":{"get":{"operationId":"getVersion","responses":{"200":{"description":"API surface and version"}},"security":[]}},"/businesses":{"get":{"description":"Requires businesses:read. Lists businesses within the key's grants whose current subscription unlocks API access. Cursor order is newest first by creation time and id.","operationId":"listBusinesses","parameters":[{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/cursor"}],"responses":{"200":{"$ref":"#/components/responses/directory"},"400":{"$ref":"#/components/responses/error"},"401":{"$ref":"#/components/responses/error"},"403":{"$ref":"#/components/responses/error"},"422":{"$ref":"#/components/responses/error"},"429":{"$ref":"#/components/responses/error"},"500":{"$ref":"#/components/responses/error"},"503":{"$ref":"#/components/responses/error"}}}},"/healthz":{"get":{"operationId":"getHealth","responses":{"200":{"description":"Process health"}},"security":[]}},"/locations":{"get":{"description":"Requires locations:read. Lists reachable locations of API-entitled businesses. Optional business filter uses a biz_ id. A cursor is valid only for the same key, resource and business filter. Lists may return an empty page with has_more=true while scanning an account with many ineligible businesses; continue with next_cursor.","operationId":"listLocations","parameters":[{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/cursor"},{"in":"query","name":"business_id","schema":{"pattern":"^biz_[0-9A-HJKMNP-TV-Z]{26}$","type":"string"}}],"responses":{"200":{"$ref":"#/components/responses/directory"},"400":{"$ref":"#/components/responses/error"},"401":{"$ref":"#/components/responses/error"},"403":{"$ref":"#/components/responses/error"},"422":{"$ref":"#/components/responses/error"},"429":{"$ref":"#/components/responses/error"},"500":{"$ref":"#/components/responses/error"},"503":{"$ref":"#/components/responses/error"}}}},"/openapi.json":{"get":{"operationId":"getOpenAPI","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"OpenAPI 3.1 document"}},"security":[]}},"/review-requests":{"post":{"description":"Requires review_requests:write, contact-rights confirmation when the key was created, a location within its grants and Growth+ for that business. One person per call. Reuses the location's review sites, repeat guard, unsubscribe/suppression rules, monthly request pack, language, schedule and reply address. send_now queues the first step immediately; delivery remains asynchronous. validate_only runs checks without creating requests, jobs or retry records; it still requires the header and consumes rate limits. Unknown fields, including ratings and sentiment, are rejected. The header identifies a call across all keys in the organization for 24 hours. The fingerprint includes method, path and canonical JSON (object field order is ignored). Completed calls replay the exact status/body with Idempotent-Replayed: true after current authorization is checked. Different input returns 422; a running call returns 409 with Retry-After: 1. Pre-operation authentication, authorization, rate-limit, body and header errors are not saved. Operation 4xx results are saved; 5xx roll back the request, jobs and retry record. A replayed error body retains its original request_id; the Request-Id header identifies the current attempt.","operationId":"createReviewRequest","parameters":[{"description":"Client-chosen, organization-wide call identifier. Use a new value for a new call. Required also for validate_only.","in":"header","name":"Idempotency-Key","required":true,"schema":{"maxLength":255,"minLength":1,"pattern":"^[ -~]+$","type":"string"}}],"requestBody":{"content":{"application/json":{"example":{"location_id":"loc_01K7AP1H6YT9Z2QX7JKRNM8CDV","recipient":{"email":"ana@example.com","name":"Ana"},"validate_only":true},"schema":{"$ref":"#/components/schemas/reviewRequestInput"}}},"description":"One UTF-8 JSON object, maximum 1 MiB.","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/reviewRequest"}}},"description":"Validation result; ids are null and no request is created."},"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/reviewRequest"}}},"description":"Request queued, or person skipped under recipient safeguards. Skipped results have null ids and first_send_at.","headers":{"Idempotent-Replayed":{"description":"true when the stored result was replayed","schema":{"const":"true","type":"string"}}}},"400":{"$ref":"#/components/responses/error"},"401":{"$ref":"#/components/responses/error"},"403":{"$ref":"#/components/responses/error"},"404":{"$ref":"#/components/responses/error"},"409":{"$ref":"#/components/responses/error"},"422":{"$ref":"#/components/responses/error"},"429":{"$ref":"#/components/responses/error"},"500":{"$ref":"#/components/responses/error"},"503":{"$ref":"#/components/responses/error"}}}},"/review-requests/batch":{"post":{"description":"Asks up to 100 people for a review in one call. Same authorization, contact-rights confirmation, plan and Idempotency-Key rules as POST /review-requests. The people form one request that follows the location's schedule and is paced over days on the location's daily quota (send_now is not available). Every person needs an email address or a mobile number; one invalid person rejects the whole call with 422. People held back by the repeat guard, unsubscribe or suppression rules are reported per person with a skipped_ status and are not an error; a call where everyone is skipped writes nothing and returns null ids. Results are in the order sent (index). validate_only checks everyone and writes nothing. The webhook review_request.created event carries this batch object as data.object. Body limit 256 KiB; more than 100 people returns 422 too_many_recipients.","operationId":"createReviewRequestBatch","parameters":[{"in":"header","name":"Idempotency-Key","required":true,"schema":{"maxLength":255,"minLength":1,"pattern":"^[ -~]+$","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/reviewRequestBatchInput"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/reviewRequestBatch"}}},"description":"Validation result; ids are null and nothing is created."},"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/reviewRequestBatch"}}},"description":"Request created, or everyone skipped (null ids)."},"400":{"$ref":"#/components/responses/error"},"401":{"$ref":"#/components/responses/error"},"403":{"$ref":"#/components/responses/error"},"404":{"$ref":"#/components/responses/error"},"409":{"$ref":"#/components/responses/error"},"422":{"$ref":"#/components/responses/error"},"429":{"$ref":"#/components/responses/error"},"500":{"$ref":"#/components/responses/error"},"503":{"$ref":"#/components/responses/error"}}}},"/reviews":{"get":{"description":"Pro and up. Requires reviews:read. Lists reviews of reachable businesses on the Pro plan or above; a key whose reachable businesses are all below Pro gets 403 plan_required. Default order is newest first by creation time and id. With updated_since, only reviews changed at or after that time are returned, oldest change first by updated_at and id, so an integrator can sync incrementally by following next_cursor. A cursor is valid only for the same key and filters. Lists may return an empty page with has_more=true while scanning an account with many ineligible businesses; continue with next_cursor. Reviews removed at the source are returned with removed_at set.","operationId":"listReviews","parameters":[{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/cursor"},{"in":"query","name":"business_id","schema":{"pattern":"^biz_[0-9A-HJKMNP-TV-Z]{26}$","type":"string"}},{"in":"query","name":"location_id","schema":{"pattern":"^loc_[0-9A-HJKMNP-TV-Z]{26}$","type":"string"}},{"description":"RFC 3339 time. Switches to incremental sync.","in":"query","name":"updated_since","schema":{"format":"date-time","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/reviewList"}}},"description":"Page of reviews"},"400":{"$ref":"#/components/responses/error"},"401":{"$ref":"#/components/responses/error"},"403":{"$ref":"#/components/responses/error"},"422":{"$ref":"#/components/responses/error"},"429":{"$ref":"#/components/responses/error"},"500":{"$ref":"#/components/responses/error"},"503":{"$ref":"#/components/responses/error"}}}},"/webhook-endpoints":{"get":{"description":"Requires webhooks:read. Growth and up.","operationId":"listWebhookEndpoints","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/webhookEndpointList"}}},"description":"Endpoints of the organization"},"401":{"$ref":"#/components/responses/error"},"403":{"$ref":"#/components/responses/error"},"429":{"$ref":"#/components/responses/error"},"500":{"$ref":"#/components/responses/error"}}},"post":{"description":"Requires webhooks:write. The signing secret (whsec_...) is returned only here and on a roll; deliveries follow the Standard Webhooks signature scheme.","operationId":"createWebhookEndpoint","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/webhookEndpointInput"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/webhookEndpointCreated"}}},"description":"Endpoint and its secret"},"400":{"$ref":"#/components/responses/error"},"401":{"$ref":"#/components/responses/error"},"403":{"$ref":"#/components/responses/error"},"422":{"$ref":"#/components/responses/error"},"429":{"$ref":"#/components/responses/error"},"500":{"$ref":"#/components/responses/error"},"503":{"$ref":"#/components/responses/error"}}}},"/webhook-endpoints/{id}":{"delete":{"description":"Requires webhooks:write.","operationId":"deleteWebhookEndpoint","responses":{"204":{"description":"Deleted"},"401":{"$ref":"#/components/responses/error"},"403":{"$ref":"#/components/responses/error"},"404":{"$ref":"#/components/responses/error"},"500":{"$ref":"#/components/responses/error"}}},"get":{"description":"Requires webhooks:read.","operationId":"getWebhookEndpoint","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/webhookEndpoint"}}},"description":"Endpoint"},"401":{"$ref":"#/components/responses/error"},"403":{"$ref":"#/components/responses/error"},"404":{"$ref":"#/components/responses/error"},"500":{"$ref":"#/components/responses/error"}}},"parameters":[{"in":"path","name":"id","required":true,"schema":{"pattern":"^wep_[0-9A-HJKMNP-TV-Z]{26}$","type":"string"}}],"patch":{"description":"Requires webhooks:write. Only the fields sent change.","operationId":"updateWebhookEndpoint","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/webhookEndpointInput"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/webhookEndpoint"}}},"description":"Endpoint"},"400":{"$ref":"#/components/responses/error"},"401":{"$ref":"#/components/responses/error"},"403":{"$ref":"#/components/responses/error"},"404":{"$ref":"#/components/responses/error"},"422":{"$ref":"#/components/responses/error"},"500":{"$ref":"#/components/responses/error"}}}},"/webhook-endpoints/{id}/deliveries":{"get":{"description":"Requires webhooks:read. Deliveries of the last 30 days.","operationId":"listWebhookDeliveries","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Deliveries"},"401":{"$ref":"#/components/responses/error"},"403":{"$ref":"#/components/responses/error"},"404":{"$ref":"#/components/responses/error"},"500":{"$ref":"#/components/responses/error"}}},"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}]},"/webhook-endpoints/{id}/roll":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"post":{"description":"Requires webhooks:write. Issues a new secret; the old one keeps signing alongside it for 24 hours. A second roll during that grace is refused with 422.","operationId":"rollWebhookSecret","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/webhookEndpointCreated"}}},"description":"Endpoint and its new secret"},"401":{"$ref":"#/components/responses/error"},"403":{"$ref":"#/components/responses/error"},"404":{"$ref":"#/components/responses/error"},"422":{"$ref":"#/components/responses/error"},"500":{"$ref":"#/components/responses/error"}}}},"/webhook-endpoints/{id}/test":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"post":{"description":"Requires webhooks:write. Queues a signed test event to an enabled endpoint.","operationId":"testWebhookEndpoint","responses":{"202":{"description":"Queued"},"401":{"$ref":"#/components/responses/error"},"403":{"$ref":"#/components/responses/error"},"404":{"$ref":"#/components/responses/error"},"422":{"$ref":"#/components/responses/error"},"500":{"$ref":"#/components/responses/error"}}}}},"security":[{"apiKey":[]}],"servers":[{"url":"https://api.ratezing.com/v1"}]}
