Making your first request

Making your first request

Going from zero to a successful API Call. This guide walks you through authentication, your first GET request, and reading the response.

Prerequisites

1

API credentials

You have your API Key and Secret Key from the Mercury team. If not, request access →

2

Auth understanding

You understand HMAC-SHA256 signing. If not, read the authentication guide → first.

3

HTTP client

Any HTTP client works: cURL, Postman, or your language of choice. We provide examples in cURL, Python, Node.js, Java, and C#.

Sandbox environment

All development and testing should use the sandbox. It mirrors production behaviour with no real money movement.

Your sandbox credentials are separate from production. The API surface is identical. Code that works here works in production with only a base URL change.

Required headers

Every request to the Mercury API must include three authentication headers:

Header Description
x-api-key Your API Key, provided by Mercury
x-nonce A unique value for each request (e.g. UUID). Prevents replay attacks. Must never be reused.
Authorization Your HMAC-SHA256 signature, sent as HMACSHA256 {signature}. See authentication guide for how to generate this.

Step 1: List your clients

The best endpoint to start with is GET /api/v1/client. It takes no parameters and returns all clients under your distributor account. Perfect for validating that your authentication is working correctly.

# 1. Set your credentials
API_KEY="your-api-key"
SECRET_KEY="your-secret-key"

# 2. Generate a unique nonce
NONCE=$(uuidgen)

# 3. Build the string to sign: values joined with newlines (GET requests have no body line)
METHOD="GET"
REQUEST_PATH="/api/v1/client"
STRING_TO_SIGN=$(printf '%s\n%s\n%s\n%s' "$API_KEY" "$METHOD" "$REQUEST_PATH" "$NONCE")

# 4. Sign with HMAC-SHA256
SIGNATURE=$(printf '%s' "$STRING_TO_SIGN" | openssl dgst -sha256 -hmac "$SECRET_KEY" -binary | base64)

# 5. Make the request
curl -s -X GET \
  "https://www.api.external.test.mercury.global${REQUEST_PATH}" \
  -H "x-api-key: ${API_KEY}" \
  -H "x-nonce: ${NONCE}" \
  -H "Authorization: HMACSHA256 ${SIGNATURE}" \
  -H "Content-Type: application/json" | jq .
import base64, hashlib, hmac, uuid
import requests

API_KEY = "your-api-key"
SECRET_KEY = "your-secret-key"
BASE_URL = "https://www.api.external.test.mercury.global"

method = "GET"
path = "/api/v1/client"
nonce = str(uuid.uuid4())

# Build and sign the string (GET requests have no body line)
string_to_sign = "\n".join([API_KEY, method, path, nonce])
signature = base64.b64encode(
    hmac.new(SECRET_KEY.encode(), string_to_sign.encode(), hashlib.sha256).digest()
).decode()

response = requests.get(
    f"{BASE_URL}{path}",
    headers={
        "x-api-key": API_KEY,
        "x-nonce": nonce,
        "Authorization": f"HMACSHA256 {signature}",
        "Content-Type": "application/json",
    },
)

print(response.status_code)
print(response.json())
const crypto = require("crypto");

const API_KEY = "your-api-key";
const SECRET_KEY = "your-secret-key";
const BASE_URL = "https://www.api.external.test.mercury.global";

const method = "GET";
const path = "/api/v1/client";
const nonce = crypto.randomUUID();

// Build and sign the string (GET requests have no body line)
const stringToSign = [API_KEY, method, path, nonce].join("\n");
const signature = crypto
  .createHmac("sha256", SECRET_KEY)
  .update(stringToSign, "utf8")
  .digest("base64");

fetch(`${BASE_URL}${path}`, {
  method: "GET",
  headers: {
    "x-api-key": API_KEY,
    "x-nonce": nonce,
    Authorization: `HMACSHA256 ${signature}`,
    "Content-Type": "application/json",
  },
})
  .then((res) => res.json())
  .then((data) => console.log(JSON.stringify(data, null, 2)));
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.net.URI;
import java.net.http.*;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.UUID;

public class MercuryFirstRequest {
    public static void main(String[] args) throws Exception {
        String apiKey = "your-api-key";
        String secretKey = "your-secret-key";
        String baseUrl = "https://www.api.external.test.mercury.global";

        String method = "GET";
        String path = "/api/v1/client";
        String nonce = UUID.randomUUID().toString();

        // Build and sign the string (GET requests have no body line)
        String stringToSign = String.join("\n", apiKey, method, path, nonce);
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
        String signature = Base64.getEncoder()
            .encodeToString(mac.doFinal(stringToSign.getBytes(StandardCharsets.UTF_8)));

        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create(baseUrl + path))
            .header("x-api-key", apiKey)
            .header("x-nonce", nonce)
            .header("Authorization", "HMACSHA256 " + signature)
            .header("Content-Type", "application/json")
            .GET()
            .build();

        HttpResponse<String> response = HttpClient.newHttpClient()
            .send(request, HttpResponse.BodyHandlers.ofString());

        System.out.println(response.statusCode());
        System.out.println(response.body());
    }
}
using System.Security.Cryptography;
using System.Text;

var apiKey = "your-api-key";
var secretKey = "your-secret-key";
var baseUrl = "https://www.api.external.test.mercury.global";

var method = "GET";
var path = "/api/v1/client";
var nonce = Guid.NewGuid().ToString();

// Build and sign the string (GET requests have no body line)
var stringToSign = string.Join("\n", apiKey, method, path, nonce);
using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(secretKey));
var signature = Convert.ToBase64String(
    hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign)));

using var client = new HttpClient();
client.DefaultRequestHeaders.Add("x-api-key", apiKey);
client.DefaultRequestHeaders.Add("x-nonce", nonce);
client.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", $"HMACSHA256 {signature}");

var response = await client.GetAsync($"{baseUrl}{path}");
var content = await response.Content.ReadAsStringAsync();

Console.WriteLine(response.StatusCode);
Console.WriteLine(content);

Expected response

A successful request returns 200 OK with a JSON array of your clients:

[
  {
    "ClientType": "Corporate",
    "Identifier": "CLIENT-001",
    "ExternalReference": "EXT-REF-001",
    "ExpectedMonthlySpend": 5000,
    "RiskRating": "Low",
    "Contacts": [
      {
        "Identifier": "b7809e48-6407-4b44-b613-921049f2d7e8",
        "FirstName": "Jane",
        "LastName": "Smith",
        "PhysicalAddress": {
          "Street": "1 High Street",
          "City": "London",
          "Region": "Greater London",
          "Postcode": "EC1A 1BB",
          "CountryCode": "GB"
        },
        "DateOfBirth": "1985-06-15"
      }
    ],
    "CorporateDetails": {
      "Name": "Acme Ltd",
      "RegistrationNumber": "12345678",
      "RegisteredAddress": {
        "Street": "1 High Street",
        "City": "London",
        "Region": "Greater London",
        "Postcode": "EC1A 1BB",
        "CountryCode": "GB"
      },
      "IndustryCode": "6419"
    }
  }
]

Troubleshooting

401 Unauthorized
›Check your API Key is correct and sent in x-api-key
›Verify the string to sign: apiKey, method, path, body (not for GET), nonce, joined with \n
›Ensure the nonce is unique per request, including retries. Reused nonces are rejected
›Confirm the Authorization header format is HMACSHA256 [signature], not Bearer
400 Validation Failed
›Read the errors array in the response. It tells you exactly which field failed
›Check required fields are present and correctly typed
›For POST requests, ensure the request body is valid JSON with Content-Type: application/json
›Use Lookup endpoints to get valid values for enum fields
500 Internal Server Error
›Retry after a short delay. This is typically transient
›If persistent, contact support with the request timestamp and nonce
Common Signature Mistakes
›Method must be uppercase: GET not get
›Path must include the leading slash: /api/v1/...
›GET requests have no body line. The string goes straight from path to nonce
›Signature output must be Base64-encoded, not hex

What's next

Need help with authentication?

The step-by-step guide breaks down exactly how HMAC-SHA256 signing works with Mercury.


Did this page help you?