Authentication
Every request carries an account API key:
Api-Key: <key_id>-<secret>
Keys are created and revoked on the API Credentials page of the HoundDog dashboard by a user who holds the Manage API Access permission (the Admin tier has it; custom roles must be granted it). A key acts with the whole account's authority, so treat it like a password: it is shown once at creation and cannot be read back.
Scopes
Each key has a scope chosen at creation:
| Scope | Allows |
|---|---|
read |
GET, HEAD and OPTIONS requests |
read_write |
everything, including POST, PATCH, DELETE and the named actions such as archive |
Scopes limit verbs, not fields: a read key sees every field a read_write key sees.
The per-key w9 grant is separate from scopes (see W-9s): without it the W-9 download (GET /w9s/:id/download) is 403 forbidden whatever the scope, and the full tin in JSON also needs the account setting that allows tax IDs through the API.
What a refused request looks like
Checks run in this order, and the first failure answers:
| Status | error.code |
Meaning |
|---|---|---|
| 401 | unauthorized |
The header is missing or malformed, the key is unknown or revoked, or the secret does not match |
| 403 | account_deactivated |
The account is deactivated |
| 403 | api_disabled |
The account's API access is turned off in HoundDog |
| 403 | insufficient_scope |
A read key attempted a write |
| 403 | feature_disabled |
The resource belongs to a feature the account has not enabled (the message names it) |
A path that no operation serves answers 404 not_found before any of these checks run, with or without a key: an unrouted path is 404 whatever the key.
Error bodies follow the shape on the Errors page.
Key hygiene
- Turning the account's API access off refuses every key at once; existing keys can still be revoked while it is off.
- Rotate a key by creating a new one, switching your integration over, then revoking the old one; both work during the overlap.
- Public documentation endpoints (
/api/docs,/api/v1/swagger_doc,/api/docs/v2/openapi.json) need no key.