Skip to main content
Gainsight Inc.

HMAC Identity Verification (Lookup Key)

This article is intended for admins who enable identity verification and developers who implement the signing and key-management logic on their servers.

Overview

Identity verification confirms that a logged-in user in your application is who they claim to be before Gainsight PX accepts data for that user. Your server signs a checksum using a shared secret key, and Gainsight PX validates that checksum on every identify call.

This method protects the complete identify payload, including all user and account fields, from unauthorized changes. It also supports nonce rotation to prevent previously generated checksums from being reused indefinitely.

The lookup key method for HMAC identity verification must be enabled for your subscription. Contact Gainsight Support to request access. If you use the user hash method, refer to HMAC Identity Verification (User Hash) article instead.

Three concepts drive this method:

  • Lookup key: A value you generate and register with Gainsight PX. You send this in every identify call.
  • Nonce: A value Gainsight PX generates and maps to your lookup key. You use it to build the string you sign, but you never send it in an identify call.
  • Checksum: The HMAC-SHA256 signature you compute and send with each identify call, so Gainsight PX can confirm the payload has not been altered.

This method is available in the Gainsight PX WebSDK.

Prerequisites

Confirm the following before you register a key:

  • Feature enabled: The HMAC dynamic key feature must be enabled for your subscription from Administration > SECURITY > Identity verification.

    Gainsight PX Identity Verification settings showing enforcement controls, identity verification secret, secret generation, and hash verification options
     
  • API key: You need a Gainsight PX API key to call the registration, retrieval, rotation, and deletion endpoints. Pass it in the X-APTRINSIC-API-KEY header.
  • Subscription secret key: You need your subscription secret key to compute the checksum. This is the same secret key used for other Gainsight PX server-side signing.

Key Considerations

Design your integration around these operational rules:

  • Key limit: Each subscription can have a maximum of 25 active keys.
  • Key and nonce TTL: Each key-nonce pair expires 90 days after creation. Plan to rotate keys before they expire.
  • Cache the nonce: Cache the nonce on your server after registration, and use your cached copy to generate checksums. Do not retrieve the nonce for each identify call.
  • Propagation delay: Allow approximately two minutes after registration or rotation before signing identify calls with the new nonce.
  • Rate limits: Every key-management endpoint (register, retrieve, rotate, and delete) is rate limited. Design your integration so key management happens occasionally, not as part of your regular request flow.

How HMAC Identity Verification Works

At a high level, the flow is:

  1. Register a Key and Get a Nonce: Register a lookup key with Gainsight PX and receive a nonce in return. Cache the nonce on your server. Do this once per key, or again ahead of a planned rotation.
  2. Generate the HMAC Checksum: Generate the checksum by signing a canonical string that includes your user fields, your account fields, and the nonce.
  3. Send the Identify Call: Send the lookup key and the checksum in your identify call.
  4. Verify the Payload: Gainsight PX resolves the nonce associated with the lookup key, rebuilds the canonical string, and verifies the checksum.

If the cached nonce is unavailable, use the nonce retrieval API to recover it. Do not retrieve the nonce as part of the regular identify flow. For more information, refer to the Retrieve a Nonce section.

 

Do not send the nonce in the identify call. Send the lookup key in the nonceKey field.

Implement HMAC Identity Verification

Complete the following steps to implement HMAC identity verification in your application.

Register a Key and Get a Nonce

Register a lookup key to receive a nonce from Gainsight PX.

Endpoint

POST /v1/subscription/identify/nonce

Authentication

X-APTRINSIC-API-KEY: <your-api-key>

Request

POST /v1/subscription/identify/nonce
{
  "key": "my-random-lookup-key-abc123"
}

Response

{
  "key": "my-random-lookup-key-abc123",
  "nonce": "9d1e4b72-cc38-4f01-b883-2a5f0d916e44",
  "createdAt": 1755000000000,
  "createdBy": "user@example.com",
  "expiresAt": 1762776000000
}

Registering a key that already exists does not overwrite it. If you submit a key that is already registered, the request fails with a 409 KEY_ALREADY_EXISTS error. For more information on how to issue a new nonce for an existing key, refer to the Rotate a Key section.

Cache the nonce on your server after registration. You use the nonce to generate checksums for subsequent identify calls.

A newly registered key takes approximately two minutes to reach Gainsight PX. Identify calls signed with its nonce are rejected until propagation completes, even though the key already shows a status of ACTIVE.

Generate the HMAC Checksum

Ensure that you follow the specified field order and formatting when building the canonical string. Incorrect ordering or formatting causes the identify call to fail verification.

Build the canonical string in this exact order:

  1. Sort your user fields alphabetically by field name, and list each as field=value.
  2. Sort your account fields alphabetically by field name, and list each as field=value.
  3. Append the nonce as the final segment, in the form nonce=<nonce-value>.
  4. Join all segments with a pipe (|) character.

Example

User fields:

email=jane.doe@acme.com
firstName=Jane
id=user-001
lastName=Doe

Account fields

id=acme-corp
plan=enterprise

Canonical string

email=jane.doe@acme.com|firstName=Jane|id=user-001|lastName=Doe|id=acme-corp|plan=enterprise|nonce=9d1e4b72-cc38-4f01-b883-2a5f0d916e44

Checksum

checksum = HMAC-SHA256(yourSubscriptionSecretKey, canonicalString)

Sign the canonical string with your subscription secret key, not with the nonce. The nonce is part of the string being signed; it is never used as the signing key. A checksum signed with the nonce is rejected.

 

Field values are not escaped or encoded before they are joined. Send them exactly as they appear in your identify call, including any values that contain a | or = character.

Send the Identify Call

Pass the checksum and your lookup key in the identify call, as a single options object: the fourth argument, after the integration context.

aptrinsic("identify",
  {
    "id":        "user-001",
    "email":     "jane.doe@acme.com",
    "firstName": "Jane",
    "lastName":  "Doe"
  },
  {
    "id":   "acme-corp",
    "plan": "enterprise"
  },
  null,
  {
    checksum: "<computed-checksum>",
    nonceKey: "my-random-lookup-key-abc123"
  }
);

  • checksum is the value you computed in the previous step.
  • nonceKey contains your lookup key, not the nonce.

If you send the identify request directly, rather than through the WebSDK helper, the checksum value is carried in a field named payloadChecksum on the wire. nonceKey keeps the same name in both places.

Manage Lookup Keys

After you implement HMAC identity verification, you can retrieve, rotate, or delete lookup keys as needed.

Retrieve a Nonce

Use this endpoint to recover a nonce or review your registered keys, for example after a server restart.

Endpoint

GET /v1/subscription/identify/nonce

Authentication

X-APTRINSIC-API-KEY: <your-api-key>
  • Pass ?key=<your-key> to retrieve a single key.
  • Omit the key parameter to return every key registered for your subscription.

Single-key Response

{
  "key": "my-random-lookup-key-abc123",
  "nonce": "9d1e4b72-cc38-4f01-b883-2a5f0d916e44",
  "createdAt": 1755000000000,
  "expiresAt": 1762776000000,
  "lastModifiedAt": 1755000000000,
  "createdBy": "user@example.com",
  "lastModifiedBy": "user@example.com",
  "status": "ACTIVE"
}

List Response (No Key Parameter)

{
  "keys": [ /* one entry per key, same shape as above */ ],
  "total": 3,
  "cap": 25
}

This endpoint is rate limited. Use it for recovery only. Do not call it on every identify call, or in real time during normal application use. Cache the nonce locally instead.

Rotate a Key

Rotate a lookup key to generate a new nonce for the existing key, without changing the key name. Because key-nonce pairs expire after 90 days, plan to rotate before expiration.

Rotating a key generates a new nonce for that key and invalidates the previous one.

A rotated key takes approximately two minutes to reach Gainsight PX. There is also a two-minute grace period after rotation during which identify calls signed with the old nonce are still accepted, to cover requests already in flight. Re-sign your identify calls with the new nonce once propagation completes, and do not rely on the grace period lasting longer than two minutes.

Endpoint

PUT /v1/subscription/identify/nonce/{key}

Authentication

X-APTRINSIC-API-KEY: <your-api-key>

API Errors

HTTP Status Error Code Meaning
400 N/A The key field is missing or empty in a register request.
401 N/A Your API key is missing or invalid.
403 FEATURE_DISABLED The HMAC dynamic key feature is not enabled for your subscription.
404 N/A No key was found for the value you provided. This means the key was never registered, or it has expired.
409 KEY_ALREADY_EXISTS You submitted a key that is already registered. Use rotate instead.
409 CAP_EXCEEDED Your subscription has reached its maximum of 25 active keys.
409 CONCURRENT_MODIFICATION Two rotation requests for the same key were submitted at the same time. Retry the rotation.

Error responses are returned in a consistent structure: status, errorMessage, errorCode, and timestamp.

Troubleshoot Identify Calls Rejected with a Generic Error

Gainsight PX returns the same generic rejection for several distinct causes: an incorrect nonce, a tampered payload, a key that has not finished propagating, or a missing checksum. Work through this checklist:

  1. Confirm you signed with your subscription secret key, not the nonce.
  2. Confirm the canonical string field order matches exactly: sorted user fields, then sorted account fields, then nonce=<value>.
  3. Confirm you sent the lookup key (nonceKey), not the nonce itself, in the identify call.
  4. Confirm the key has finished propagating (allow two minutes after registration or rotation).
  5. Confirm the key has not expired (90-day TTL).