Authentication & Environments

API keys, environments, pagination, errors and the conventions every Monark request follows.

Everything on this page applies to every Monark endpoint. It is worth reading once before you write any client code, because several of these conventions differ from what an API of this shape usually does.

Authentication

Send your API key in the Authorization header:

Authorization: <your API key>

The header is parsed by splitting on whitespace and taking the last token, so Authorization: Bearer <key> works identically. There is no other accepted header.

Note: If you have seen X-Api-Key in a sample somewhere, it was not a Monark header — some client-side proxies use it internally and convert. The API itself reads Authorization and nothing else.

Keys expire. Each key carries an expiry, and an expired key fails authentication outright rather than degrading. Track the expiry you were issued and rotate ahead of it.

Keys are scoped to their owner. A partner key carries a partner id, and every query is filtered by it. This is structural rather than a convention — it is why another partner's investor reads as a 404 rather than a 403. See Data Access Patterns.

Environments

Sandbox and production are separate deployments with separate keys and separate data. An investor, account or transaction created in sandbox does not exist in production.

EnvironmentBase URL
Sandboxhttps://sandbox-api.monark-markets.com
ProductionIssued by Monark at go-live

Request a sandbox key at [email protected]. Production keys are issued after the go-live review — see Go-Live Checklist.

Paths and versions

Partner endpoints live under /primary/v1 and /primary/v2. Both generations are live and operate on the same underlying records; v2 is the model to build against, and the guides note where a v1 endpoint still matters.

Paths are kebab-cased: /primary/v2/transaction-action, /primary/v1/pre-ipo-company-spv.

Pagination

List endpoints take page and pageSize:

ParameterDefaultBounds
page1Greater than 0
pageSize251 to 1000

Responses carry an items array and a pagination object:

{
  "items": [],
  "pagination": { "totalRecords": 65, "totalPages": 3, "currentPage": 1 }
}

Two exceptions are worth knowing:

Note: GET /primary/v1/watchlist takes pageNumber, not page.

GET /primary/v2/transaction-action/transaction/{transactionId} returns a bare array with no pagination envelope at all.

Enumerations

Enums serialise as strings, and they are case-sensitive. Send Subscription, not SUBSCRIPTION or subscription. Accreditation statuses are sent exactly as written, for example NET_WORTH_GT_1M.

Where an enum is extended, new values appear without a version bump. Treat an unrecognised value as unknown and render it rather than crashing on it.

Errors

Errors are RFC 7807 problem responses carrying an HTTP status and a human-readable message:

{
  "detail": "Investment amount is lower than the minimum commitment amount. Min amount - 25000",
  "status": 400
}

Important: The private markets API returns no machine-readable reason code. There is no reasonCode or statusReasonCode field to switch on — the HTTP status and the detail string are all you get.

This is why Errors & Reason Codes quotes the refusal messages verbatim: they are what your code has to recognise, and what your UI should show the investor.

Branch on the response body, not only on the HTTP status code.

Idempotency

POST requests accept an optional IdempotencyKey header. Send one on every order submission, and reuse the same key when retrying after a timeout — the cached response is returned instead of a second record being created.

Keys are cached for 24 hours. A retry outside that window is a fresh request, so fall back to a lookup by your own referenceId before resubmitting.

Your own identifiers

Several resources accept an identifier you supply. They are echoed back on reads and are the simplest bridge between Monark's records and your own ledger.

FieldSet onNotes
referenceIdTransactions, partiesMaximum 100 characters on a transaction, and filterable on GET /primary/v2/transaction
externalAccountNumberAccounts, and transactions created with an investorIdYour account number. Cannot be combined with accountId
investorReferenceIdInvestorsYour investor identifier

Fields that are not there

Some fields are marked admin-only and are removed from partner responses — absent from the JSON rather than returned as null. The ones most likely to catch you out are on a transaction: managementFee, feePerShare and carry. Read fee economics from the SPV instead.

This is worth knowing before you write a mapper that assumes every documented field arrives.

Webhooks

Status changes are delivered by webhook so your platform does not poll. Events can arrive out of order, so treat each as a signal and re-read the record with a GET before acting on it.

See Webhooks for registration and signature verification, and Webhooks for what to do with each private markets event.

Next steps


Did this page help you?