Authentication¶
Every request needs credentials. Scripts use a team API key. A team member who is signed in to PoreStore in a browser can also call the API with their session, which is how the interactive schema views work.
Team API keys¶
A team owner creates keys on the team's API keys page. Each key:
- belongs to one team. It works only under
/api/v1/teams/{that team's ID}/. - acts as the owner who created it. Jobs it submits are recorded as started by that person, and it stops working if they leave the team or their account is deactivated. It sees the analyses that person may run on the team.
- is shown once. PoreStore stores only a hash. If you lose a key, revoke it and create another.
- can be revoked at any time from the same page. Revocation takes effect on the next request.
A key looks like AbCd1234.Q2xhdWRlIHdyb3RlIHRoaXMgZXhhbXBsZQ: an eight-character prefix, a dot, then the secret. The prefix identifies the key in the key list. The whole string is the credential.
Sending the key¶
Put it in the Authorization header with the Api-Key scheme:
GET /api/v1/teams/7k3mf8q2/images/ HTTP/1.1
Host: porestore.com
Authorization: Api-Key AbCd1234.Q2xhdWRlIHdyb3RlIHRoaXMgZXhhbXBsZQ
Never put a key in a URL or a query string, and don't commit it to source control. Read it from an environment variable or a secrets manager.
The upload itself doesn't use your key
The presigned form returned by POST /uploads/ already authorises one upload to object storage. Send that form without an Authorization header. Object storage would reject the header anyway.
When authentication fails¶
| Status | error.code |
Meaning |
|---|---|---|
401 |
not_authenticated |
No Authorization header and no browser session. |
401 |
authentication_failed |
The key is unknown, revoked or expired, or its owner's account is inactive. |
403 |
permission_denied |
The key is valid and its owner belongs to this team, but the key was made for another team (or for no team), wasn't created by a team owner, or its owner has left the team it was made for. |
403 |
analysis_unavailable |
Authentication is fine, but this analysis isn't available to you on this team. See Analysis types. |
404 |
not_found |
The team doesn't exist, or you can't reach it: the key isn't for this team and its owner isn't a member, or the signed-in user isn't a member. |
A 401 response carries WWW-Authenticate: Api-Key.
A team you can't reach gets exactly the same 404 as a team that doesn't exist, so Team IDs can't be discovered by trying them.
Rate limits¶
Each key has its own budget of 3000 requests per hour. A signed-in browser session gets its own budget too. Keys don't share a quota, so one busy script doesn't slow down another team's integration or your own other keys. Over the limit, the API returns 429 Too Many Requests with Retry-After in seconds.
Polling a job every 5–10 seconds uses 360–720 requests an hour, comfortably inside the limit. Poll several jobs from one loop rather than one tight loop per job.