The key
A Developer API key reaches the whole tenant’s data within its scopes and its owner’s permissions. Treat it as a service password.- Keep it in a secret manager or an environment variable, not in the repository and not in a config file next to the code.
- Never use it in a frontend or mobile app, where every user can read it.
- Issue a separate key per integration. A compromise then costs you one key rather than all access.
- Rotation is manual: create a new key, switch the integration over, then revoke the old one. Keys currently have no expiry.
- The secret is shown once at creation. Lists show only the 12-character prefix.
What a key can see
Effective access is the intersection of two limits:- The key’s scopes. An endpoint requires a specific scope; without it the
request is rejected with
DEVELOPER.SCOPE_INSUFFICIENT. - The owner’s permissions. The key sees exactly the employees, documents, and fields available to the permission profile of the user who created it. Permissions are evaluated per request: narrow the owner’s access and the key narrows with it.
redacted_fields. A single resource you
cannot access is indistinguishable from one that does not exist: both return 404.
A key stops working once its owner is removed from the tenant or deactivated, so a
departure does not require a separate revocation — though reviewing the key list
after one is still worthwhile.
Webhook URLs
Doodocs calls your server, so a subscription URL must satisfy two requirements:- the
httpsscheme only; - a publicly resolvable address only:
localhost, private ranges, and cloud metadata addresses are rejected withDEVELOPER.WEBHOOK_URL_INVALID.
https address.
Verifying deliveries
Every delivery is signed: theDoodocs-Signature header carries a timestamp and an
HMAC-SHA256 of {t}.{body} computed with the subscription secret. Verify the
signature before parsing the body and reject requests older than five minutes, or an
intercepted delivery can be replayed.
The secret is shown once when the subscription is created and is not rotated. To
replace it, create a new subscription with the same URL and event types, switch your
verification to the new secret, and delete the old one.
Event payloads are deliberately thin: type, time, and a resource id. Personal data
never leaves for an external URL — you fetch it with your own key, where scopes and
field redaction apply.
Document events are delivered for every document in the tenant the endpoint
subscribes to, regardless of the key owner’s per-document permissions. The event
itself carries only an id and a timestamp; the document’s content stays gated by
permissions when you read it through
GET /documents/{id}.