#
Authentication
Scope: This guide applies to partner-facing endpoints under
/partner/**in omni-partner-api. Internal or service-to-service endpoints may use different mechanisms.
#
Overview
Omni Partner API uses HMAC-SHA256 request signing. Partners authenticate each request using their Client ID and Secret Key. When acting on behalf of a specific store, partners also pass a Store Client ID and Store Token for authorization.
- Partner identity:
clientId+secretKey - Optional store delegation:
storeClientId+storeToken - Guarded surface:
/partner/**(validated by our HMAC guard)
#
Credentials & Delegation
#
Partner credentials
- Client ID (public): e.g.
ptnr_xxxxx - Secret Key (private): shared out-of-band; do not embed in client-side apps.
#
Store delegation
Include these when calling endpoints that act on a store’s resources:
- Store Client ID (public): e.g.
str_xxxxx - Store Token (private, revokable/expirable): issued during onboarding/rotation.
#
Required headers
Notes
• Header names are case-insensitive in HTTP; when signing, canonicalize to lowercase exactly as listed above. Values remain case-sensitive.
•x-store-client-idandx-store-tokenare required only for store-scoped calls.
#
HMAC signature
Generate x-signature: sha256=<hex> using your partner secretKey over a canonical base string.
#
Canonical components
#
Base string layout
Join the components with a single newline \n:
METHOD
PATH
HEADER1:VALUE
HEADER2:VALUE
...
BODYHASH
#
Signature calculation
signature_hex = HEX( HMAC-SHA256( secretKey, baseString ) )
x-signature: sha256=<signature_hex>
#
Reference
These mirror your flow. Replace <epoch_ms> with the integer epoch (milliseconds) you send in x-timestamp. For no-body requests, the last line is the SHA-256 of the empty string.
#
API GET
Inputs
- Method:
GET - Path:
/partner/stores/catalog/02b65657-bfcd-47ba-9f91-ec67e7b5913e - Headers present:
x-partner-client-id: ptnr_1s4UqMnO64,
x-store-client-id: str_TGIxyboe7-Rz,
x-store-token: stkn_1G_R3r_5QTvwr_0O,
x-timestamp: 1709024577000
Base string (headers sorted alphabetically)
GET
/partner/stores/catalog/02b65657-bfcd-47ba-9f91-ec67e7b5913e
x-partner-client-id:ptnr_1s4UqMnO64
x-store-client-id:str_TGIxyboe7-Rz
x-store-token:stkn_1G_R3r_5QTvwr_0O
x-timestamp:1709024577000
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
#
API POST
Inputs
- Method:
POST - Path:
/partner/stores/catalog/sync - Headers present:
x-partner-client-id: ptnr_1s4UqMnO64,
x-store-client-id: store_NB5DgDcEoWEu,
x-store-token: stkn_Xfe-j_OKH5H2Xg66,
x-timestamp: 1709024577000 - Body: (use the exact JSON bytes you transmit)
Body hash
<BODY_SHA256_HEX>
Base string
POST
/partner/stores/catalog/sync
x-partner-client-id:ptnr_1s4UqMnO64
x-store-client-id:store_NB5DgDcEoWEu
x-store-token:stkn_Xfe-j_OKH5H2Xg66
x-timestamp:1709024577000
<BODY_SHA256_HEX>
Important: Body hash must be computed over the exact string you send on the wire. Whitespace or field-order changes will alter the hash.
#
Example Request (cURL)
curl -X \
POST "https://api.example.com/partner/products?lang=id&sku=SKU-1" -H \
"Content-Type: application/json" -H \
"x-partner-client-id: ptnr_AbC123" -H \
"x-store-client-id: str_9xyZ" -H \
"x-store-token: stkn_example" -H \
"x-timestamp: 1709024577000" -H \
"x-signature: sha256=<computed-hex>" -d '{"name":"Sample","sku":"SKU-1"}'
#
Example Responses
{
"success": false,
"error": {
"code": "AUTH_003",
"message": "Expired or invalid timestamp",
"details": {
"timestamp": "2025-08-27T08:55:28.453Z",
"hint": "Request timestamp must be within 300 seconds",
"context": {
"providedTimestamp": 1756284543435,
"currentTime": 1756284928453,
"ageSeconds": 385
}
}
},
"requestId": "51b97684-b509-4940-b315-12d49b2c0f28"
}
{
"success": false,
"error": {
"code": "VAL_001",
"message": "storeId is required"
},
"requestId": "9b7a4d44-1d7e-4d27-8d6b-1e9a7c2b4f01"
}
Notes
• Use the returnedrequestIdwhen contacting support.
• Ensure your client clock is NTP-synced. If you retry, recompute bothx-timestampandx-signature.
#
Verification notes
x-timestampmust be within ±5 minutes of server time (epoch milliseconds).- The path you sign must match the path you send (after stripping
/api/v1, without query). - Headers included in the signature must also be sent with the same values.
- BODYHASH must reflect the exact stringified body sent.
#
Common pitfalls
- Signing the path with query parameters attached.
- Not lowercasing header names before sorting into the base string.
- Hashing a pretty-printed body but sending minified (or vice versa).
- Forgetting to include
x-store-client-id/x-store-tokenin the canonical headers when calling store-scoped endpoints.