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-Keyin a sample somewhere, it was not a Monark header — some client-side proxies use it internally and convert. The API itself readsAuthorizationand 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.
| Environment | Base URL |
|---|---|
| Sandbox | https://sandbox-api.monark-markets.com |
| Production | Issued 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:
| Parameter | Default | Bounds |
|---|---|---|
page | 1 | Greater than 0 |
pageSize | 25 | 1 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/watchlisttakespageNumber, notpage.
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
reasonCodeorstatusReasonCodefield to switch on — the HTTP status and thedetailstring 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.
| Field | Set on | Notes |
|---|---|---|
referenceId | Transactions, parties | Maximum 100 characters on a transaction, and filterable on GET /primary/v2/transaction |
externalAccountNumber | Accounts, and transactions created with an investorId | Your account number. Cannot be combined with accountId |
investorReferenceId | Investors | Your 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
- Who can see what: Data Access Patterns
- How the entities relate: Relationships and Dependencies
- Start building: Private Markets: Onboarding
Updated about 17 hours ago