{"templateId":"markdown","versions":[{"version":"1.0","label":"v1.0","link":"/omni-api/overview/authentication","default":true,"active":true,"folderId":"6bec560c"}],"sharedDataIds":{"sidebar":"sidebar-omni-api/@1.0/overview/sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":[]},"type":"markdown"},"seo":{"title":"Authentication","llmstxt":{"hide":false,"sections":[{"title":"Table of contents","includeFiles":["**/*"],"excludeFiles":[]}],"excludeFiles":[]}},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"authentication","__idx":0},"children":["Authentication"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The Omni CLO API uses issuer-scoped server-side API tokens. It does not use OAuth or Bearer authentication."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"authorization-header","__idx":1},"children":["Authorization header"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Send this header with every Percents API request:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"http","header":{"controls":{"copy":{}}},"source":"Authorization: token <token-id>:<token-secret>\n","lang":"http"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The token ID starts with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["tok_"]}," and the secret starts with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["api_"]},"."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"http","header":{"controls":{"copy":{}}},"source":"Authorization: token tok_11111111-1111-4111-8111-111111111111:api_example_secret\n","lang":"http"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Bearer"]},", Basic authentication, query-string credentials, and a token without the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["token "]}," scheme are invalid."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"credential-handling","__idx":2},"children":["Credential handling"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Store the token in a secrets manager."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Use it only from issuer-controlled server infrastructure."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Never include it in browser or mobile code."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Do not log the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Authorization"]}," header."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Use different credentials for sandbox and production."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Contact Percents immediately if a credential is exposed."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"network-access","__idx":3},"children":["Network access"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Percents may enforce a source-IP allowlist before token validation. Provide stable public egress IP addresses or CIDR ranges for every environment that will call the API. Coordinate changes before moving production traffic to new egress addresses."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"authorization-gates","__idx":4},"children":["Authorization gates"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Authentication identifies the issuer. Percents separately enables:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["access to the Omni merchant and offer APIs;"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["file uploads; and"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["specific file content formats such as ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["plaid-txn-stream"]},"."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["A correctly authenticated request can therefore receive ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["401"]}," or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["403"]}," when the issuer is not enabled for the requested capability."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The token inherits issuer scope, so clients do not send an issuer identifier or scope override."," ","Offer, merchant, and transaction-file operations are resolved for the authenticated issuer. Contact"," ","Percents if a credential returns unexpected data; do not attempt to override scope in a query"," ","parameter or payload."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"webhook-signing","__idx":5},"children":["Webhook Signing"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Outgoing webhooks use a different ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["sign_"]}," signing token and the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["X-Percents-Signature"]}," header. Never use the API token to validate a webhook. See ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/omni-api/overview/webhooks/signatures"},"children":["Webhook Signing"]},"."]}]},"headings":[{"value":"Authentication","id":"authentication","depth":1},{"value":"Authorization header","id":"authorization-header","depth":2},{"value":"Credential handling","id":"credential-handling","depth":2},{"value":"Network access","id":"network-access","depth":2},{"value":"Authorization gates","id":"authorization-gates","depth":2},{"value":"Webhook Signing","id":"webhook-signing","depth":2}],"frontmatter":{"seo":{"title":"Authentication"}},"lastModified":"2026-08-11T01:36:09.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/omni-api/overview/authentication","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}