Programmatic Access

Overview

This page is your starting point for calling the MoneyHash API directly: the base URL, how to authenticate test vs live with your API keys, the headers to send, and how requests and responses are shaped. After reading it, you'll be able to make a correctly-formed, authenticated API call without guessing.

MoneyHash exposes a JSON REST API over HTTPS. Every server-to-server request is authenticated with an account API key sent in the x-api-key header, and every response comes back in a consistent JSON envelope. The environment a call runs against - Test or Live - is decided entirely by which API key you use, not by a different URL.


Prerequisites

  • An account API key (test and/or live) for the account you're integrating. See Organization and Account for how keys are organized.
  • A server-side environment to send requests from. API keys are secrets and must never be shipped in a frontend or mobile app - the only client-side key is the public API key, which is used by the SDKs, not the REST API.
  • A tool to make HTTP requests (cURL, your backend HTTP client, etc.).

Base URL

All endpoints share a single base URL, with the API version in the path:

https://web.moneyhash.io/api/v1.4/

The version segment (currently v1.4) may change as newer versions are released - always use the latest documented version rather than hardcoding assumptions around it. The same base URL serves both Test and Live; the environment is selected by your key (see below).


API keys

KeyUsed forWhere
Account API keyAccount-level operations (payments, intents, transactions)Your backend, in x-api-key
Organization API keyOrganization-level endpoints (e.g. creating accounts)Your backend, in x-api-key
Public API keySDK & frontend usage onlyClient (not used for REST)

Each account has separate keys per environment - a test account API key and a live account API key (and likewise for the public key). For full detail on the key hierarchy and where each one lives, see Organization and Account.


Authentication & security

Authenticate every request by sending your key in the x-api-key header:

curl --location 'https://web.moneyhash.io/api/v1.4/payments/intent/' \
  --header 'Content-Type: application/json' \
  --header 'x-api-key: <YOUR_ACCOUNT_API_KEY>' \
  --data '<REQUEST_BODY>'

Test vs Live is determined solely by the key you use. Send your test account API key to operate in Test mode, or your live account API key to operate in Live mode - the endpoint and base URL are identical for both. There's no environment header or query flag to set; the key carries the environment.

Account vs organization endpoints. Most endpoints are account-level and use the account API key. Some endpoints are organization-level and accept only the organization API key - for example, creating an account:

curl --location 'https://web.moneyhash.io/api/v1.4/accounts/' \
  --header 'Content-Type: application/json' \
  --header 'x-api-key: <YOUR_ORGANIZATION_API_KEY>' \
  --data '<REQUEST_BODY>'

Keep all API keys on the server, store them as secure secrets, and never expose them client-side.


Headers

HeaderRequiredNotes
x-api-keyYesYour account (or organization) API key. Required on every request.
Content-TypeYes for requests with a bodyUse application/json.
X-Idempotency-KeyOptionalA v4 UUID to make write requests safe to retry. See Idempotency.

HTTP header names are case-insensitive, so x-api-key and X-Api-Key are equivalent.

Request bodies may be sent as application/json (recommended, and used throughout this page) or application/x-www-form-urlencoded.


Request and response format

Requests and responses are JSON. Every response uses the same envelope:

{
  "status": { "code": 200, "message": "success", "errors": [] },
  "data": { },
  "count": null,
  "next": null,
  "previous": null
}
  • status - code (mirrors the HTTP status), a message, and an errors array (empty on success).
  • data - the result: an object for a single resource, or an array for a list.
  • count / next / previous - pagination fields (see below); null for non-list responses.

The envelope never changes shape, so you can rely on the same fields for every call - check status.code first, then read data. Lists add the pagination fields; single-resource responses leave them null.

Time format

All timestamps are ISO 8601 in UTC, where the trailing Z means UTC - for example 2026-06-28T08:11:31.170743Z.


Pagination

List endpoints return count (total number of items) along with next and previous - fully-qualified URLs for the adjacent pages, or null when there is no such page. Control the page with the limit and offset query parameters; limit has a maximum of 100.

https://web.moneyhash.io/api/v1.4/accounts/?limit=20&offset=20

To page through a full result set, follow next until it is null — don't compute offsets yourself; next already carries the correct limit/offset (and any required tokens):

{
  "status": { "code": 200, "message": "success", "errors": [] },
  "data": [
    { "id": "Vgln9", "name": "string", "payment_methods": [] },
    { "id": "A9eEg", "name": "string", "payment_methods": ["CARD"] }
  ],
  "count": 442,
  "next": "https://web.moneyhash.io/api/v1.4/accounts/?limit=20&offset=20",
  "previous": null
}

Errors

On failure, status.code carries a 4xx code, status.errors lists what went wrong (each entry maps a field to a message), and data is empty:

{
  "status": {
    "code": 400,
    "message": "",
    "errors": [
      { "operation": "\"pay\" is not a valid choice." },
      { "webhook_url": "This field is required." }
    ]
  },
  "data": {},
  "count": null,
  "next": null,
  "previous": null
}

A missing resource returns 404:

{
  "status": { "code": 404, "message": "", "errors": [ { "detail": "Not found." } ] },
  "data": {},
  "count": null,
  "next": null,
  "previous": null
}

Status codes

The HTTP status code and status.code mirror each other, so you can check either.

CodeMeaningWhat to do
200SuccessRead data.
400Validation / bad request