Managing Credentials via API
Introduction
When you create a service account through the Noon Partner portal, you download a .json key file that your application uses to authenticate API requests. The API User Service lets you do the same thing — create and remove these credentials — programmatically, without logging into the portal.
Each credential is an RSA key pair tied to a service account. The private key is used to sign JWT tokens, which are exchanged for session cookies to authenticate your API calls. Every service account is identified by a user_code — a unique identifier that you'll pass to the API User Service when creating or removing credentials.
If you've already downloaded a .json key file from the portal and are using it to call Noon APIs — that is exactly the type of credential this service manages. The API User Service gives you a programmatic way to create additional keys for the same service account, or revoke existing ones.
Identifying the Target Service Account
Every create/remove call needs to know which service account it's operating on. You can identify the account two ways:
user_code— the canonical identifier for the service account. Prefer this if you have it.channel_identifier— the service account's username (the email-like identifier such as[email protected]). Use this when you don't have theuser_codehandy.
If both are provided, user_code takes precedence. If only channel_identifier is provided, the service resolves it to a user_code server-side before performing the operation.
Both values live in the credential payload you already have:
- From the portal flow — see the
.jsonkey file you downloaded in Getting Your Credentials. - From the OAuth flow — see the
resultobject returned by the token exchange step in Getting Credentials via OAuth. Thechannel_identifierfield on that response is the same value you'd pass here.
This is especially useful for integrators completing the OAuth flow: the token-exchange response gives you a channel_identifier but no user_code, so you can drive credential rotation from the value you already have.
When to Use
The portal works well for one-off credential creation, but there are scenarios where programmatic access is essential:
- Credential rotation — You want to regularly cycle out old keys and replace them with new ones, without manual intervention. For example, rotating keys every 30 days as part of your security policy.
- Managing credentials at scale — If you're an integrator managing service accounts across multiple seller projects (especially those created via the OAuth flow), manually downloading and rotating keys for each one becomes impractical.
- Incident response — If a key is compromised, you need to revoke it immediately. Calling the remove endpoint is faster than navigating the portal, and can be triggered automatically by your monitoring systems.
Prerequisites
- You must have a Noon Partner account and an existing service account (see Getting Your Credentials)
- You must be authenticated — follow the Authentication Guide to set up API access
- You must have appropriate permissions (project owner) to manage the target service account
Available Operations
Creating a Credential
The CreateCredential operation generates a new RSA key pair for a service account and returns the credential details, including the private key. Identify the target service account using either user_code or channel_identifier (see Identifying the Target Service Account above).
A few important things to understand:
- The private key. When you create a credential, the response includes the private key in PEM format.
The private key is only returned once at creation time — Noon does not store it. If you lose it, you will need to create a new credential. Treat it like a password: store it in a secrets manager, never commit it to source control, and never log it.
- IP whitelisting is optional but recommended. You can restrict a credential to a set of known IP addresses (up to 10). Requests from other IPs will be rejected. This is useful for locking down production credentials to your server IPs.
- Expiry is optional. You can set an expiry timestamp so the credential automatically becomes invalid after a certain date. If you don't set one, the credential remains valid indefinitely (or until you explicitly remove it).
- Each service account can have up to 5 active keys. This allows you to rotate credentials without downtime — create the new key, update your application, then remove the old key. You can request to have the quota for keys increased if needed.
Response
A successful call returns a credential object. See the API Reference for full schema details.
Removing Credentials
The RemoveCredentials operation deactivates credentials for a service account. As with CreateCredential, you can identify the target account using either user_code or channel_identifier (see Identifying the Target Service Account above).
You can either:
- Remove a specific credential by providing its
key_id(returned when the credential was created). This is useful for targeted revocation — for example, rotating out a single key while keeping others active. - Remove all active credentials by omitting the
key_id. This is a nuclear option for when you need to immediately lock down a service account — for example, if you suspect the account is compromised.
Removal is immediate. Any subsequent authentication attempts using a removed credential will fail. If there are no active credentials to remove, the operation still succeeds (with a count of zero).
If there are no active credentials to remove, the API will return success: true with credentials_removed: 0.
Credential Rotation Example
Each service account supports a maximum of 5 active keys. If you're near that limit, remove the old key before creating a new one to avoid hitting the cap mid-rotation.
A common pattern is to rotate credentials without downtime. Here's how it works:
- Create a new credential — Call CreateCredential to generate a fresh key pair
- Update your application — Deploy the new key to your application or secrets manager
- Verify the new key works — Make a test API call using the new credential
- Remove the old credential — Call RemoveCredentials with the old
key_id
This ensures your application is never without a valid credential during the rotation.
Code Examples
These examples assume you already have an active session cookie from completing the Authentication Guide. Complete that guide first — a valid session is required for all the requests below.
- Python
- Bash / cURL
import requests
import json
BASE_URL = "https://noon-api-gateway.noon.partners"
# Assumes you are already authenticated (session cookie from login)
session = requests.Session()
# ... authenticate first using the steps in the Authentication guide ...
# Create a new credential with IP whitelisting and expiry.
# Identify the service account by user_code (preferred) OR channel_identifier.
create_response = session.post(
f"{BASE_URL}/identity/apiuser/v1/credential/create",
json={
"user_code": "USR12345",
# Alternatively, omit user_code and provide channel_identifier:
# "channel_identifier": "[email protected]",
"whitelisted_ips": ["203.0.113.10"],
"expires_at": "2026-12-31T23:59:59Z"
},
headers={"User-Agent": "MyApp/1.0.0"}
)
credential = create_response.json()["credential"]
key_id = credential["key_id"]
# Store the credential securely — the private key won't be available again.
# The returned credential includes channel_identifier, which you can keep on
# hand for future rotations if you don't want to track user_code separately.
with open("service_account_key.json", "w") as f:
json.dump(credential, f)
print(f"Created credential with key_id: {key_id}")
# Later, remove the credential when it's no longer needed.
remove_response = session.post(
f"{BASE_URL}/identity/apiuser/v1/credential/remove",
json={
"user_code": "USR12345",
# Or identify by channel_identifier instead:
# "channel_identifier": credential["channel_identifier"],
"key_id": key_id
},
headers={"User-Agent": "MyApp/1.0.0"}
)
print(f"Removed {remove_response.json()['credentials_removed']} credential(s)")
# Create a new credential
curl -X POST "https://noon-api-gateway.noon.partners/identity/apiuser/v1/credential/create" \
-H "Content-Type: application/json" \
-H "User-Agent: MyApp/1.0.0" \
-b cookies.txt \
-d '{
"user_code": "USR12345",
"whitelisted_ips": ["203.0.113.10"],
"expires_at": "2026-12-31T23:59:59Z"
}'
# Remove a specific credential by key_id
curl -X POST "https://noon-api-gateway.noon.partners/identity/apiuser/v1/credential/remove" \
-H "Content-Type: application/json" \
-H "User-Agent: MyApp/1.0.0" \
-b cookies.txt \
-d '{
"user_code": "USR12345",
"key_id": "key-abc123"
}'
# Remove ALL active credentials for a service account
curl -X POST "https://noon-api-gateway.noon.partners/identity/apiuser/v1/credential/remove" \
-H "Content-Type: application/json" \
-H "User-Agent: MyApp/1.0.0" \
-b cookies.txt \
-d '{
"user_code": "USR12345"
}'
# Same operation, but identifying the account by channel_identifier
# (e.g. the value returned in the OAuth token-exchange `result`).
curl -X POST "https://noon-api-gateway.noon.partners/identity/apiuser/v1/credential/remove" \
-H "Content-Type: application/json" \
-H "User-Agent: MyApp/1.0.0" \
-b cookies.txt \
-d '{
"channel_identifier": "[email protected]"
}'
Limits
| Limit | Value |
|---|---|
| Maximum keys per service account | 5 |
| Maximum whitelisted IPs per credential | 10 |
Error Handling
Common error scenarios for CreateCredential:
| Error | Description | Solution |
|---|---|---|
User not found | Neither the user_code nor the channel_identifier matches an existing service account | Verify the value you provided. For OAuth-created accounts, the channel_identifier from the token exchange result is a drop-in option when you don't have the user_code |
Either user_code or channel_identifier is required | Both fields were omitted from the request | Provide one of the two — see Identifying the Target Service Account |
User is not active | The service account has been deactivated | Reactivate the account through the Noon Partner portal, or create a new service account |
Cannot regenerate credentials for this user | The user_code belongs to a non-service account | This API only works with service accounts. Check that you're using the correct user_code |
Not allowed to regenerate credentials for this user | Your session is referencing a different project than that of the target service account | You can only manage credentials by referencing the correct project |
apijwt key quota exceeded for the account | The service account already has the maximum number of active keys (default: 5) | Remove unused keys before creating new ones, or request a quota increase |
Maximum 10 whitelisted IPs allowed | More than 10 IPs were provided in whitelisted_ips | Reduce the list to 10 or fewer IP addresses |
Invalid expires_at format | The expires_at timestamp is not in valid ISO 8601 format | Use the format: 2026-12-31T23:59:59Z |
Common error scenarios for RemoveCredentials:
| Error | Description | Solution |
|---|---|---|
User does not exist | Neither the user_code nor the channel_identifier matches an existing service account | Verify the value you provided |
Either user_code or channel_identifier is required | Both fields were omitted from the request | Provide one of the two — see Identifying the Target Service Account |
Cannot remove channels for this user | The user_code belongs to a non-service account | This API only works with service accounts. Check that you're using the correct user_code |
Not allowed to remove channels for this user | Your session is referencing a different project than that of the target service account | You can only manage credentials by referencing the correct project |
RemoveCredentials is lenient by design — if the user_code is valid but there are no active credentials to remove, the API returns success: true with credentials_removed: 0 rather than an error.
Security Best Practices
- Rotate credentials regularly — Don't let keys live forever. Set up a rotation schedule (e.g., every 30–90 days) and use the create/remove flow to cycle keys. Request quota increases if you have reached the maximum number of keys allowed.
- Use IP whitelisting — If your application runs on known infrastructure, whitelist those IPs. This limits the blast radius if a key is leaked.
- Set expiry dates — Use
expires_atas a safety net. Even if you forget to rotate a key, it will expire automatically. - Don't keep unused keys active — If a key is no longer in use, remove it. Fewer active keys means a smaller attack surface.
- Store private keys in a secrets manager — Avoid storing keys as plain text files on disk or in environment variables. Use a dedicated secrets manager for production deployments.
Next Steps
- See the API User API Reference for full request/response details and schema documentation
- Learn about Authenticating Your Requests using the credentials you create
- See Getting Your Credentials for creating service accounts via the portal