Getting started

Authentication

Every request is authenticated with a Bearer token. Servers use secret API keys; the dashboard and mobile apps use short-lived user access tokens.

Two kinds of credentials#

CredentialWho uses itScope
API key mk_live_…Your backend serversOne organization, limited to the scopes chosen when the key was created.
Access tokenWeb dashboard, iOS and Android appsA user. Organization access follows the member's role.

API keys (servers)#

Send your secret key in the Authorization header. The key already identifies its organization, so no other header is needed.

curl https://api.muny.io/v1/payouts \
  -H "Authorization: Bearer mk_live_..."

Keep secret keys on the server

API keys can move funds. Never embed them in a browser bundle, a mobile app or a public repository. If a key leaks, revoke it in Developers → API keys and create a new one. See API keys.

User tokens (apps and mobile)#

Interactive clients sign a user in and receive a short-lived access_token (15 minutes) plus a long-lived, single-use refresh_token. Tokens are returned in the response body — never only as cookies — so the same flow works for native apps.

POST /v1/auth/login
curl https://api.muny.io/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{
    "email": "abdullah@creatorhub.io",
    "password": "••••••••••",
    "device": { "platform": "ios", "device_name": "iPhone 17" }
  }'
200 OK
{
  "token_type": "Bearer",
  "access_token": "eyJhbGciOiJIUzI1NiIs...",
  "expires_in": 900,
  "refresh_token": "mrt_9QxV...",
  "refresh_expires_at": "2026-10-31T09:30:00.000Z",
  "session_id": "1e0b6b5c-0c1e-4c39-a3f8-2b4f7c9d5e11",
  "user": { "id": "…", "object": "user", "email": "abdullah@creatorhub.io", "name": "Abdullah" }
}

Refreshing

When the access token expires (or a request returns 401), exchange the refresh token for a new pair. Refresh tokens rotate on every use: store the new one and discard the old.

POST /v1/auth/refresh
curl https://api.muny.io/v1/auth/refresh \
  -H "Content-Type: application/json" \
  -d '{ "refresh_token": "mrt_9QxV..." }'

Reuse detection

If a refresh token is presented after it has already been rotated, Muny assumes it was stolen and revokes every session in that token family. The user has to sign in again.
  • On mobile, store the refresh token in the iOS Keychain or Android Keystore — never in plain storage.
  • The web dashboard keeps tokens in HttpOnly, Secure, SameSite cookies on its own server and never exposes them to JavaScript.
  • Sign out with POST /v1/auth/logout to revoke the session.

Choosing an organization#

A user can belong to several organizations. When calling organization resources with a user token, send the organization ID in the Muny-Organization header. Without it, wallet and transaction endpoints use the user's personal account.

bash
curl https://api.muny.io/v1/payouts \
  -H "Authorization: Bearer eyJhbGciOi..." \
  -H "Muny-Organization: 3f6a2c71-8d4e-4b0a-9c55-1e2f3a4b5c6d"

Every organization endpoint checks the member's role — Owner, Admin, Developer, Finance or Viewer — before acting. Requests without the needed permission return 403 permission_error.