Developer platform
Build your review workflow on Approvela.
The public API is tenant-scoped, JSON-first, and designed for agency systems that need to create projects, collect feedback, and receive approval events.
Authentication
Create an API key in Settings → API & webhooks. Send it on every request as a Bearer token. Keys are shown only once and are scoped to their agency.
curl https://app.approvela.com/api/v1/me \ -H 'Authorization: Bearer apv_live_…'
Quick start
curl -X POST https://app.approvela.com/api/v1/clients \
-H 'Authorization: Bearer $APPROVELA_KEY' \
-H 'content-type: application/json' \
-d '{"name":"Acme","contacts":[{"name":"Sam","email":"sam@example.com"}]}'
curl -X POST https://app.approvela.com/api/v1/projects \
-H 'Authorization: Bearer $APPROVELA_KEY' \
-H 'content-type: application/json' \
-d '{"clientOrgId":"…","name":"Acme site","originUrl":"https://staging.example.com"}'
curl -X POST https://app.approvela.com/api/v1/projects/PROJECT/review-links \
-H 'Authorization: Bearer $APPROVELA_KEY' \
-d '{"contactId":"…"}'Endpoint reference
GET/api/v1/meCurrent agency and API keyGET/api/v1/clientsList client organizations and contactsPOST/api/v1/clientsCreate a client organizationPOST/api/v1/clients/:id/contactsAdd a client contactGET/api/v1/projectsList projectsPOST/api/v1/projectsCreate a proxy review projectGET/api/v1/projects/:idGet project detailsPOST/api/v1/projects/:id/review-linksIssue a client review linkPOST/api/v1/projects/:id/versionsPublish a new version; returns round: null with a client-approval message when rounds are exhaustedGET/api/v1/projects/:id/feedbackList feedback threadsPATCH/api/v1/feedback/:threadIdUpdate feedback status or priorityPOST/api/v1/feedback/:threadId/commentsReply to feedbackGET/api/v1/projects/:id/approvalGet the approval recordGET/api/v1/projects/:id/receipt.pdfDownload the approval receiptGET/api/v1/webhooksList webhook endpointsPOST/api/v1/webhooksCreate a webhook endpointDELETE/api/v1/webhooks/:idDelete a webhook endpointPOST/api/v1/webhooks/:id/testSend a ping eventList endpoints accept limit (default 50, maximum 200). Projects and feedback support cursor pagination. Review-link issuance emails the contact.
Webhooks
Register an HTTPS endpoint in Settings or through the API. An empty event list subscribes to every event.
round.submittedproject.approvedadditional_round.requestedfeedback.createdfeedback.repliedfeedback.status_changedping
{
"id": "delivery-id",
"event": "feedback.created",
"createdAt": "2026-01-01T00:00:00.000Z",
"data": { "projectId": "…", "threadId": "…" }
}Verify signatures
Compute HMAC-SHA256 over timestamp.rawBody with the secret shown once when the endpoint is created.
import crypto from "node:crypto";
const [, timestamp, signature] =
header.match(/^t=(\d+),v1=([a-f0-9]+)$/i) ?? [];
const expected = crypto
.createHmac("sha256", secret)
.update(timestamp + "." + rawBody)
.digest("hex");
const valid = crypto.timingSafeEqual(
Buffer.from(signature, "hex"),
Buffer.from(expected, "hex"),
);Errors
Errors use a consistent envelope with a machine-readable code. Validation failures include an issues array.
{
"error": {
"code": "not_approved",
"message": "This project has not been approved"
}
}Rate limits
Each API key may make 120 requests per minute. A 429 response includes retry-after seconds. All timestamps are ISO 8601 strings.