Skip to content

Request Signing

NativeSuite signs requests to your API using HMAC, allowing you to verify that incoming requests are genuinely from NativeSuite. This guide explains the signing scheme and how to verify signatures in your backend.

Why Request Signing?

When NativeSuite fetches data from your API on behalf of a user, you want to be sure the request is legitimate. Request signing provides:

  • Authenticity — Confirm the request came from NativeSuite
  • Integrity — Verify the request wasn't tampered with in transit
  • Replay protection — Timestamps prevent old requests from being replayed

How It Works

  1. NativeSuite constructs the request to your API endpoint
  2. It creates a signature using your app's signing secret and the request details
  3. The signature is included in the request headers
  4. Your backend verifies the signature before processing the request

Signature Headers

NativeSuite adds these headers to every request to your data source endpoints:

HeaderDescription
X-NativeSuite-SignatureThe HMAC-SHA256 signature
X-NativeSuite-TimestampUnix timestamp of when the request was signed

Verifying the Signature

Step 1: Extract Headers

Pull the signature and timestamp from the request headers.

Step 2: Check Timestamp

Reject requests where the timestamp is more than 5 minutes old to prevent replay attacks:

python
import time

timestamp = int(request.headers["X-NativeSuite-Timestamp"])
if abs(time.time() - timestamp) > 300:
    return Response("Request expired", status=401)

Step 3: Construct the Signing String

The signing string is composed of:

{timestamp}.{method}.{path}.{body}
  • timestamp — The X-NativeSuite-Timestamp value
  • method — HTTP method, uppercase (e.g., GET)
  • path — The request path (e.g., /api/stats)
  • body — The request body (empty string for GET requests)

Step 4: Compute the Expected Signature

Use HMAC-SHA256 with your app's signing secret:

python
import hmac
import hashlib

signing_string = f"{timestamp}.{method}.{path}.{body}"
expected = hmac.new(
    signing_secret.encode(),
    signing_string.encode(),
    hashlib.sha256
).hexdigest()
javascript
const crypto = require("crypto");

const signingString = `${timestamp}.${method}.${path}.${body}`;
const expected = crypto
  .createHmac("sha256", signingSecret)
  .update(signingString)
  .digest("hex");
go
import (
    "crypto/hmac"
    "crypto/sha256"
    "encoding/hex"
    "fmt"
)

signingString := fmt.Sprintf("%s.%s.%s.%s", timestamp, method, path, body)
mac := hmac.New(sha256.New, []byte(signingSecret))
mac.Write([]byte(signingString))
expected := hex.EncodeToString(mac.Sum(nil))

Step 5: Compare Signatures

Use a constant-time comparison to prevent timing attacks:

python
if not hmac.compare_digest(expected, received_signature):
    return Response("Invalid signature", status=401)

Finding Your Signing Secret

Your app's signing secret is available in the dashboard:

  1. Navigate to your app → Settings
  2. Find the Credentials section
  3. Copy the Signing Secret

You can rotate credentials from the same page if they're ever compromised. After rotation, NativeSuite immediately starts using the new secret.

When to Verify

Signature verification is optional but recommended. Consider your risk model:

  • Public endpoints — Verification adds an extra layer of security
  • Internal endpoints — May be sufficient to rely on network-level security
  • Sensitive data — Always verify signatures when serving user-specific or financial data

Troubleshooting

Signature mismatch

  • Make sure you're using the correct signing secret (not the app ID or API key)
  • Check that your signing string construction matches the format exactly
  • Ensure the body matches byte-for-byte (watch for encoding differences)

Timestamp rejection

  • Clock skew between your server and NativeSuite — ensure your server's clock is synced (NTP)
  • The 5-minute window is a recommendation; adjust based on your needs

Ship native mobile experiences without building an app.