Guide

Physical delivery

Ship real gold and silver coins to an end user's address — minted, insured and tracked to the door.

Delivery turns holdings into metal in someone's hand, so it needs the delivery capability — enable it on the Use cases page. It is a detailed-API flow only; the hosted embed does not expose it.

Because the goods are irreversible once shipped, two guardrails sit in front of every order:

GuardrailWhat it means
Approved KYCThe end user must have completed and passed KYC before a quote will price. Otherwise the quote returns 403 KYC_REQUIRED.
OTP to the userThe last step is an OTP sent to the user's own registered mobile — not to you. No code, no order.

Who pays for what

Pick a payment mode per order.

payment_modeHow it bills
redeemThe user's own gold/silver holdings are debited for the coin's metal weight. INR charges (minting + insured delivery + GST) are billed to YOUR partner wallet.
buyNo user holdings touched — the full cost (metal + minting + delivery + GST) is billed to YOUR partner wallet at the live rate.
Rupee charges are always billed to your partner wallet — we never charge the end user directly. Keep the float topped up: a confirm that hits 402 INSUFFICIENT_PARTNER_FUNDS rolls the whole order back.

1. Browse the catalog

GET/partner/delivery/productsdelivery
GET/partner/delivery/products/:skudelivery
FieldTypeDescription
skustringStable identifier for the coin. Pass it to the quote.
namestringDisplay name, e.g. a 1g 24K gold coin.
metalTypestringgold or silver.
puritystringFineness of the minted coin.
productWeightnumberPhysical weight of the coin in grams.
redeemWeightnumberGrams debited from the user's holdings in redeem mode.
pricePerUnitInrnumberIndicative all-in price per coin, ex-GST — metal at the live rate plus minting and insured delivery. For display only.
gstPctnumberGST added at checkout, so you can label the indicative price honestly.
imagesarrayProduct imagery you can render in your own UI.
inStockbooleanWhether the mint can currently fulfil this SKU.
Catalog pricing is indicative — it moves with the metal rate. The binding number is the total on the quote you are about to create.
curl https://api.oropocket.com/partner/delivery/products \
  -H "Authorization: Bearer oro_live_xxx"

2. Quote the order

The quote prices the coins, freezes the shipping address and sends the OTP to the user in one call.

POST/partner/users/:user_code/delivery/quotedelivery
FieldTypeDescription
skustringrequiredThe coin to ship, from the catalog.
quantityintegerrequiredHow many coins, 1 to 999.
payment_modestringrequiredEither "redeem" or "buy" — see the billing table above.
addressobjectrequiredWhere to ship. Fields are listed below.

Inside address:

FieldTypeDescription
namestringrequiredRecipient name, 2 to 50 letters.
mobileNumberstringrequired10-digit contact number for the courier.
addressLinestringrequiredFull street address, 10 to 100 characters.
pincodestringrequired6-digit Indian PIN code.
emailstringoptionalOptional — used for delivery notifications.
FieldTypeDescription
partner_quote_idstringPass this to the resend and confirm calls. Lives about 5 minutes.
productobject{ sku, name, metal_type, quantity } — what is being shipped.
payment_modestring"redeem" or "buy", echoed back.
breakdownobject{ line_items, total_payable_inr } — itemised metal, minting, delivery and GST.
billingobject{ source: "partner_wallet", charge_inr } — what will be debited from you.
shipping_addressobjectThe address as we stored it. Check it before confirming; it is frozen into the order.
otpobject{ required, sent, channel, sent_to, resend_after_seconds } — sent_to is masked, resend_after_seconds is 45.
expires_atstringISO timestamp. Confirm before this or request a new quote.

Quotes fail with 403 KYC_REQUIRED if the user is not verified, and — in redeem mode — 402 INSUFFICIENT_USER_BALANCE if they do not hold enough metal to cover the coin.

curl -X POST https://api.oropocket.com/partner/users/usr_xxx/delivery/quote \
  -H "Authorization: Bearer oro_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "sku": "GOLD_COIN_1G",
    "quantity": 1,
    "payment_mode": "redeem",
    "address": {
      "name": "Anya Sharma",
      "mobileNumber": "9876543210",
      "addressLine": "12 Turner Road, Bandra West, Mumbai",
      "pincode": "400050"
    }
  }'

3. Resend the OTP (optional)

POST/partner/users/:user_code/delivery/otp/resenddelivery
FieldTypeDescription
partner_quote_idstringrequiredThe quote to reissue a code for. Wait out resend_after_seconds (45) first.

4. Confirm and ship

Confirm verifies the OTP, bills your wallet and places the order with the mint — atomically. Either all three happen or none do.

POST/partner/users/:user_code/delivery/confirmdelivery
FieldTypeDescription
partner_quote_idstringrequiredThe quote to execute, confirmed before it expires.
otpstringrequiredThe code the end user received on their registered mobile.
Idempotency-KeyheaderoptionalStrongly recommended. Any string up to 100 characters — retrying with the same key replays the original response instead of shipping twice.
A wrong code returns 401 INVALID_OTP; after 5 attempts the quote locks and you need a new one. But if billing fails — 402 INSUFFICIENT_PARTNER_FUNDS or 403 WALLET_NOT_CONFIGURED — everything rolls back and the quote reopens, so you can top up and retry with the same OTP.
curl -X POST https://api.oropocket.com/partner/users/usr_xxx/delivery/confirm \
  -H "Authorization: Bearer oro_live_xxx" \
  -H "Idempotency-Key: 8f14e45f-cea1-4b2c-9d3a-1f2e3d4c5b6a" \
  -H "Content-Type: application/json" \
  -d '{"partner_quote_id":"pdq_xxx","otp":"1234"}'

5. Track the order

GET/partner/users/:user_code/delivery/ordersdelivery
GET/partner/users/:user_code/delivery/orders/:order_iddelivery
StatusMeaning
pendingOrder accepted and paid for, waiting to be picked up by the mint.
processingThe coin is being minted and packed.
dispatched_but_not_deliveredHanded to the courier. Tracking details are now available.
delivered_to_clientSigned for by the recipient. Terminal state.

Tracking fields — awbNo and logisticName — appear once the parcel is dispatched. Status is refreshed from the fulfilment partner every time you read an order, so a poll always returns fresh state.

Testing in sandbox

In sandbox the OTP is always 1234 and no SMS goes out. Orders are simulated end to end — nothing is written to your wallet and nothing reaches the fulfilment partner — so you can exercise the full quote, confirm and tracking loop for free.