Skip to main content
A purchase order buys units of a mutual fund scheme for an investor. This guide covers LUMPSUM_PURCHASE. Placing an order is a two-part flow:
1

Create the order

POST /api/orders/v1/ — validated and persisted synchronously, then dispatched to the exchange in the background. Returns 202.
2

Pay for it

POST /api/payments/v1/ — reference one or more orders and a payment mode.

Prerequisites

  • The investor is status: ACTIVE — registered and client-authorised (see Create an investor).
  • An investment account exists for the investor.
  • For mandate-funded payments, a REGISTERED mandate exists.
  • The target scheme_code allows the transaction type you’re placing — look it up via schemes and check purchase_allowed/redemption_allowed/switch_allowed first.

Supported order types

Create the order

Response 202:
The 202 is returned the moment the order is validated and persisted; the exchange dispatch runs in the background and a status-sync job later fills in allotment details.

Fields

Validation

Rejected synchronously before the 202:
Send an Idempotency-Key (UUID) on order creation. Replaying the same key + body returns the original response with Idempotency-Replayed: true; a different body with the same key is 409 IDEMPOTENCY_KEY_REUSED.

Order lifecycle

Track progress

Poll GET /api/orders/v1/:id:
status tracks the order at the exchange; payment_status tracks the money for it separately, and is also returned by the list endpoint (which accepts it as a filter): GET /api/orders/v1/:id/events returns the full transition trail ({ from, to, at, remark }). Or listen for webhook events order.accepted, order.rejected, order.failed, order.allotted.

Cancel an order

Allowed only from PENDING, SUBMITTED or ACCEPTED — otherwise 409 INVALID_STATE.

Pay for the order

Response 201:

Payment fields

How each mode settles

Allotment and redemption-payout timing (T+n) is set by the scheme and its RTA, not by Atlas. The one date rule Atlas enforces is cheque dates: they must fall within T−90 … T+3 calendar days.

Payment status

INITIATED → CAPTURED (success) / FAILED / REFUNDED. Completion arrives asynchronously via an exchange callback, which emits webhook events payment.captured, payment.failed, payment.refunded. Each linked order’s payment_status is updated in step. Once settled, GET /api/payments/v1/:id also returns provider_ref (the exchange’s own settlement reference), payment_account_no, payment_datetime and settlement_number — a reconciliation pass fills these in even for a payment made through the exchange’s own hosted flow without ever calling POST /api/payments/v1 yourself.

Submit a UTR

Read endpoints

Redemption and switch (brief)

Both use the same POST /api/orders/v1/ endpoint:
  • Redemption — order_type: "REDEMPTION", plus units or all_units: true (demat), or folio_no for physical holdings. No payment step — proceeds are credited to the registered bank account.
  • Switch — order_type: "SWITCH" with switch: { "to_scheme_code": "..." }.
Both follow the same PENDING → SUBMITTED → ACCEPTED → ALLOTTED lifecycle and emit the same order.allotted / order.rejected webhooks. ALLOTTED means “processed” for every order type:
  • Redemption — units, nav and allotment_date are the units actually redeemed and the NAV they were redeemed at.
  • Switch — the exchange books a switch-out and a switch-in. The order becomes ALLOTTED once the switch-in is allotted, and units/nav/ folio_no then describe the new holding in the target scheme. If either side is rejected, the order is REJECTED.
Instead of placing an order directly, you can propose one and have the investor confirm and pay for it themselves — the same self-serve pattern as the public onboarding link for investors, generalized to orders.
1

Propose the order

POST /api/orders/v1/public-link with the same body POST /api/orders/v1/ takes, wrapped as { "proposal": { ... }, "secret_code": "1234" } (secret_code is an optional PIN). No order is created yet — only the proposal is stored. Response 201:
Share https://<your-ui>/order-confirm?linkId=8f3e2b1a-... with the investor (and the PIN, out of band, if you set one).
2

Investor reviews and confirms

GET /api/public/v1/order-links/:link_id (header X-Draft-Secret: 1234 if a PIN was set) returns the proposal pre-confirm, or the live order once confirmed:
scheme is proposal.scheme_code resolved against the scheme master — the fund being bought, redeemed or (for a SWITCH) switched out of — and to_scheme is the SWITCH target (proposal.switch.to_scheme_code), so your confirmation page can show fund names rather than bare codes. Both are best-effort and omitted when the code isn’t in the master. A REDEMPTION or SWITCH link collects no payment from the investor — word your page accordingly (the payment_link it later surfaces is an exchange authorization page, not a payment page).401 means the PIN is required or wrong; 410 GONE means the link has expired (order/mandate links expire after 7 days — unlike the investor onboarding link, which never expires).POST /api/public/v1/order-links/:link_id/confirm then runs the exact same validated create-and-dispatch flow as the authenticated POST /api/orders/v1/ and returns the same OrderData shape. A second confirm on the same link is 409 ALREADY_CONFIRMED.
3

Investor pays once accepted

Poll the same GET .../order-links/:link_id — once the exchange has accepted the order, the response adds "order": { ...OrderFullData } and "payment_ready": true. order.payment_link, once populated, is an additional NSE-hosted payment page (the same link NSE already auto-emails/SMSes the investor after order registration) — an alternative you can redirect the investor to directly, without ever calling our own /pay endpoint. It’s best-effort and may take a moment to populate after payment_ready first turns true; whether completing payment there alone also produces a settlement observable through this API is not yet confirmed, so keep polling regardless of which path the investor takes.Alternatively, for programmatic control over payment mode, the investor (or your own backend) can pick a mode and call POST /api/public/v1/order-links/:link_id/pay with the same body shape POST /api/payments/v1/ takes (minus investor_id/order_ids, which are derived from the link, never accepted from the public caller):
Response is the normal PaymentData — for UPI/NETBANKING, redirect the investor to payment_url to complete settlement. This remains the only path this backend can confirm creates a Payment record.