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.
Everything is served from https://api.tensorrail.com. Which header you use
depends on the endpoint:
- Payment endpoints (
/payments,/refunds,/disputes) takeapi-key: rail_…. /v1/…endpoints — the read-oriented Reporting API plus balances, settlements, exports, webhook and key management — take the samerail_*key as a bearer token:Authorization: Bearer rail_….
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
| Key | Prefix | Use | Where |
|---|---|---|---|
| Secret | rail_full_… | Full server-to-server access | Server-side only, never in a browser |
| Publishable | rail_open_… | Browser-safe; must be paired with a payment's client_secret | Hosted 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'sclient_secretto 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
- Node
- Python
curl https://api.tensorrail.com/payments/pay_N5c… \
-H "api-key: rail_full_test_xxx"
const response = await fetch("https://api.tensorrail.com/payments/pay_N5c…", {
headers: { "api-key": "rail_full_test_xxx" },
});
import requests
response = requests.get(
"https://api.tensorrail.com/payments/pay_N5c…",
headers={"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:
| Secret | Publishable | |
|---|---|---|
| Test | rail_full_test_… | rail_open_test_… |
| Live | rail_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).
| Scope | Grants |
|---|---|
payments:read | View payments and transactions |
payments:write | Create and confirm payments |
refunds:read | View refunds |
refunds:write | Create refunds |
settlements:read | View balances |
analytics:read | Run analytics reports |
disputes:read | View disputes |
disputes:write | Respond to disputes |
payouts:read | View payouts — reserved; the payout API is not exposed today |
payouts:write | Create payouts — reserved; the payout API is not exposed today |
webhooks:read | View webhook configuration |
webhooks:write | Update webhook configuration |
customers:read | View customers |
customers:write | Create and update customers |
compliance:read | View compliance information |
compliance:write | Submit compliance information |
routing:read | View routing configuration |
connectors:read | View available processors |
api_keys:manage | Create and revoke API keys |
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:
| Code | Meaning | Usual cause |
|---|---|---|
ERR_1002 | Missing or invalid API key | The 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_1003 | Expired API key | A key past its validity still in use |
ERR_3051 | Mode mismatch | Test key against a live resource or vice versa |
ERR_2002 | Invalid parameter | For 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_3051exists 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.