REST · HMAC-signed
One key.
Spot and futures.
mSamex exposes both matching engines under a single API key. Sign the request once, hit either base URL.
https://api.msamex.com/api/v2/spothttps://api.msamex.com/api/v2/futuresGet a key
Four steps. The whole thing takes about two minutes, and step 1 is not optional.
Enable two-factor authentication
Key creation is gated on 2FA server-side. Without an authenticator app on your account the request fails with 400 resource.api_key.2fa_disabled — from the website and from a direct API call alike. There is no way around it, by design: a key can place orders with your money.
Open your account's API keys
Go to Account → API keys and choose to create a new key. You will be asked for the six-digit code from your authenticator.
Copy the secret — it is shown once
You get two values: an access key (the kid) and a secret. The kid stays visible in your account; the secret is displayed exactly once and never again. Copy the whole string — a half-copied secret produces authz.invalid_signature on every request and is indistinguishable from a wrong signing implementation.
Verify it before you build on it
Sign one request and check the status. A 200 here means your signing is correct; anything else is worth fixing now rather than mid-integration.
Authentication#
Every authenticated request carries three headers. The signature is an HMAC-SHA256 of nonce + kid — the concatenation, in that order, with no separator. Not the body, not the path, not the method.
| Header | Value |
|---|---|
| X-Auth-Apikey | Your access key (kid). |
| X-Auth-Nonce | Current UTC time in milliseconds. |
| X-Auth-Signature | HMAC-SHA256(secret, nonce + kid), lowercase hex. |
Date.now() in JavaScript is already correct. time.time() in Python returns seconds and must be multiplied by 1000. A nonce in seconds returns authz.nonce_expired — the same error as a genuinely stale nonce.
This is the standard HMAC scheme used across most exchange APIs. Bots written against a comparable exchange port with minimal changes — swap the base URL and keys.
Rate limits#
Limits apply per API key, not per IP. Measured end-to-end capacity: 9,958 requests/minute. Distribute work across keys if a single strategy needs more.
Errors#
Response bodies as returned by the engine.
| Status | Body | Cause |
|---|---|---|
| 401 | {"error":"Missing Authorization header"} | No auth headers sent. |
| 401 | {"errors":["authz.invalid_signature"]} | Signed the wrong string. Sign nonce + kid only. |
| 401 | {"errors":["authz.nonce_expired"]} | See the nonce trap below. |
| 401 | {"errors":["authz.unexistent_apikey"]} | kid not recognised. |
| 403 | Forbidden | Withdrawal or key-management path. API keys cannot reach these. |
| 404 | {"error":"Market 'xxx' not found"} | Unknown market id. |
| 422 | Failed to deserialize | Wrong field name or type. |
| 400 | {"errors":["resource.api_key.2fa_disabled"]} | Account has no 2FA. Keys require it. |
A nonce in seconds returns exactly the same error as a stale nonce. If you see nonce_expired, check the unit before you check the clock. Compare against GET /api/v2/spot/public/timestamp — the server's current time, no auth required.
POST /api/v2/futures/margin_mode expects the field mode, not margin_mode. Sending margin_mode returns 422. Some older spec material documents the other name; the spec is wrong and the engine is right.
Key permissions#
An API key cannot withdraw. Withdrawal and key-management endpoints return 403 to any API-key-authenticated request. A leaked key can place and cancel orders; it cannot move funds off the platform.
- Creating a key requires two-factor authentication on the account.
- If a key is exposed, disable it immediately — it can still trade until you do.
- Keys are created and revoked in the web app only, never through the API.
Order types#
Passed as ord_type. reduce_only is a separate boolean flag on futures orders.
| ord_type | Trigger | Becomes |
|---|---|---|
| limit | — | Rests at price. |
| market | — | Executes immediately at the best available price. |
| stop_market | stop_price touched | A market order. Fills, at whatever the market is. |
| stop_limit | stop_price touched | A limit order at price. It rests — it may not fill at all if the market runs through your price. |
| take_profit_market | stop_price touched (in profit) | A market order. |
| take_profit_limit | stop_price touched (in profit) | A limit order at price. Same resting caveat as stop_limit. |
| ioc | — | Fills what it can immediately; the remainder is cancelled. |
A stop that becomes a limit order only protects you if the market trades at your limit. In a fast move it can be skipped entirely. Use stop_market when you need the position closed.
Public#
No authentication. Rate-limited per IP.
Futures#
Base /api/v2/futures. Authenticated. Leverage up to 1000× (500× on BTC, 12 leverage tiers — see the note below).
Spot#
Base /api/v2/spot. Authenticated.