Authentication
Requests to the Atomic API are authenticated using the client credentials OAuth 2 flow, via a client ID and secret created in the Atomic Workbench.
API credentials can be created in the Atomic Workbench under Configuration > API Keys. Read more about this in the API section of the Workbench guide.
The basic flow is:
- Base64-encode your client id and secret i.e.
echo -n "$CLIENT_ID:$CLIENT_SECRET" | base64 - Pass this value as the
Authorizationheader in a request to our oauth server - Use the returned token to authenticate requests to Atomic
Atomic's OAuth URL is:
https://master-atomic-io.auth.us-east-1.amazoncognito.com/oauth2/token
Tokens have a limited lifespan, so should be renewed when appropriate. Access Tokens are valid for 1 hour, Refresh Tokens are valid for 30 days.
Note: requests to the Atomic API must include a User-Agent header.
When accessing the Atomic API programmatically, each API request should not request a new token. Instead, tokens should be cached and used until expiry and then a new token requested. The oauth endpoint used to retrieve tokens is rate limited and will return HTTP 429 status codes when used at too high a rate.
Full authentication example
Bash
Requires bash, and the shell utilities curl, base64, and jq.
Values for org_id, client_id and client_secret can all be managed in the Configuration section of the Workbench. Read more about this in the API section of the Workbench guide.
#!/bin/bash
# auth.sh
# fill in your organization id
ORG_ID=<your org id>
# fill in your API credentials for the environment you want to send requests to
CLIENT_ID=<your client id>
CLIENT_SECRET=<your secret>
OAUTH_URL=https://master-atomic-io.auth.us-east-1.amazoncognito.com/oauth2/token
ATOMIC_API=https://$ORG_ID.customer-api.atomic.io
# base64 encode your credentials
CREDENTIALS=$(echo -n "$CLIENT_ID:$CLIENT_SECRET" | base64)
# retrieve access token details as json
TOKEN_DETAILS=$(curl -X POST "$OAUTH_URL?grant_type=client_credentials&client_id=$CLIENT_ID" \
--header "Content-Type:application/x-www-form-urlencoded" \
--header "Authorization: Basic $CREDENTIALS")
# parse the token value
TOKEN=$(echo $TOKEN_DETAILS | jq -r -c ".access_token")
# retrieve Environment details
ENVIRONMENTS=$(curl -X GET "$ATOMIC_API/v1/environments" \
--header "Content-Type:application/json" \
--header "Authorization: Bearer $TOKEN")
# store first Environment id for use in other examples
ENVIRONMENT_ID=$(echo $ENVIRONMENTS | jq -r ".environments[0].id")
# output environment details, formatted with jq
echo $ENVIRONMENTS | jq
The output should be a list of Atomic environments you have access to, similar to
[
{
"id": 123,
"name": "production",
"created": "2019-07-04T04:18:08.153Z",
"organisationName": "Your organisation"
}
]
Javascript
An example in Javascript with caching implemented on the token.
let cachedToken = {
token: null,
expires: null
}
const getAPIToken = async () => {
if (cachedToken.token && cachedToken.expires > new Date()) {
return cachedToken.token
}
const clientId = process.env.ATOMIC_API_CLIENT_ID
const clientSecret = process.env.ATOMIC_API_CLIENT_SECRET
const oauthURL = process.env.ATOMIC_API_OAUTH_URL
// base64 encode your credentials
const credentials = Buffer.from(`${clientId}:${clientSecret}`).toString('base64')
// retrieve access token details as json
const tokenDetails = await fetch(`${oauthURL}?grant_type=client_credentials&client_id=${clientId}`, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': `Basic ${credentials}`
}
})
// parse the token value
const tokenResp = (await tokenDetails.json())
cachedToken = {
token: tokenResp.access_token,
expires: new Date(Date.now() + (tokenResp.expires_in * 1000))
}
return cachedToken.token
}
API key permissions
Fine-grained API keys
A fine-grained API key is granted a set of permissions that control which operations it can perform. The Atomic API spec shows for each endpoint which permission is required.
For example, retrieving cards requires the cards:read permission:
paths:
/v1/{environmentId}/cards:
get:
summary: "Retrieve cards"
security:
- oAuth2: ['cards:read']
When creating a fine-grained key, grant only the permissions needed for your integration.
Legacy API keys
Each legacy API credential pair is scoped to the environment and assigned one of the following roles:
auth- used only to create and rotate other credentialsworkbench- used to manage workbench resources such as cards and SNS platformsevents- used to create cards, and manage customers
Roles are associated with legacy API keys. We recommend using fine-grained API keys which use permissions instead that allow you to set what actions the API key is allowed to take.
The Atomic API spec shows for each request which role should be used.
For example, retrieving cards requires the events role:
paths:
/v1/{environmentId}/cards:
get:
summary: "Retrieve cards"
security:
- oAuth2: [events]
If you haven't added any API credentials yet, follow the steps as described in the API keys section to add new ones.
Troubleshooting
401 Unauthorized
Your access token is missing, malformed, or expired. Check that you're passing the token correctly as a Bearer token in the Authorization header, and that it hasn't exceeded its 1-hour lifespan. If it has expired, request a new token.
403 Forbidden
Your token is valid but the credential doesn't have permission to perform the operation. For fine-grained keys, check that the API key has the permission required by the endpoint. Refer to the API spec to confirm which permission is needed. For legacy keys, check that the key's role matches what the endpoint requires.
A 403 can also occur if the request comes from an IP address not on the API key's allowlist. Check whether the key has IP allowlisting configured under Authentication controls.
429 Too Many Requests
Your code is requesting a new token on every API call. Tokens are valid for 1 hour. Cache the token and reuse it until it expires rather than fetching a new one each time.
Key not working after rotation
After rotating an API key, the previous Client Secret is immediately invalidated. Make sure all services using the key have been updated to use the new secret.
Key not working after the expiry date
API keys with an expiry date stop working once that date passes. Create a new API key or rotate the existing one before it expires to avoid downtime.