Akeneo API Authentication: OAuth2 Setup Guide for Developers
Before you can export a single product from Akeneo, you need a working OAuth2 connection. This guide covers everything: creating API credentials, making the token request, handling expiry, and avoiding common authentication mistakes.
How Akeneo API authentication works
Akeneo uses OAuth2 with the Resource Owner Password Credentials grant (also called "password flow"). Unlike typical OAuth2 web flows with redirect URLs, this flow is designed for server-to-server integrations:
Step 1 — Create an API connection in Akeneo
Log into your Akeneo PIM and navigate to System → API Connections. If you don't see this menu, you need the ROLE_ADMINISTRATOR role.
- 1.Click Create
- 2.Enter a label:
SyncPIM Export(or any name) - 3.Akeneo generates a Client ID and Client Secret
- 4.Copy the Client Secret immediately — it's shown only once. If you miss it, regenerate it.
Client ID: 2_abc123def456ghi789
Client Secret: 7j8k9l0m1n2o3p4q5r6s7t8u9v0w1x2y3z4
Step 2 — Request an access token
Make a POST request to /api/oauth/v1/token. The credentials are sent as Basic Auth (base64-encoded client_id:client_secret) and the body is JSON:
# Using curl:
curl -X POST https://your-akeneo.com/api/oauth/v1/token \
-H "Content-Type: application/json" \
-u "2_abc123def456ghi789:7j8k9l0m1n2o3p4q5r6s7t8u9v0w1x2y3z4" \
-d '{
"username": "your_akeneo_username",
"password": "your_akeneo_password",
"grant_type": "password"
}'
# Response:
{
"access_token": "NzY4MDM4OGE4MjZjYTRiOGQ0YTJlYmI3...",
"expires_in": 3600,
"token_type": "bearer",
"scope": null
}The same request in Python:
import requests
from base64 import b64encode
def get_akeneo_token(base_url, client_id, client_secret, username, password):
credentials = b64encode(f"{client_id}:{client_secret}".encode()).decode()
response = requests.post(
f"{base_url}/api/oauth/v1/token",
headers={
"Content-Type": "application/json",
"Authorization": f"Basic {credentials}"
},
json={
"username": username,
"password": password,
"grant_type": "password"
}
)
response.raise_for_status()
return response.json()["access_token"]
token = get_akeneo_token(
"https://your-akeneo.com",
"2_abc123def456ghi789",
"7j8k9l0m...",
"admin",
"your_password"
)Step 3 — Use the token in API requests
Include the token in the Authorization header as a Bearer token:
import requests
def get_products(base_url, token, page=1, limit=100):
response = requests.get(
f"{base_url}/api/rest/v1/products",
headers={"Authorization": f"Bearer {token}"},
params={"page": page, "limit": limit, "with_count": "true"}
)
response.raise_for_status()
return response.json()
# First page
data = get_products("https://your-akeneo.com", token)
print(f"Total products: {data['items_count']}")
# → Total products: 4283Handling token expiry (1-hour TTL)
Akeneo access tokens expire after 3600 seconds (1 hour). For long-running exports, you need to detect expiry and re-authenticate. The API returns HTTP 401 when the token is expired:
import time
class AkeneoClient:
def __init__(self, base_url, client_id, client_secret, username, password):
self.base_url = base_url
self.creds = (client_id, client_secret, username, password)
self.token = None
self.token_expires_at = 0
def get_token(self):
# Refresh 5 minutes before expiry
if time.time() < self.token_expires_at - 300:
return self.token
self.token = get_akeneo_token(self.base_url, *self.creds)
self.token_expires_at = time.time() + 3600
return self.token
def request(self, path, params=None):
response = requests.get(
f"{self.base_url}{path}",
headers={"Authorization": f"Bearer {self.get_token()}"},
params=params
)
# If 401, force token refresh and retry once
if response.status_code == 401:
self.token_expires_at = 0
response = requests.get(
f"{self.base_url}{path}",
headers={"Authorization": f"Bearer {self.get_token()}"},
params=params
)
response.raise_for_status()
return response.json()Akeneo API rate limits
Akeneo does not publish official rate limits, but in practice:
Akeneo Serenity (Cloud)
~30 requests/second sustained, higher bursts tolerated
Rate limits vary by plan — contact Akeneo support for specifics
Akeneo Enterprise Edition (self-hosted)
Determined by your server capacity — no API-level throttle by default
Server performance (CPU/RAM) is the limiting factor
Akeneo Growth Edition
~10–20 requests/second in our testing
Use limit=100 per page and avoid parallel requests
# Safe pagination pattern: use limit=100, add small delay on 429
import time
def paginate_products(client, delay=0.1):
page = 1
while True:
data = client.request("/api/rest/v1/products",
params={"page": page, "limit": 100})
items = data.get("_embedded", {}).get("items", [])
if not items:
break
yield from items
# Check if there's a next page
next_link = data.get("_links", {}).get("next")
if not next_link:
break
page += 1
time.sleep(delay) # polite delayCommon authentication errors and fixes
HTTP 401 — invalid_client
Cause: Wrong Client ID or Client Secret. Double-check for trailing spaces when copy-pasting.
Fix: Regenerate the client secret in Akeneo admin and copy it again.
HTTP 400 — invalid_grant
Cause: Wrong username or password. The Akeneo user account may be locked or have wrong permissions.
Fix: Try logging into the Akeneo UI with the same credentials. If locked, unlock from System → Users.
HTTP 401 — expired token
Cause: Token TTL (3600s) exceeded. Common in long-running exports.
Fix: Implement token refresh logic (re-request token before expiry as shown above).
HTTP 403 — access denied
Cause: The API user doesn't have permission to access the requested resource (e.g., products in a channel they can't see).
Fix: Check the user's role and category/channel permissions in Akeneo admin.
Connection refused / SSL error
Cause: Wrong base URL format. Akeneo URL should not have a trailing slash and must use HTTPS.
Fix: Use https://your-akeneo.com (no trailing slash, no /api path in the base URL).
Skip OAuth2 complexity with SyncPIM
SyncPIM handles OAuth2 authentication for you. You paste your Akeneo URL, Client ID, Client Secret, username, and password once in the connection wizard — SyncPIM manages token refresh, rate limiting, and pagination automatically.
Connect Akeneo in 2 minutes
Paste your credentials once. SyncPIM handles OAuth2, token refresh, and pagination for every export.