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.

Spothttps://api.msamex.com/api/v2/spot
Futureshttps://api.msamex.com/api/v2/futures
101futures markets
54spot markets
0.020%maker
0.055%taker

Get a key

Four steps. The whole thing takes about two minutes, and step 1 is not optional.

1

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.

2

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.

3

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.

4

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.

HeaderValue
X-Auth-ApikeyYour access key (kid).
X-Auth-NonceCurrent UTC time in milliseconds.
X-Auth-SignatureHMAC-SHA256(secret, nonce + kid), lowercase hex.
Nonce is milliseconds

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.

Porting

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.

StatusBodyCause
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.
403ForbiddenWithdrawal or key-management path. API keys cannot reach these.
404{"error":"Market 'xxx' not found"}Unknown market id.
422Failed to deserializeWrong field name or type.
400{"errors":["resource.api_key.2fa_disabled"]}Account has no 2FA. Keys require it.
The nonce_expired trap

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.

The margin_mode trap

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_typeTriggerBecomes
limitRests at price.
marketExecutes immediately at the best available price.
stop_marketstop_price touchedA market order. Fills, at whatever the market is.
stop_limitstop_price touchedA limit order at price. It rests — it may not fill at all if the market runs through your price.
take_profit_marketstop_price touched (in profit)A market order.
take_profit_limitstop_price touched (in profit)A limit order at price. Same resting caveat as stop_limit.
iocFills what it can immediately; the remainder is cancelled.
stop_limit is not protection

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.

Copied