Authentication
Every request carries two credentials: a public API key that identifies you, and a secret that proves it is you. Requests are made over HTTPS only.
API key and secret
GP Code issues your organisation one or more API keys. Each key comes with a secret, shown once when the key is issued — GP Code stores only a hash of it and cannot show it again.
| Credential | Format | Sent as | Handling |
|---|---|---|---|
| API key | gpk_live_… / gpk_test_… | X-GoPeeko-Key header | Identifies the key. Safe to log. |
| Secret | gps_… | Authorization: Bearer header | Keep in a secret store. Never log it, never ship it to a browser or app. |
curl {{BASE}}/me/quota \
-H "X-GoPeeko-Key: gpk_live_7f3a91c4b2e84d05" \
-H "Authorization: Bearer gps_…"
$client = new GuzzleHttp\Client([
'base_uri' => '{{BASE}}/',
'headers' => [
'X-GoPeeko-Key' => getenv('GPCODE_KEY'),
'Authorization' => 'Bearer ' . getenv('GPCODE_SECRET'),
'Accept' => 'application/json',
],
]);
const headers = {
'X-GoPeeko-Key': process.env.GPCODE_KEY,
Authorization: `Bearer ${process.env.GPCODE_SECRET}`,
Accept: 'application/json',
};
session = requests.Session()
session.headers.update({
"X-GoPeeko-Key": os.environ["GPCODE_KEY"],
"Authorization": f"Bearer {os.environ['GPCODE_SECRET']}",
"Accept": "application/json",
})
A missing header, an unknown key or a wrong secret answers 401 unauthenticated. The response does not say which part was wrong.
Environments
gpk_live_ keys work only against production; gpk_test_ keys only against staging ({{SANDBOX}}). The two environments have separate databases.
Scopes
Your partner account carries a set of scopes that decide which endpoints your keys may call. New partners get all four. An endpoint that needs a scope you lack answers 403 forbidden_scope.
| Scope | Allows |
|---|---|
codes:read | GET /gp-codes, GET /gp-codes/{code} |
codes:write | POST /gp-codes, PATCH /gp-codes/{code}, DELETE /gp-codes/{code} |
users:read | GET /users, GET /users/{id} |
users:write | POST /users |
| none | GET /me/quota works with any valid key |
Inline users and scopesPOST /gp-codes with a user object creates that user if needed. It only needs codes:write.
Rotating and revoking keys
Keys do not expire. To rotate, ask GP Code for a new key: you get a new key and secret, and the old key keeps working until GP Code revokes it. That gives you time to deploy the new credentials without downtime.
- Request a rotation from {{SUPPORT}}.
- Deploy the new key and secret to all your servers.
- Confirm traffic uses the new key, then ask for the old one to be revoked.
A revoked key answers 401 key_revoked. If GP Code suspends your partner account, every key answers 401 client_suspended until it is reactivated.
Secret leaked?Contact GP Code immediately to revoke the key. Revocation takes effect on the next request.
IP allowlist
Optionally, GP Code can restrict your keys to a list of IP addresses or CIDR ranges (for example 203.0.113.0/24). A request from any other address answers 401 unauthenticated, exactly as if the key were wrong. Send your servers' egress addresses when you request access, or later to change them.
Best practices
- Call the API from your back end only. Never embed the secret in front-end code, mobile apps or public repositories.
- Keep staging and production credentials in separate secret stores.
- Log the API key (to tell keys apart) but never the
Authorizationheader. - Ask for only the scopes your integration needs.