Requests
Base URLs, authentication headers, API key types, and error format — the mechanics common to every moat API call.
Base URLs
Sandbox
The sandbox environment is for integration and testing. Transactions submitted here are simulated — they never reach a real processor, never move money, and never appear on any card statement.
https://sandbox.fluidpay.com
Production
Production is live processing. Only point your integration here once you have verified the full set of flows you need in sandbox.
https://app.fluidpay.com
Mixing sandbox and production credentials is the most common cause of unauthorized responses. Sandbox keys do not work against production, and vice versa.
Versioning
The API is backwards compatible. You do not need to send a version header, and versions are not pinned in the URL. When a new feature ships, existing calls continue to work unchanged. Breaking changes, should they ever be necessary, would be announced well in advance through the Control Panel.
Current release: 1.5.1.
Required headers
Authorization
Every call includes an Authorization header. The value is either a JWT (for session-scoped tokens) or an API key.
Authorization: Bearer {JWT}
Authorization: {API_KEY}
API keys
API keys live in Settings → API Keys in your Control Panel. Each key belongs to a user account. Two types exist:
| Type | Prefix | Use from | Typical use |
|---|---|---|---|
| Public | pub_ | Client-side | Tokenizer, Cart sessions |
| Private | api_ | Server-side | Transaction processing, Customer Vault, Recurring |
Never embed api_ keys in browser code, mobile apps, emails, or support tickets. If a private key leaks, revoke it and issue a new one immediately. Using a private key from client-side code will fail with an unauthorized response by design.
Content-Type
Almost always application/json. Some endpoints (batch uploads, file attachments) accept other types; those are called out in the relevant page. Responses are always JSON.
Error format
Standard HTTP status codes indicate the success or failure of a request. On errors the body is a short JSON object:
{
"status": "failed",
"msg": "bad request error: invalid Postal Code"
}
The msg field describes what the server rejected and is the first thing to read when a call fails.
Unauthorized responses
When a request comes back unauthorized, the issue is almost always one of these:
- The
Authorizationheader is missing or malformed. - The API key was revoked or never existed.
- You are using a public key (
pub_) where a private key (api_) is required, or vice versa. - The key has IP or URL restrictions that your caller does not match.
- You are calling as a merchant user where a partner user is required, or vice versa.
- You are sending a sandbox key to production (or production key to sandbox).
- The key is URL-restricted and you are calling from a URL (including
localhost) that does not match.
URL-restricted keys expect a real hostname in the request origin. If you are developing locally, leave the URL field blank on the key, or use a tunnel (ngrok, Cloudflare) to get a real hostname.
Correlation ID
Every response carries an x-correlation-id response header. This ID threads the request through moat's internal logs. When something goes wrong, log this value along with the rest of the response — it is what support will ask for first.
HTTP/1.1 200 OK
Content-Type: application/json
x-correlation-id: 9f3d7c8a-2b1e-4b2c-9a4e-5d6f7a8b9c0d