Skip to main content

Secure API Request Signing and Idempotency Mechanism

Overview

This API leverages a robust security mechanism involving HMAC-based request signing, timestamping, unique request identification (nonce), and idempotency keys. These mechanisms collectively ensure the integrity, authenticity, and non-replayability of client requests, as well as safe handling of duplicate submissions. This documentation explains each mechanism, their purposes, and how to implement the required client logic (e.g., in Postman or custom API clients).

1. HMAC Signature (X-Signature Header)

What is it?

An HMAC (Hash-based Message Authentication Code) is a cryptographic signature generated using a shared secret and the request data. It ensures that the request cannot be tampered with, and its sender can be authenticated.

Purpose

  • Integrity: Detects if any part of the request (method, URI, body, timestamp) has been altered.
  • Authentication: Confirms the request is from a trusted client who knows the secret key.
  • Anti-Replay: Tied to a timestamp and unique values, making replay attacks detectable.

How is it used?

  • The client constructs a string to sign, concatenating the HTTP method, full request path (including query), current timestamp in epoch milliseconds, and resolved request body:
dataToSign = HTTP_METHOD + "|" + PATH_WITH_QUERY + "|" + TIMESTAMP + "|" + BODY
  • The client generates the HMAC SHA256 signature using the shared secret (kept in a secure vault, never exposed):
X-Signature = HMAC_SHA256(secret, dataToSign)
  • This signature is sent in the request header X-Signature.
Please ask us HMAC Secret before making your first API call

What if not used?

  • Client will receive an error message with http status 400 - Bad Request
{
  "timestamp": "2025-04-14T16:58:10.414972912",
  "status": 400,
  "error": "Bad Request",
  "message": "Missing signature, timestamp, or nonce headers",
  "path": "/auth/login"
}

What if signature is not valid?

  • Client will receive an error message with http status 401 - Unauthorized
{
  "timestamp": "2025-04-14T16:57:50.083970026",
  "status": 401,
  "error": "Unauthorized",
  "message": "Invalid request signature",
  "path": "/auth/login"
}

2. Timestamp (X-Timestamp Header)

What is it?

The Unix timestamp (in milliseconds) at the moment the request is generated.

Purpose

  • Anti-Replay: Prevents an attacker from reusing a previously valid request, since the server can enforce strict time windows for valid requests.

How is it used?

  • The client generates the timestamp just before sending the request and includes it as the X-Timestamp header.

What if not used?

  • Client will receive an error message with http status 400 - Bad Request
{
  "timestamp": "2025-04-14T16:58:10.414972912",
  "status": 400,
  "error": "Bad Request",
  "message": "Missing signature, timestamp, or nonce headers",
  "path": "/auth/login"
}

3. Nonce (X-Nonce Header)

What is it?

A nonce is a randomly generated unique identifier (UUID v4) included in each request.

Purpose

  • Anti-Replay: Further prevents request replay by uniquely identifying each request. Even if method, URI, and body are the same, the nonce will differ.

How is it used?

  • The client generates a new UUID v4 for every request and includes it as the X-Nonce header.

What if not used?

  • Client will receive an error message with http status 400 - Bad Request
{
  "timestamp": "2025-04-14T16:58:10.414972912",
  "status": 400,
  "error": "Bad Request",
  "message": "Missing signature, timestamp, or nonce headers",
  "path": "/auth/login"
}

What if re-used?

  • Client will receive an error message with http status 409 - Conflict
{
  "timestamp": "2025-04-14T16:57:21.168927321",
  "status": 409,
  "error": "Conflict",
  "message": "Replay attack detected (nonce reused)",
  "path": "/endpoint/uri/here"
}

4. Idempotency Key (X-Idempotency-Key Header)

What is it?

A unique identifier (UUID v4) for each request, enabling the server to recognize and safely ignore duplicate submissions (e.g., from retrying a POST request).

Purpose

  • Idempotency: Guarantees that retrying a request due to network errors will not result in duplicate resource creation or side effects.

How is it used?

  • The client generates a new UUID v4 for each operation and sends it as the X-Idempotency-Key header.

What if not used?

  • Client will receive an error message with http status 400 - Bad Request
{
  "timestamp": "2025-04-14T16:26:54.203118461",
  "status": 400,
  "error": "Bad Request",
  "message": "Missing X-Idempotency-Key header",
  "path": "/endpoint/uri/here"
}

What if re-used?

  • Client will receive an error message with http status 409 - Conflict
{
  "timestamp": "2025-04-14T16:56:28.671809875",
  "status": 409,
  "error": "Conflict",
  "message": "Duplicate request detected (X-Idempotency-Key)",
  "path": "/endpoint/uri/here"
}

Security Considerations

  • The secret used for HMAC must never be shared or exposed in client code or documentation.
  • Always use HTTPS to prevent man-in-the-middle attacks.
  • Servers enforce a maximum allowable time skew for the X-Timestamp and reject used/replayed X-Nonce or X-Idempotency-Key values within a certain window.

Example Headers

X-Signature: 75c759570bbb5dfd40136cffd3dbaa51b28d4620e51359161686790adcc53bea
X-Timestamp: 1752751106704
X-Nonce: 684a0dca-bd6a-4056-a449-2567f9847f9c
X-Idempotency-Key: 777edc03-ad49-4c17-be6b-9baf05a1b9e0

Summary Table

HeaderValue/FormatPurpose
X-SignatureHexadecimal stringRequest authenticity/integrity
X-TimestampMilliseconds since epochPrevent replay
X-NonceUUID v4Uniqueness/anti-replay
X-Idempotency-KeyUUID v4Idempotency for retries