Skip to main content

Payment Requests

Track the payment links your agents send to customers through your own Razorpay account, and cap how much an agent may request.

Overview

A payment request is one payment link an agent sent to one of your customers during a call or chat: an EMI instalment, an order payment, an invoice. The link is created with your own Razorpay account, so the money is paid into your account. It is never CallMissed credits and never passes through CallMissed.

Agents create payment requests with the create_payment_link tool once Razorpay is connected. On a WhatsApp chat the link is sent in the chat; elsewhere (for example on a phone call) Razorpay texts it to the customer's phone and emails it when an email is known. This API is read-only for the requests themselves: you list them, read one, and set the per-link limit.

Status changes arrive from Razorpay and are applied to the request, then delivered to you as payment_request.* webhook events.

Authentication

Authorization: Bearer cm_your_api_key
OperationScope
List, get, read settingsintegrations:read
Update settingsintegrations:write

Setup: connect Razorpay

  1. In Razorpay Dashboard → Account & Settings → API Keys, create a key. Choose a webhook secret (at least 8 characters) and keep it for step 3.
  2. Connect it with POST /api/v1/integrations:
curl -X POST https://api.callmissed.com/api/v1/integrations \
  -H "Authorization: Bearer cm_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "provider": "razorpay",
    "name": "Collections",
    "credentials": {
      "key_id": "rzp_live_XXXXXXXXXXXXXX",
      "key_secret": "your_key_secret",
      "webhook_secret": "the_secret_you_chose"
    }
  }'

The key is checked with Razorpay before it is saved. A rzp_test_… key connects in test mode. 3. Call GET /api/v1/payment-requests/settings. In Razorpay Dashboard → Webhooks, add a webhook whose URL is the returned webhook_url, whose secret is the one from step 1, and whose events are the returned webhook_events. Without this webhook, requests stay at created and no payment_request.* events are sent.

If more than one Razorpay integration is connected, the oldest one is used.

Statuses

statusMeaning
creatingSaved, link being created with Razorpay
createdLink created and sent; nothing paid yet
partially_paidPart of the amount paid (amount_paid_minor is less than amount_minor)
paidPaid in full. paid_at is set
expiredThe link expired unpaid
cancelledThe link was cancelled
failedRazorpay refused the link, or the result could not be confirmed. See error

Statuses only move forward: a late or repeated event from Razorpay never moves a request back. paid, expired and cancelled are final. A failed request can still become partially_paid or paid if Razorpay reports a payment on its link.

The payment request object

{
  "id": "5c7d…",
  "provider": "razorpay",
  "status": "paid",
  "amount_minor": 149900,
  "amount_paid_minor": 149900,
  "currency": "INR",
  "description": "EMI 3 of 12",
  "external_reference": "LOAN-2291-03",
  "short_url": "https://rzp.io/i/AbC123",
  "customer_name": "Priya Sharma",
  "customer_phone": "+919812345678",
  "customer_email": null,
  "contact_id": "4411…",
  "bot_id": "c3d4…",
  "channel": "voice",
  "conversation_id": null,
  "voice_session_id": "8e9f…",
  "delivered_via": "sms",
  "error": null,
  "paid_at": "2026-09-26T10:42:00Z",
  "created_at": "2026-09-26T10:31:00Z",
  "updated_at": "2026-09-26T10:42:00Z"
}
FieldTypeNotes
providerstringrazorpay
amount_minorintegerRequested amount in the smallest currency unit (paise): 149900 = ₹1,499.00
amount_paid_minorintegerPaid so far, in paise
currencystringINR
descriptionstringWhat the payment is for, as shown to the customer
external_referencestring | nullYour own reference (invoice, EMI or order number), if the agent was given one
short_urlstring | nullThe payment link. null until the link is created
customer_name / customer_phone / customer_emailstring | nullWho the link was sent to. Phone in E.164
contact_idUUID | nullThe CRM contact, when known. Status changes are also added as a note on this contact
bot_idUUID | nullThe agent that created the request
channelstring | nullWhere the agent was, e.g. voice or whatsapp
conversation_id / voice_session_idUUID | nullThe chat or call it came from
delivered_viastring | nullComma-separated channels the link was sent through: whatsapp, sms, email
errorstring | nullWhy the request failed, safe to show
paid_atdatetime | nullWhen it became paid

GET /api/v1/payment-requests

Returns an array of payment request objects, newest first.

ParameterTypeRequiredConstraints
statusstringNoOne of the seven statuses
contact_idUUIDNoOne contact's requests
limitintegerNo1 <= limit <= 200, default 50
offsetintegerNo0 <= offset <= 100000, default 0
curl "https://api.callmissed.com/api/v1/payment-requests?status=paid&limit=50" \
  -H "Authorization: Bearer cm_your_api_key"

An unknown status returns 422 status must be one of: creating, created, partially_paid, paid, expired, cancelled, failed.

GET /api/v1/payment-requests/{request_id}

One payment request. 404 Payment request not found.

curl https://api.callmissed.com/api/v1/payment-requests/{request_id} \
  -H "Authorization: Bearer cm_your_api_key"

GET /api/v1/payment-requests/settings

The connected Razorpay account, the per-link limit and the webhook to configure in Razorpay.

curl https://api.callmissed.com/api/v1/payment-requests/settings \
  -H "Authorization: Bearer cm_your_api_key"
{
  "connected": true,
  "integration_id": "6a1e…",
  "account": "rzp_live_XXXXXXXXXXXXXX",
  "mode": "live",
  "max_amount_inr": 10000,
  "platform_max_amount_inr": 500000,
  "webhook_url": "https://api.callmissed.com/api/v1/webhooks/razorpay/6a1e…",
  "webhook_events": [
    "payment_link.cancelled",
    "payment_link.expired",
    "payment_link.paid",
    "payment_link.partially_paid"
  ]
}
FieldTypeNotes
connectedbooleanfalse when no Razorpay integration is connected. integration_id, account, mode and webhook_url are then null
accountstring | nullThe connected Razorpay key id
modestring | nulllive for a rzp_live_… key, otherwise test
max_amount_inrintegerThe largest amount, in whole rupees, an agent may request in one link. Default 10000
platform_max_amount_inrintegerThe highest value max_amount_inr can be set to: 500000
webhook_urlstring | nullPaste this exactly as returned into Razorpay's webhook settings
webhook_eventsstring[]The Razorpay events to enable on that webhook

PUT /api/v1/payment-requests/settings

Sets the largest amount an agent may request in one payment link. Larger collections are left to a person.

FieldTypeRequiredConstraints
max_amount_inrintegerYesWhole rupees, 1 <= max_amount_inr <= 500000
curl -X PUT https://api.callmissed.com/api/v1/payment-requests/settings \
  -H "Authorization: Bearer cm_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{ "max_amount_inr": 25000 }'

Returns the settings object. 404 Connect Razorpay first when no Razorpay integration is connected; 422 when the value is out of range.

Webhook events

Subscribe a webhook to these events to hear about payments as they happen:

EventWhen
payment_request.partially_paidA part payment was made
payment_request.paidPaid in full
payment_request.expiredThe link expired
payment_request.cancelledThe link was cancelled

The event's data object:

{
  "payment_request_id": "5c7d…",
  "status": "paid",
  "provider": "razorpay",
  "amount": 1499.0,
  "amount_paid": 1499.0,
  "currency": "INR",
  "description": "EMI 3 of 12",
  "reference": "LOAN-2291-03",
  "short_url": "https://rzp.io/i/AbC123",
  "contact_id": "4411…",
  "customer_phone": "+919812345678",
  "customer_email": null,
  "bot_id": "c3d4…",
  "paid_at": "2026-09-26T10:42:00.481203+00:00"
}

Note the units: in event payloads amount and amount_paid are in rupees, while the API's amount_minor and amount_paid_minor are in paise. reference is the API's external_reference.

Errors

StatusWhen
403Key is missing integrations:read / integrations:write
404Payment request not in your account, or settings updated before Razorpay is connected
422Unknown status filter, or max_amount_inr outside 1–500000

Nothing on this page consumes credits.