API reference
The bynh API.
Read and change your workspace from scripts and CI: certificates, evidence, policies, your status page, access requests, disclosure reports and subprocessors. Every endpoint here works with a personal API token.
https://api.bynh.io/api/v1Authentication
Send a personal API token as a bearer token on every request. Create one in the app under My account → API tokens; see Create an API token. The whole token, {id}|bynh_pat_…, goes in the header.
Authorization: Bearer 42|bynh_pat_••••••••Every path starts with https://api.bynh.io/api/v1/workspaces/{workspace}, where {workspace} is your workspace’s address. A token works only in the workspace it was made in; any other workspace answers 404. Tokens expire after 7, 30 or 90 days or a year, and a missing, expired or revoked token gets 401.
Scopes and roles
A token has one of two scopes, and acts with its owner’s current role in the workspace.
| Scope | Can call |
|---|---|
read | GET requests only |
read + write | Every endpoint here, within the owner’s role |
| Endpoint needs | Roles that can call it |
|---|---|
| Any member | Viewer, Editor, Admin, Owner |
| Editor | Editor, Admin, Owner (viewers get 403) |
| Admin | Admin, Owner (the audit log) |
Errors
Errors are JSON with a message that says what went wrong, in the token owner’s language. Validation errors (422) add errors, with the messages for each field.
{
"message": "Enter the standard, like ISO/IEC 27001:2022. (and 1 more error)",
"errors": {
"name": ["Enter the standard, like ISO/IEC 27001:2022."],
"issuer": ["Enter who issued it, like BSI Group."]
}
}| Status | When | What to do |
|---|---|---|
401 | The token is missing, wrong, expired or revoked. | Send a valid token. |
403 | The token is read-only, your role can’t do this, or editing is paused on the workspace. | Read the message: it names the reason. |
404 | The token is for another workspace, you’re no longer a member, or the id doesn’t exist in this workspace. | Check the address and the id. |
422 | A value isn’t allowed, or the change doesn’t fit the record’s state. | Fix the fields listed in errors. |
429 | You’ve gone over a rate limit. | Wait, then try again. See Rate limits. |
500 | Something broke on our side. | Retry with backoff, and check status.bynh.io. |
Editing pauses when a trial ends without a plan or a payment doesn’t go through. Reads keep working; writes answer 403 with a message such as “Your trial has ended, so editing is paused. Your trust center stays online.”
Rate limits
Each person can make 120 requests a minute, shared by all their tokens and their browser session. Every response tells you where you stand.
| Header | Means |
|---|---|
X-RateLimit-Limit | Requests allowed in the window |
X-RateLimit-Remaining | Requests left in the window |
Retry-After | Seconds to wait, sent with a 429 from the general limit |
Some actions have their own, lower limit on top, shown on each endpoint: uploads (20 a minute), evidence changes (60 a minute), reminders (30 an hour), monitor checks (10 a minute), incident notices (30 an hour), invitations (60 an hour) and subprocessor changes (90 a minute). Their 429 has a message but no Retry-After; wait a minute and try again.
Pagination
Most lists return every row in data, in one response. Three are different:
| List | How it pages |
|---|---|
| Access requests, status subscribers | Pass page; the response has meta.page, meta.last_page and meta.total (25 and 50 a page). |
| Audit events | Pass cursor from meta.next_cursor, and send your filters again with it. |
| Incidents, maintenance | The newest 100. |
Conventions
- Successful responses wrap their payload in
data.DELETEanswers204with no body. Downloads return the file. - Ids are numbers. Frameworks use their slug (
iso-27001) and disclosure reports their number in your workspace. - Dates are
YYYY-MM-DD; times are ISO 8601 in UTC. - Messages and labels follow the token owner’s language, English or Arabic. Values such as statuses never change.
- Every change is recorded in your workspace’s audit log, with the token’s owner as the person who made it.
- There are no outgoing webhooks. To react to changes, read the lists on a schedule, or connect Slack in the app.
Endpoints
Certificates
- GETList certificates/workspaces/{workspace}/certificates
- POSTAdd a certificate/workspaces/{workspace}/certificates
- GETGet a certificate/workspaces/{workspace}/certificates/{certificate}
- PATCHUpdate a certificate/workspaces/{workspace}/certificates/{certificate}
- POSTUpload a certificate document/workspaces/{workspace}/certificates/{certificate}/documents
- GETList expiry reminders/workspaces/{workspace}/certificates/{certificate}/reminders
- GETDownload a document/workspaces/{workspace}/documents/{document}/download
Evidence
- GETGet coverage/workspaces/{workspace}/evidence
- GETList a framework’s requirements/workspaces/{workspace}/evidence/frameworks/{framework}/requirements
- GETExport coverage as CSV/workspaces/{workspace}/evidence/export
- GETList requirements you can map/workspaces/{workspace}/evidence/requirements
- PATCHAssign a requirement/workspaces/{workspace}/evidence/requirements/{requirementId}
- GETList evidence/workspaces/{workspace}/evidence/items
- POSTAdd evidence/workspaces/{workspace}/evidence/items
- GETGet evidence/workspaces/{workspace}/evidence/items/{evidenceItem}
- PATCHUpdate evidence/workspaces/{workspace}/evidence/items/{evidenceItem}
- POSTMark evidence collected/workspaces/{workspace}/evidence/items/{evidenceItem}/collect
- POSTUpload an evidence file/workspaces/{workspace}/evidence/items/{evidenceItem}/files
- GETDownload an evidence file/workspaces/{workspace}/evidence/items/{evidenceItem}/files/{file}/download
- DELETEDelete an evidence file/workspaces/{workspace}/evidence/items/{evidenceItem}/files/{file}
Policies
- GETList policies/workspaces/{workspace}/policies
- POSTCreate a policy/workspaces/{workspace}/policies
- GETGet a policy/workspaces/{workspace}/policies/{policy}
- PATCHUpdate a policy’s details/workspaces/{workspace}/policies/{policy}
- POSTMark a policy reviewed/workspaces/{workspace}/policies/{policy}/reviewed
Status page
- GETGet the status overview/workspaces/{workspace}/status
- GETList monitors/workspaces/{workspace}/status/monitors
- POSTCreate a monitor/workspaces/{workspace}/status/monitors
- GETGet a monitor/workspaces/{workspace}/status/monitors/{monitor}
- PATCHUpdate a monitor/workspaces/{workspace}/status/monitors/{monitor}
- POSTPause a monitor/workspaces/{workspace}/status/monitors/{monitor}/pause
- POSTResume a monitor/workspaces/{workspace}/status/monitors/{monitor}/resume
- POSTCheck a monitor now/workspaces/{workspace}/status/monitors/{monitor}/check
- GETGet response times/workspaces/{workspace}/status/monitors/{monitor}/response-times
- GETList incidents/workspaces/{workspace}/status/incidents
- POSTReport an incident/workspaces/{workspace}/status/incidents
- GETGet an incident/workspaces/{workspace}/status/incidents/{incident}
- PATCHUpdate an incident/workspaces/{workspace}/status/incidents/{incident}
- DELETEDelete a draft incident/workspaces/{workspace}/status/incidents/{incident}
- POSTPost an incident update/workspaces/{workspace}/status/incidents/{incident}/updates
- GETList maintenance/workspaces/{workspace}/status/maintenance
- POSTSchedule maintenance/workspaces/{workspace}/status/maintenance
- PATCHChange maintenance/workspaces/{workspace}/status/maintenance/{maintenance}
- POSTCancel maintenance/workspaces/{workspace}/status/maintenance/{maintenance}/cancel
- GETList subscribers/workspaces/{workspace}/status/subscribers
- POSTInvite a subscriber/workspaces/{workspace}/status/subscribers
Access requests
- GETList access requests/workspaces/{workspace}/access/requests
- GETExport access requests as CSV/workspaces/{workspace}/access/requests/export
- GETGet an access request/workspaces/{workspace}/access-requests/{accessRequest}
- POSTApprove an access request/workspaces/{workspace}/access-requests/{accessRequest}/approve
- POSTDecline an access request/workspaces/{workspace}/access-requests/{accessRequest}/decline
- POSTEnd someone’s access/workspaces/{workspace}/access/requests/{accessRequest}/revoke
- POSTResend an access link/workspaces/{workspace}/access/requests/{accessRequest}/resend