Authenticating Your Requests
This guide explains how to authenticate your API requests to the Noon Partner API using service account credentials.
Prerequisites
- you already have a Noon Partner account.
- You have created a service account and downloaded the service account key file (
.json). If you haven't done this yet, follow the steps in the Getting Credentials guide.
Step 1: Get Your API Key
To use the API, you need a service account key file (a .json file with your credentials).
- If you don't have one yet, follow the Authentication Guide to create it.
- If you already created a service account, locate the downloaded
.jsonfile — this will be your API key.
⚠️ Keep this file secure. It contains your private key and must never be committed to source control.
Step 2: Authenticate and Make you First API call
Use your API key file to generate a JWT token and exchange it for a session cookie. This cookie is required for all subsequent requests.
Required Header: User-Agent
All API requests must include a User-Agent header identifying your application. Requests without this header may be rejected.
Example:
User-Agent: YourAppName/1.0.0
- Python
- Go
- Java
- Node.js
- PHP
- .NET
- Curl/Bash
import json
import time
import uuid
import jwt
import requests
BASE_URL = "https://noon-api-gateway.noon.partners"
USER_AGENT = "NoonApiClient/1.0"
with open("noon_credentials_sensitive.json", "r", encoding="utf-8") as file:
credentials = json.load(file)
# Create a signed RS256 JWT for the login request.
def create_jwt():
return jwt.encode(
{
"sub": credentials["key_id"],
"iat": int(time.time()),
"jti": str(uuid.uuid4()),
},
credentials["private_key"],
algorithm="RS256",
)
# Log in and return a requests session that keeps auth cookies.
def get_authenticated_session():
session = requests.Session()
session.headers.update({"User-Agent": USER_AGENT})
response = session.post(
f"{BASE_URL}/identity/public/v1/api/login",
json={
"token": create_jwt(),
"default_project_code": credentials["project_code"],
},
)
if response.status_code != 200:
raise Exception(f"Login failed with HTTP {response.status_code}: {response.text}")
return session
# Example authenticated request.
session = get_authenticated_session()
response = session.get(f"{BASE_URL}/identity/v1/whoami")
if response.status_code != 200:
raise Exception(f"Whoami failed with HTTP {response.status_code}: {response.text}")
print("Logged in as:", response.json())
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"net/http/cookiejar"
"os"
"time"
// go get github.com/google/uuid github.com/golang-jwt/jwt/v5
"github.com/golang-jwt/jwt/v5"
"github.com/google/uuid"
)
const BASE_URL = "https://noon-api-gateway.noon.partners"
const USER_AGENT = "NoonApiClient/1.0"
type Credentials struct {
PrivateKey string `json:"private_key"`
KeyID string `json:"key_id"`
ProjectCode string `json:"project_code"`
}
var credentials Credentials
func check(err error) {
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}
// Read credentials from the local sensitive credentials file.
func read_credentials() Credentials {
file, err := os.ReadFile("noon_credentials_sensitive.json")
check(err)
var credentials Credentials
check(json.Unmarshal(file, &credentials))
return credentials
}
// Create a signed RS256 JWT for the login request.
func create_jwt() string {
private_key, err := jwt.ParseRSAPrivateKeyFromPEM([]byte(credentials.PrivateKey))
check(err)
token := jwt.NewWithClaims(jwt.SigningMethodRS256, jwt.MapClaims{
"sub": credentials.KeyID,
"iat": time.Now().Unix(),
"jti": uuid.NewString(),
})
signed_token, err := token.SignedString(private_key)
check(err)
return signed_token
}
// Log in and return an HTTP client that keeps auth cookies.
func get_authenticated_session() *http.Client {
jar, err := cookiejar.New(nil)
check(err)
client := &http.Client{Jar: jar}
body, _ := json.Marshal(map[string]string{
"token": create_jwt(),
"default_project_code": credentials.ProjectCode,
})
req, err := http.NewRequest(
"POST",
BASE_URL+"/identity/public/v1/api/login",
bytes.NewReader(body),
)
check(err)
req.Header.Set("User-Agent", USER_AGENT)
req.Header.Set("Content-Type", "application/json")
resp, err := client.Do(req)
check(err)
defer resp.Body.Close()
response_body, _ := io.ReadAll(resp.Body)
if resp.StatusCode != 200 {
fmt.Fprintf(os.Stderr, "Login failed with HTTP %d: %s\n", resp.StatusCode, response_body)
os.Exit(1)
}
return client
}
// Example authenticated request.
func main() {
credentials = read_credentials()
client := get_authenticated_session()
req, err := http.NewRequest("GET", BASE_URL+"/identity/v1/whoami", nil)
check(err)
req.Header.Set("User-Agent", USER_AGENT)
resp, err := client.Do(req)
check(err)
defer resp.Body.Close()
response_body, _ := io.ReadAll(resp.Body)
if resp.StatusCode != 200 {
fmt.Fprintf(os.Stderr, "Whoami failed with HTTP %d: %s\n", resp.StatusCode, response_body)
os.Exit(1)
}
fmt.Println("Logged in as:", string(response_body))
}
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import java.io.File;
import java.io.StringReader;
import java.net.CookieManager;
import java.net.CookiePolicy;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.security.PrivateKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;
public class Main {
static final String BASE_URL = "https://noon-api-gateway.noon.partners";
static final String USER_AGENT = "NoonApiClient/1.0";
static final ObjectMapper json = new ObjectMapper();
static JsonNode credentials;
static String cred(String key) {
return credentials.get(key).asText();
}
// Read the RSA private key from the credentials file.
static RSAPrivateKey parse_private_key(String private_key_pem) throws Exception {
try (PEMParser parser = new PEMParser(new StringReader(private_key_pem))) {
Object pem_object = parser.readObject();
JcaPEMKeyConverter converter = new JcaPEMKeyConverter();
PrivateKey private_key;
if (pem_object instanceof PEMKeyPair) {
private_key = converter.getKeyPair((PEMKeyPair) pem_object).getPrivate();
} else if (pem_object instanceof PrivateKeyInfo) {
private_key = converter.getPrivateKey((PrivateKeyInfo) pem_object);
} else {
throw new IllegalArgumentException("Unsupported private key format");
}
return (RSAPrivateKey) private_key;
}
}
// Create a signed RS256 JWT for the login request.
static String create_jwt() throws Exception {
RSAPrivateKey private_key = parse_private_key(cred("private_key"));
Algorithm algorithm = Algorithm.RSA256((RSAPublicKey) null, private_key);
return JWT.create()
.withSubject(cred("key_id"))
.withIssuedAt(new Date())
.withJWTId(UUID.randomUUID().toString())
.sign(algorithm);
}
// Log in and return an HTTP client that keeps auth cookies.
static HttpClient get_authenticated_session() throws Exception {
CookieManager cookie_manager = new CookieManager();
cookie_manager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
HttpClient client = HttpClient.newBuilder()
.cookieHandler(cookie_manager)
.build();
String body = json.writeValueAsString(Map.of(
"token", create_jwt(),
"default_project_code", cred("project_code")
));
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(BASE_URL + "/identity/public/v1/api/login"))
.header("User-Agent", USER_AGENT)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(body))
.build();
HttpResponse<String> response = client.send(
request,
HttpResponse.BodyHandlers.ofString()
);
if (response.statusCode() != 200) {
throw new RuntimeException(
"Login failed with HTTP " +
response.statusCode() +
": " +
response.body()
);
}
return client;
}
// Example authenticated request.
public static void main(String[] args) throws Exception {
credentials = json.readTree(new File("noon_credentials_sensitive.json"));
HttpClient session = get_authenticated_session();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(BASE_URL + "/identity/v1/whoami"))
.header("User-Agent", USER_AGENT)
.GET()
.build();
HttpResponse<String> response = session.send(
request,
HttpResponse.BodyHandlers.ofString()
);
if (response.statusCode() != 200) {
throw new RuntimeException(
"Whoami failed with HTTP " +
response.statusCode() +
": " +
response.body()
);
}
System.out.println("Logged in as: " + response.body());
}
}
import fs from 'fs';
import crypto from 'crypto'
const credentials = JSON.parse(
fs.readFileSync('noon_credentials_sensitive.json', 'utf8'),
);
const BASE_URL = 'https://noon-api-gateway.noon.partners';
const USER_AGENT = 'NoonApiClient/1.0';
// Helpers for creating the signed JWT used in the login request.
function base64url(value) {
return Buffer.from(value).toString('base64url');
}
function create_jwt() {
const header = base64url(JSON.stringify({
alg: 'RS256',
typ: 'JWT',
}));
const payload = base64url(JSON.stringify({
sub: credentials.key_id,
iat: Math.floor(Date.now() / 1000),
jti: crypto.randomUUID(),
}));
const signing_input = `${header}.${payload}`;
const signature = crypto.sign(
'RSA-SHA256',
Buffer.from(signing_input),
credentials.private_key,
);
return `${signing_input}.${base64url(signature)}`;
}
// Extract auth cookies from the login response.
function get_cookie_header(response) {
const set_cookie_headers =
response.headers.getSetCookie?.() ||
[response.headers.get('set-cookie')].filter(Boolean);
return set_cookie_headers
.map((cookie) => cookie.split(';')[0])
.join('; ');
}
// Log in and return a small authenticated session wrapper.
async function get_authenticated_session() {
const response = await fetch(`${BASE_URL}/identity/public/v1/api/login`, {
method: 'POST',
headers: {
'User-Agent': USER_AGENT,
'Content-Type': 'application/json',
},
body: JSON.stringify({
token: create_jwt(),
default_project_code: credentials.project_code,
}),
});
if (response.status !== 200) {
throw new Error(`Login failed with HTTP ${response.status}: ${await response.text()}`);
}
const cookie_header = get_cookie_header(response);
return {
get: (path) => fetch(`${BASE_URL}${path}`, {
headers: {
'User-Agent': USER_AGENT,
Cookie: cookie_header,
},
}),
post: (path, body) => fetch(`${BASE_URL}${path}`, {
method: 'POST',
headers: {
'User-Agent': USER_AGENT,
'Content-Type': 'application/json',
Cookie: cookie_header,
},
body: JSON.stringify(body),
}),
};
}
// Example authenticated request.
async function main() {
const session = await get_authenticated_session();
const response = await session.get('/identity/v1/whoami');
if (response.status !== 200) {
throw new Error(`Whoami failed with HTTP ${response.status}: ${await response.text()}`);
}
console.log('Logged in as:', await response.json());
}
main().catch((error) => {
console.error(error.message);
process.exit(1);
});
<?php
require __DIR__ . '/vendor/autoload.php';
// composer require firebase/php-jwt guzzlehttp/guzzle ramsey/uuid
use Firebase\JWT\JWT;
use GuzzleHttp\Client;
use GuzzleHttp\Cookie\CookieJar;
use Ramsey\Uuid\Uuid;
const BASE_URL = 'https://noon-api-gateway.noon.partners';
const USER_AGENT = 'NoonApiClient/1.0';
$credentials = json_decode(
file_get_contents(__DIR__ . '/noon_credentials_sensitive.json'),
true
);
// Create a signed RS256 JWT for the login request.
function create_jwt(): string
{
global $credentials;
return JWT::encode([
'sub' => $credentials['key_id'],
'iat' => time(),
'jti' => Uuid::uuid4()->toString(),
], $credentials['private_key'], 'RS256');
}
// Log in and return a Guzzle client that keeps auth cookies.
function get_authenticated_session(): Client
{
global $credentials;
$client = new Client([
'base_uri' => BASE_URL,
'cookies' => new CookieJar(),
'http_errors' => false,
'headers' => [
'User-Agent' => USER_AGENT,
],
]);
$response = $client->post('/identity/public/v1/api/login', [
'json' => [
'token' => create_jwt(),
'default_project_code' => $credentials['project_code'],
],
]);
if ($response->getStatusCode() !== 200) {
throw new Exception(
'Login failed with HTTP ' .
$response->getStatusCode() .
': ' .
$response->getBody()
);
}
return $client;
}
// Example authenticated request.
$session = get_authenticated_session();
$response = $session->get('/identity/v1/whoami');
if ($response->getStatusCode() !== 200) {
throw new Exception(
'Whoami failed with HTTP ' .
$response->getStatusCode() .
': ' .
$response->getBody()
);
}
echo 'Logged in as: ' . $response->getBody() . PHP_EOL;
.NET
using System.Net;
using System.Net.Http.Json;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
const string BASE_URL = "https://noon-api-gateway.noon.partners";
const string USER_AGENT = "NoonApiClient/1.0";
var credentials = JsonSerializer.Deserialize<Dictionary<string, string>>(
File.ReadAllText("noon_credentials_sensitive.json")
)!;
// Helper for JWT-safe base64 encoding.
string base64url(byte[] value)
{
return Convert.ToBase64String(value)
.TrimEnd('=')
.Replace('+', '-')
.Replace('/', '_');
}
// Create a signed RS256 JWT for the login request.
string create_jwt()
{
var headerJson = JsonSerializer.Serialize(new
{
alg = "RS256",
typ = "JWT"
});
var payloadJson = JsonSerializer.Serialize(new
{
sub = credentials["key_id"],
iat = DateTimeOffset.UtcNow.ToUnixTimeSeconds(),
jti = Guid.NewGuid().ToString()
});
var header = base64url(Encoding.UTF8.GetBytes(headerJson));
var payload = base64url(Encoding.UTF8.GetBytes(payloadJson));
var signingInput = $"{header}.{payload}";
using var rsa = RSA.Create();
rsa.ImportFromPem(credentials["private_key"]);
var signature = rsa.SignData(
Encoding.UTF8.GetBytes(signingInput),
HashAlgorithmName.SHA256,
RSASignaturePadding.Pkcs1
);
return $"{signingInput}.{base64url(signature)}";
}
// Log in and return an HTTP client that keeps auth cookies.
async Task<HttpClient> get_authenticated_session()
{
var handler = new HttpClientHandler
{
CookieContainer = new CookieContainer()
};
var client = new HttpClient(handler)
{
BaseAddress = new Uri(BASE_URL)
};
client.DefaultRequestHeaders.UserAgent.ParseAdd(USER_AGENT);
var response = await client.PostAsJsonAsync("/identity/public/v1/api/login", new
{
token = create_jwt(),
default_project_code = credentials["project_code"]
});
if (response.StatusCode != HttpStatusCode.OK)
{
throw new Exception(
$"Login failed with HTTP {(int)response.StatusCode}: {await response.Content.ReadAsStringAsync()}"
);
}
return client;
}
// Example authenticated request.
var session = await get_authenticated_session();
var response = await session.GetAsync("/identity/v1/whoami");
if (response.StatusCode != HttpStatusCode.OK)
{
throw new Exception(
$"Whoami failed with HTTP {(int)response.StatusCode}: {await response.Content.ReadAsStringAsync()}"
);
}
Console.WriteLine("Logged in as: " + await response.Content.ReadAsStringAsync());
#!/usr/bin/env bash
set -euo pipefail
NOON_BASE_URL="${NOON_BASE_URL:-https://noon-api-gateway.noon.partners}"
CREDENTIALS_FILE="${NOON_CREDENTIALS_FILE:-noon_credentials_sensitive.json}"
NOON_USER_AGENT="${NOON_USER_AGENT:-NoonApiClient/1.0}"
COOKIE_JAR="$(mktemp "${TMPDIR:-/tmp}/noon_cookies.XXXXXX")"
PRIVATE_KEY_FILE="$(mktemp "${TMPDIR:-/tmp}/noon_private_key.XXXXXX")"
trap 'rm -f "$COOKIE_JAR" "$PRIVATE_KEY_FILE"' EXIT
for cmd in curl openssl jq uuidgen; do
command -v "$cmd" >/dev/null 2>&1 || {
echo "Missing required command: $cmd" >&2
exit 1
}
done
[ -f "$CREDENTIALS_FILE" ] || {
echo "Missing credentials file: $CREDENTIALS_FILE" >&2
exit 1
}
# Small helpers for reading credentials and JWT-safe base64 encoding.
cred() {
jq -r --arg key "$1" '.[$key]' "$CREDENTIALS_FILE"
}
b64url() {
openssl base64 -A | tr '+/' '-_' | tr -d '='
}
# Create a signed RS256 JWT for the login request.
create_jwt() {
cred private_key > "$PRIVATE_KEY_FILE"
chmod 600 "$PRIVATE_KEY_FILE"
header_b64="$(printf '%s' '{"alg":"RS256","typ":"JWT"}' | b64url)"
payload_json="$(
jq -cn \
--arg sub "$(cred key_id)" \
--argjson iat "$(date +%s)" \
--arg jti "$(uuidgen | tr '[:upper:]' '[:lower:]')" \
'{sub:$sub,iat:$iat,jti:$jti}'
)"
payload_b64="$(printf '%s' "$payload_json" | b64url)"
signing_input="${header_b64}.${payload_b64}"
signature_b64="$(
printf '%s' "$signing_input" \
| openssl dgst -sha256 -sign "$PRIVATE_KEY_FILE" -binary \
| b64url
)"
printf '%s.%s\n' "$signing_input" "$signature_b64"
}
# Log in and store the returned auth cookies.
get_authenticated_session() {
body="$(
jq -cn \
--arg token "$(create_jwt)" \
--arg project_code "$(cred project_code)" \
'{token:$token,default_project_code:$project_code}'
)"
login_result="$(
curl --silent --show-error \
--request POST "${NOON_BASE_URL}/identity/public/v1/api/login" \
--header "User-Agent: ${NOON_USER_AGENT}" \
--header "Content-Type: application/json" \
--cookie-jar "$COOKIE_JAR" \
--data "$body" \
--write-out $'\n%{http_code}'
)"
login_status="${login_result##*$'\n'}"
login_body="${login_result%$'\n'*}"
if [ "$login_status" != "200" ]; then
echo "Login failed with HTTP $login_status:" >&2
echo "$login_body" >&2
exit 1
fi
printf '%s\n' "$COOKIE_JAR"
}
# Example authenticated request.
SESSION_COOKIE_JAR="$(get_authenticated_session)"
whoami_result="$(
curl --silent --show-error \
--request GET "${NOON_BASE_URL}/identity/v1/whoami" \
--header "User-Agent: ${NOON_USER_AGENT}" \
--cookie "$SESSION_COOKIE_JAR" \
--cookie-jar "$SESSION_COOKIE_JAR" \
--write-out $'\n%{http_code}'
)"
whoami_status="${whoami_result##*$'\n'}"
whoami_body="${whoami_result%$'\n'*}"
if [ "$whoami_status" != "200" ]; then
echo "Whoami failed with HTTP $whoami_status:" >&2
echo "$whoami_body" >&2
exit 1
fi
printf 'Logged in as: %s\n' "$whoami_body"
Step 3: Next Steps
Now that you can authenticate and call APIs, you can visit the API Reference for the full list of endpoints.