Skip to main content

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.

Relationship to Existing 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 the user_code handy.

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.

Where do I find these values?

Both values live in the credential payload you already have:

  • From the portal flow — see the .json key file you downloaded in Getting Your Credentials.
  • From the OAuth flow — see the result object returned by the token exchange step in Getting Credentials via OAuth. The channel_identifier field 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.
Store Your Private Key Securely

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).

tip

If there are no active credentials to remove, the API will return success: true with credentials_removed: 0.

Credential Rotation Example

Stay within the key limit

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:

  1. Create a new credential — Call CreateCredential to generate a fresh key pair
  2. Update your application — Deploy the new key to your application or secrets manager
  3. Verify the new key works — Make a test API call using the new credential
  4. 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

Before You Run These 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.

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)")

Limits

LimitValue
Maximum keys per service account5
Maximum whitelisted IPs per credential10

Error Handling

Common error scenarios for CreateCredential:

ErrorDescriptionSolution
User not foundNeither the user_code nor the channel_identifier matches an existing service accountVerify 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 requiredBoth fields were omitted from the requestProvide one of the two — see Identifying the Target Service Account
User is not activeThe service account has been deactivatedReactivate the account through the Noon Partner portal, or create a new service account
Cannot regenerate credentials for this userThe user_code belongs to a non-service accountThis API only works with service accounts. Check that you're using the correct user_code
Not allowed to regenerate credentials for this userYour session is referencing a different project than that of the target service accountYou can only manage credentials by referencing the correct project
apijwt key quota exceeded for the accountThe 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 allowedMore than 10 IPs were provided in whitelisted_ipsReduce the list to 10 or fewer IP addresses
Invalid expires_at formatThe expires_at timestamp is not in valid ISO 8601 formatUse the format: 2026-12-31T23:59:59Z

Common error scenarios for RemoveCredentials:

ErrorDescriptionSolution
User does not existNeither the user_code nor the channel_identifier matches an existing service accountVerify the value you provided
Either user_code or channel_identifier is requiredBoth fields were omitted from the requestProvide one of the two — see Identifying the Target Service Account
Cannot remove channels for this userThe user_code belongs to a non-service accountThis API only works with service accounts. Check that you're using the correct user_code
Not allowed to remove channels for this userYour session is referencing a different project than that of the target service accountYou can only manage credentials by referencing the correct project
tip

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_at as 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