Quick Start
You need a Noon Partner account to follow this guide. If you don't have one yet, check Noon's Partner onboarding process.
1. Get your credentials
- Open the Access App
- Click Add Service Account, fill in a display name, username, and role, then click Add
- A
.jsonkey file will download — this is your credential file:
Keep this file secure
Never commit your .json credential file to source control. It contains your private key.
For the full walkthrough see Getting Your Credentials.
2. Authenticate
Use your .json file to generate a JWT and exchange it for a session cookie. All subsequent API requests use that cookie.
Required header
All API requests must include a User-Agent header identifying your application. Requests without it may be rejected.
- 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"
You're authenticated. Visit the API Reference for the full list of available endpoints.