Skip to main content

Authentication

TensorRail uses API keys. There is one base URL, https://api.tensorrail.com, and your key selects the environment: …_test_… keys operate on sandbox data, …_live_… keys on production.

Two auth headers, one host

Everything is served from https://api.tensorrail.com. Which header you use depends on the endpoint:

  • Payment endpoints (/payments, /refunds, /disputes) take api-key: rail_….
  • /v1/… endpoints — the read-oriented Reporting API plus balances, settlements, exports, webhook and key management — take the same rail_* key as a bearer token: Authorization: Bearer rail_….
Explore the API

The main API is published as an OpenAPI spec, downloadable at /openapi/tensorrail-merchant.json. Import it into Postman or Insomnia to browse and try those endpoints against your test keys. The spec covers the main API; the /v1 account and reporting endpoints are documented on the Reporting API guide pages instead.

Key types

KeyPrefixUseWhere
Secretrail_full_…Full server-to-server accessServer-side only, never in a browser
Publishablerail_open_…Browser-safe; must be paired with a payment's client_secretHosted checkout and client-side flows
  • Secret keys (rail_full_test_…, rail_full_live_…) authenticate every server call: create, confirm, capture, cancel, retrieve, list, and refunds. Keep them secret and server-side.
  • Publishable keys (rail_open_test_…, rail_open_live_…) are safe to expose in the browser. They cannot authenticate server APIs on their own; they are used together with a payment's client_secret to drive the hosted page or a client-side confirm.

This split is what makes the browser flow safe: a publishable key plus a client_secret can act on exactly one payment (the one whose secret it holds) and nothing else. A leaked publishable key cannot create payments, list data, or refund anything.

Sending the key

Pass your secret key in the api-key header on every request:

curl https://api.tensorrail.com/payments/pay_N5c… \
-H "api-key: rail_full_test_xxx"

Test mode lives in the key

There is no separate sandbox host. The mode is encoded in the key:

SecretPublishable
Testrail_full_test_…rail_open_test_…
Liverail_full_live_…rail_open_live_…

Test-mode and live-mode data never mix: payments you create with a test key never appear in your live balance, reporting, or settlements. Presenting a key whose mode does not match the resource is rejected with a mode-mismatch error (ERR_3051), which is your safety net against an environment loading the wrong key.

Scopes

Each key carries scopes that gate access. On the Reporting API (the /v1 surface, the /v1/… endpoints), a request whose key lacks the required scope returns 403 (ERR_1004).

ScopeGrants
payments:readView payments and transactions
payments:writeCreate and confirm payments
refunds:readView refunds
refunds:writeCreate refunds
settlements:readView balances
analytics:readRun analytics reports
disputes:readView disputes
disputes:writeRespond to disputes
payouts:readView payouts — reserved; the payout API is not exposed today
payouts:writeCreate payouts — reserved; the payout API is not exposed today
webhooks:readView webhook configuration
webhooks:writeUpdate webhook configuration
customers:readView customers
customers:writeCreate and update customers
compliance:readView compliance information
compliance:writeSubmit compliance information
routing:readView routing configuration
connectors:readView available processors
api_keys:manageCreate and revoke API keys
Reserved scopes

A key can carry payouts:read / payouts:write, but money-out is not exposed on the merchant API: /v1/payouts and /v1/settlements* return 404 today. settlements:read is live and is what GET /v1/balances requires. Payouts and settlement requests are handled by your account manager; the scopes exist so that keys do not need reissuing when the surface opens.

New keys include the 19 default scopes listed above. Contact your account manager for additional scopes (for example routing:write). The machine-readable form is GET /v1/scopes; see API key management.

Authentication errors you will meet

All auth failures use the standard error body and stable codes; branch on error.code:

CodeMeaningUsual cause
ERR_1002Missing or invalid API keyThe api-key header was not sent, or its value is wrong — a truncated paste, or a rotated or revoked key still deployed. Payment endpoints return this in both cases; ERR_1001 is emitted only on /v1/*, where auth is Authorization: Bearer.
ERR_1003Expired API keyA key past its validity still in use
ERR_3051Mode mismatchTest key against a live resource or vice versa
ERR_2002Invalid parameterFor example a secret-key confirm that also passes client_secret

Treat any ERR_1xxx as a configuration alert, never something to retry in a loop.

Browser flows and client_secret

For anything in the browser, use the publishable key together with the payment's client_secret (returned when you create the payment). A confirm from the browser uses the publishable key plus client_secret. A secret-key call that also passes client_secret is rejected (ERR_2002): keep secret keys server-side and pair the publishable key with the client_secret client-side.

Handle the client_secret like a short-lived credential: pass it to the paying customer's session only, do not log it, and do not store it beyond the checkout.

Keeping keys safe

  • Never ship a secret key to the browser, a mobile binary, or source control. Load it from an environment variable or secret store.
  • Manage, create, and rotate keys from the dashboard under Developers → API Keys. Rotation issues a new key so you can cut over without downtime; sensitive key operations in the dashboard require step-up verification.
  • If a key is exposed, rotate it immediately, then check your webhook deliveries and payment list for anything unexpected.
  • Use different keys per environment and never point staging at live keys; ERR_3051 exists to catch exactly this, but the goal is to never see it.

See Testing and sandbox for the build-then-go-live key workflow.

TensorRail, Limassol, Cyprus.