Authentication
To call the API you need two things. An API key is created once in By Dawn and lives on your server. An access token is what your code gets from that key and sends with every request. This page explains how the two fit together, what a key may do, and how to look after keys.
The split exists for safety. A key lasts a long time, so it never travels with ordinary requests. A token expires after about 15 minutes, so one that leaks into a log can’t do much harm.
Create a key
Section titled “Create a key”An organization owner or admin creates keys in By Dawn, under Settings › Organization › Security, on the
API keys card (API keys walks through it). Give the
key a name you’ll recognise later, pick what it may do (see Scopes), and choose when
it expires: in 30, 90 or 365 days, or never. By Dawn shows the key once, so copy it straight away. It
starts with saw_live_.
Keep the key on a server, in a secret store or a CI secret. Don’t put it in a web page or a mobile app, where anyone using them could read it. (Pasting your own key into Try it on this site is fine, because it never leaves your browser.)
Exchange a key for an access token
Section titled “Exchange a key for an access token”Your code sends the key to the accounts host and gets a token back:
POST https://accounts.dev.sawrun.com/api/v1/auth/token/api-keyContent-Type: application/json
{ "apiKey": "saw_live_…" }{ "ok": true, "data": { "accessToken": "eyJ…", "tokenType": "Bearer", "expiresInSeconds": 900 } }Then it sends the token with every request to the workspace host, in an Authorization header:
GET https://workspace.dev.sawrun.com/api/v1/orgs/{orgId}/projectsAuthorization: Bearer eyJ…Keep using the same token until it’s about to expire, then exchange again. Don’t exchange before
every request: the exchange has its own, lower rate limit.
A long-running integration should remember when its token expires (expiresInSeconds from now)
and swap a minute before then.
If a request comes back 401 unauthorized, the token has expired or its key was revoked.
Exchange once more and repeat the request. If that fails too, stop, because the key itself no
longer works.
Your organization ID
Section titled “Your organization ID”Every workspace path starts with /orgs/{orgId}. A key belongs to exactly one organization, and
you don’t need to look its ID up: the access token carries it, in its org_id claim. The token
is a JWT, so you can read the claim by decoding its middle part:
// The token is a JWT; its `org_id` claim is the organization the key belongs to.const claims = JSON.parse(atob(token.data.accessToken.split('.')[1]!.replace(/-/g, '+').replace(/_/g, '/')));const orgId: string = claims.org_id;Asking about any other organization gets 403 forbidden.
Scopes
Section titled “Scopes”When you create a key you choose its Access, and that decides what its tokens may do:
| Access in Settings | Scopes | What it allows |
|---|---|---|
| Board — read only | tickets:read |
Read tickets, comments, projects, columns, labels, cycles, epics and the teams that work in a project |
| Board — read & write | tickets:read, tickets:write |
Everything above, plus create, update, move and archive tickets, post comments, link tickets together, and create, update and close epics |
| Tests — submit results | tests:write |
Send test runs from CI (Send test results from CI), and nothing else: it can’t read or change tickets |
| Tests — read cases & runs | tests:read |
Read a project’s test case library, its runs and their results, and nothing on the board |
| Tests — read & write cases & runs | tests:read, tests:write |
Everything above, plus create and edit test cases, folders and manual runs, import cases, and send test runs from CI |
Separately from its Access, a key has a Customers access, which opens your organization’s customers (Customers API):
| Customers in Settings | Scopes | What it allows |
|---|---|---|
| None | none | Nothing about customers. This is the default |
| Read | customers:read |
Read customers, their requests, and the customer statuses and tiers |
| Read & write | customers:read, customers:write |
Everything above, plus create and update customers, and add, change and remove the requests on a ticket. Changing a ticket’s requests also needs tickets:read on its project |
Customers only in Access makes a key with no board access, for a sync that only keeps your customer list up to date.
Start with read only, and make a read & write key when your integration needs to change things. Give a CI job that
only sends test results a Tests key, so a leaked CI secret can’t touch your board.
A request the key’s scopes don’t cover gets 403 forbidden.
What a key can’t do
Section titled “What a key can’t do”A key acts for your organization, not for a person, and it’s kept away from a few things a person should decide. So whatever its scopes, a key can’t:
- list tickets across the whole organization. Pass a
projectIdwhen listing tickets. For the same reason it can’t list a team’s tickets across projects (GET /teams/{teamId}/tickets), so filter each project byteamIdinstead, and it must pass aprojectIdwhen listing epics (GET /epics). - list the organization’s members.
GET /usersanswers403 forbidden, so assign tickets with user IDs you already have. - list the organization’s teams.
GET /orgs/{orgId}/teamson the accounts host answers403 forbidden, so keep the team IDs you need in your configuration. A project’s teams give you their IDs. - delete a ticket. Archive it instead, with
POST /tickets/{ticketId}/archive. - create labels. That needs an organization admin, signed in.
- attach a team to a project or detach one. That’s a project admin’s job, signed in.
- move a ticket into the column that starts an agent run (the column with the
buildingrole). Starting an agent should be a person’s call. - see restricted projects. They don’t appear in its lists, and their tickets are refused.
- merge or delete a customer. Both change other people’s data at once, so they’re an organization admin’s, signed in.
- change Customers settings or turn Customers on, including statuses, tiers, the revenue unit and who sees revenue. Those are an organization admin’s, signed in (see Customers settings and privacy).
- forget a requester, or export a customer’s requests as CSV. Both are about personal data, so a person does them in the app.
Anything a key creates, a ticket or a comment, shows the key as its author, not a person.
Revoke and rotate keys
Section titled “Revoke and rotate keys”Revoke a key in Settings › Organization › Security. It stops working at once: it can’t be exchanged any more, and tokens already issued from it stop working within seconds. An expired key behaves the same way.
To rotate a key without downtime, create the new key, switch your integration over, and only then revoke the old one.