Authentication
Every request carries one credential in the Authorization header:
Authorization: Bearer <API key or access token>Credentials are read only from that header. Query parameters such as
?api_key= and cookies are ignored, so a key never ends up in a URL or log.
A credential belongs to exactly one workspace, and every request acts on that workspace. There is no workspace parameter.
API keys
Section titled “API keys”An API key is a long-lived secret for scripts, CI pipelines and integrations.
devsk_exampleexample00_EXAMPLE-not-a-real-key-EXAMPLE-000000000└─┬─┘ └──────┬───────┘ └──────────────────┬──────────────────┘prefix key id (public) secret- Create keys in the dashboard under Integrations → API keys. Workspace owners and members whose role allows managing API keys can do this.
- The full key is shown once. DevSecure stores only a keyed hash and cannot show it again.
- Scopes limit what a key can do. Pick the fewest you need; see Scopes. You can only grant scopes your own role has.
- Expiry. Every key expires, after at most 730 days. Without a date, the maximum applies.
- Rotate a key to get a new secret with the same id, name and scopes. The old secret stops working immediately.
- Revoke a key to stop it at once.
A key follows the person who created it. If that person leaves the workspace,
is disabled, or is limited to particular repositories or teams, the key stops
working. If their role loses a permission, the key loses the matching scopes
on its next request. GET /v1/credential always shows the scopes a key has
right now.
OAuth client credentials
Section titled “OAuth client credentials”Use an OAuth client when a service should exchange its credentials for
short-lived tokens. Create one in the dashboard like an API key, choosing the
OAuth client type. You get a client id (devsc_…) and a client secret
(devss_…); the secret is shown once.
Request an access token with the client credentials grant (RFC 6749 §4.4):
curl -s https://api.devsecure.io/oauth/token \ -u "$DEVSECURE_CLIENT_ID:$DEVSECURE_CLIENT_SECRET" \ -d grant_type=client_credentials \ -d scope="issues:read scans:read"{ "access_token": "devsat_exampleexample00_EXAMPLE-not-a-real-token-EXAMPLE-0000000", "token_type": "Bearer", "expires_in": 3600, "scope": "issues:read scans:read"}- Send the body as
application/x-www-form-urlencoded. - Authenticate with HTTP Basic, or with
client_idandclient_secretin the body. Use one method, not both. scopeis optional. Without it the token gets all of the client’s scopes; with it, the requested subset.- Tokens last one hour (
expires_in) and never outlive the client. Request a new one when it expires; there are no refresh tokens. - Revoking the client revokes its tokens.
Token errors follow RFC 6749, not the API’s usual error format:
| Status | error |
When |
|---|---|---|
| 400 | invalid_request |
Missing or repeated parameters, wrong content type, two authentication methods |
| 400 | unsupported_grant_type |
Anything but client_credentials |
| 400 | invalid_scope |
A requested scope is unknown or not granted to the client |
| 400 | unauthorized_client |
The workspace’s plan does not include API access |
| 401 | invalid_client |
Wrong, unknown, expired or revoked client credentials |
| 429 | rate_limited |
Too many token requests; see Retry-After |
When authentication fails
Section titled “When authentication fails”Every authentication failure returns the same response, whatever the cause:
HTTP/1.1 401 UnauthorizedWWW-Authenticate: Bearer realm="devsecure"{ "error": { "code": "invalid_credentials", "message": "Authentication failed.", "request_id": "req_3f0c2a9d5b6e4f7a8c1d2e3f4a5b6c7d" }}Repeated failures from one address are throttled with 429 rate_limited.
Keeping keys safe
Section titled “Keeping keys safe”- Keep keys in a secret manager or your CI’s secret store, never in code.
- Give each integration its own key with only the scopes it needs.
- Set an expiry and rotate keys on a schedule.
- Revoke a key as soon as you suspect it leaked. The workspace audit log
(
GET /v1/audit-log) shows what each key did.