Docs
Partner API
For approved partners: make Chart Premium activation codes for your clients from your own systems (CRM, client area, onboarding), and see which ones were used. About the partner programme.
Authentication
Create a key on your partner page and send it in the Authorization header. Keys look like mdp_pk_3f9a1c07de_…; we keep only a fingerprint, so a lost key cannot be shown again: make a new one.
curl https://app.marketapi.app/partner/v1/account \
-H "Authorization: Bearer mdp_pk_YOUR_KEY"
Rotation without downtime: Rotate makes a new key and keeps the old one working for 24 hours. Put the new key in your systems, then the old one expires by itself (or revoke it at once). Never put a key in a web page or mobile app: call the API from your server.
Limits: 120 requests a minute per partner; too many failed keys from one address are blocked for 10 minutes. Errors are JSON: {"error": "…", "code": "invalid"} with HTTP 400, 401, 405 or 429.
Your seats
GET /partner/v1/account
{"partner_id": "MP-7KQ3TA", "name": "Example Broker", "status": "active",
"seats": [{"plan": "pro", "name": "Pro", "days": 30, "left": 48, "trial": false, "expires_at": null}]}
Each seat is one activation code for a plan and a length (30, 91, 182 or 365 days). Buy seat packs on your partner page (30% off the normal price, packs of 10, 50, 250).
Make codes
POST /partner/v1/codes with a JSON body:
| Field | Meaning |
|---|---|
plan | pro or proplus |
months | 1, 3, 6 or 12 (the seat length), or days |
count | how many codes (1–5000); may be left out when you give references |
customer_refs | optional: your own reference for each code (e.g. the client's account number), up to 120 characters each. We store it masked (45•••68) with a keyed fingerprint, so you can find a code by the full reference but we never keep it. |
expires_days | how long an unused code stays valid (default 365; trial seats end sooner). An unused code that expires gives its seat back. |
batch | optional name to recognise the batch |
Send an Idempotency-Key header (any unique text): if your request is retried, you get the same codes back instead of new ones (for 24 hours).
curl -X POST https://app.marketapi.app/partner/v1/codes \
-H "Authorization: Bearer mdp_pk_YOUR_KEY" -H "Content-Type: application/json" \
-H "Idempotency-Key: onboarding-45123468" \
-d '{"plan": "pro", "months": 1, "customer_refs": ["45123468"]}'
201 {"count": 1, "codes": [{"code": "K7QM-3XTP-9RWA-FD2H", "hint": "FD2H", "customer_ref": "45•••68",
"plan": "pro", "days": 30, "expires_at": "2027-10-17T08:00:00+00:00"}]}
The codes are in the answer only once. Give each client their code; they enter it on https://app.marketapi.app/premium (signed in) and the plan starts at once, or after the plan they already have.
Big batches: more than 100 codes are made by our task queue. The answer is 202 {"job": 812, "url": "/partner/v1/jobs/812"}; ask that URL until status is done; the codes are in that answer the first time only.
GET /partner/v1/jobs/812
{"status": "queued", "position": 2, "eta_s": 4.0} → {"status": "done", "count": 2000, "codes": [ … ]}
Find codes
GET /partner/v1/codes?customer_ref=45123468&status=unused&limit=100&offset=0 — status: unused, redeemed or cancelled.
{"codes": [{"id": 9134, "hint": "FD2H", "customer_ref": "45•••68", "plan": "pro", "days": 30, "status": "redeemed",
"created_at": "…", "expires_at": "…", "redeemed_at": "…"}]}
Cancel a code
POST /partner/v1/codes/9134/cancel — only unused codes; the seat is free again at once.
Security
- Every call is over HTTPS; keys are compared in constant time and only their keyed fingerprint is stored.
- We e-mail your contact address whenever a key is created or rotated.
- Codes are 16 characters from 32 symbols (80 bits), shown once, stored only as a fingerprint, and limited to 10 tries an hour per account when entered.