User-to-user gifting
Let one of your users gift gold or silver to someone else, verified by an OTP sent to the sender's own mobile.
Gifting is a user → user transfer: the assets leave one of your end users' holdings and land with whoever they choose. You orchestrate it, but the value is theirs, which is why every gift is OTP-verified. To move assets out of your own wallet instead, see Sending assets.
- Your server:
Check the sender qualifies
The sending user needs approved KYC and enough of the asset to cover the gift plus the 0.25% fee.
Otherwise the quote returns 403 KYC_REQUIRED or 400 INSUFFICIENT_BALANCE.
- Your server:
Quote the gift
One call prices the gift and dispatches the OTP. There is no separate send-OTP step.
POST/partner /users /:user_code /gift /quote - The user:
The sender confirms it is them
The code goes to the sender's own registered mobile. They enter it in your interface.
The value is theirs, which is why every gift is OTP-verified.
- Your server:
Confirm the gift
Send the gift_id and the OTP within the 10-minute window, with an Idempotency-Key.
POST/partner /users /:user_code /gift /confirm - OroPocket:
The receiver is credited
Assets leave the sender's holdings and land with the recipient — who is created by the gift if they had no account.
Before you start
Gifting needs the gift capability on your profile, and the sender has to clear two checks:
| Requirement | If it is not met |
|---|---|
| Approved KYC | The sending user must have completed and passed KYC, or the quote returns 403 KYC_REQUIRED. |
| Sufficient holdings | The sender must hold enough of the asset to cover the gift plus the 0.25% fee, or the quote returns 400 INSUFFICIENT_BALANCE. |
See KYC for how to get a user verified, and Errors for the full envelope.
1. Quote the gift
The quote prices the gift and triggers the OTP in one call — there is no separate "send OTP" step.
/partner/users/:user_code/gift/quotegift| Field | Type | Description | |
|---|---|---|---|
| receiver_mobile | string | required | Who receives the gift, 10 to 15 digits. Auto-created if they are new to OroPocket. |
| asset_type | string | required | Either "gold" or "silver". |
| amount_inr | number | optional | Rupee value to gift. Provide this OR amount_grams, not both. |
| amount_grams | number | optional | Exact grams to gift. Provide this OR amount_inr. |
| Field | Type | Description |
|---|---|---|
| gift_id | string | Pass this to the resend and confirm calls. Valid for 10 minutes. |
| sender_user_code | string | The user_code the gift is debited from, echoed back. |
| receiver | object | { mobile, name, exists, will_be_created } — will_be_created is true when we will open a new account at confirm. |
| breakdown | object | Costing for the gift — see the table below. |
| otp | object | { required, sent, channel, sent_to, resend_after_seconds } — sent_to is masked, resend_after_seconds is 45. |
Inside breakdown:
| Field | Type | Description |
|---|---|---|
| rate_per_gram | number | Locked rate for this gift. |
| price_basis | string | Which side of the spread priced the gift. |
| receiver_grams | number | Grams the receiver is credited. |
| sender_grams | number | Grams debited from the sender — receiver grams plus the fee. |
| fee_grams | number | Platform fee in grams. |
| fee_inr | number | The same fee in rupees. |
| fee_percentage | number | 0.25 — the fee is 0.25% of the gift. |
| amount_inr | number | Rupee value of the gift. |
1234 and no SMS is sent.curl -X POST https://api.oropocket.com/partner/users/usr_xxx/gift/quote \
-H "Authorization: Bearer oro_live_xxx" \
-H "Content-Type: application/json" \
-d '{"receiver_mobile":"9876543210","asset_type":"gold","amount_inr":500}'2. Resend the OTP (optional)
If the sender never got the code, resend it against the same quote. Wait out resend_after_seconds (45) before calling.
/partner/users/:user_code/gift/otp/resendgift| Field | Type | Description | |
|---|---|---|---|
| gift_id | string | required | The gift_id from the quote. The quote's own 10-minute clock is not extended. |
3. Confirm the gift
/partner/users/:user_code/gift/confirmgift| Field | Type | Description | |
|---|---|---|---|
| gift_id | string | required | The gift_id from the quote, confirmed within its 10-minute window. |
| otp | string | required | The code the sender received on their registered mobile. |
| Idempotency-Key | header | optional | Strongly recommended. Any string up to 100 characters — retrying with the same key replays the original response instead of gifting twice. |
| Field | Type | Description |
|---|---|---|
| transaction_id | string | Identifier for the resulting trade. |
| gift_id | string | The quote this settled, echoed back. |
| status | string | Outcome of the gift. |
| side | string | "gift" — how gifts are distinguished in the trades feed. |
| sender_user_code | string | The user the assets came from. |
| receiver | object | { mobile, is_new_user } — is_new_user is true when the account was created by this gift. |
| asset_type | string | "gold" or "silver". |
| amount_inr | number | Rupee value of the gift. |
| asset_quantity_grams | number | Grams credited to the receiver. |
| fee_inr | number | Fee charged, in rupees. |
| fee_grams | number | The same fee in grams. |
| sender_new_balance_grams | number | The sender's remaining balance for that asset. |
| created_at | string | ISO timestamp of the gift. |
401 INVALID_OTP. After 5 failed attempts the quote locks — request a fresh one with /gift/quote, which also issues a new OTP.curl -X POST https://api.oropocket.com/partner/users/usr_xxx/gift/confirm \
-H "Authorization: Bearer oro_live_xxx" \
-H "Idempotency-Key: 8f14e45f-cea1-4b2c-9d3a-1f2e3d4c5b6a" \
-H "Content-Type: application/json" \
-d '{"gift_id":"gft_xxx","otp":"1234"}'Finding gifts later
Gifts show up in GET /partner/trades alongside buys and sells, tagged with side: "gift". Subscribe to webhooks if you would rather be pushed the event than poll for it.