List invoices (status, clientId, kind)
GET /invoices Invoices and payments: read
Example
curl https://app.msmepulse.com/api/v1/invoices \
-H "Authorization: Bearer $MSMEPULSE_TOKEN"
Response 200
| Field | Type | Notes |
|---|---|---|
invoices | array of object | |
invoices[].id | string | |
invoices[].number | string or null | |
invoices[].status | "draft" | "issued" | "partially_paid" | "paid" | "cancelled" | |
invoices[].kind | "invoice" | "credit_note" | "debit_note" | |
invoices[].clientId | string | |
invoices[].clientName | string | |
invoices[].issueDate | string or null | YYYY-MM-DD |
invoices[].dueDate | string or null | YYYY-MM-DD |
invoices[].currency | string | |
invoices[].total | integer | Total, in minor units (paise or cents) |
invoices[].balance | integer | Still to pay, in minor units (paise or cents) |
invoices[].overdue | boolean | |
invoices[].sentAt | string or null | |
invoices[].sample | boolean | |
summary | object | |
summary.currency | string | |
summary.outstanding | integer | Owed to you, in minor units (paise or cents) |
summary.overdue | integer | Overdue, in minor units (paise or cents) |
summary.otherCurrencies | number | Open invoices in other currencies, not in the totals |
Create a draft invoice
POST /invoices Invoices and payments: read and write
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
clientId | string | Yes | at least 1 characters |
projectId | string or null | ||
issueDate | string | Yes | format ^\d{4}-\d{2}-\d{2}$ |
dueDate | string or null | format ^\d{4}-\d{2}-\d{2}$ | |
currency | "INR" | "SGD" | "USD" | "EUR" | "GBP" | "AED" | "AUD" | "MYR" | "CAD" | "CHF" | "HKD" | "NZD" | Yes | |
exchangeRate | number or null | ||
poNumber | string | up to 40 characters | |
notes | string | up to 2000 characters | |
exportUnderLut | boolean | default false | |
reverseCharge | boolean | default false | |
lines | array of object | Yes | at most 200 items |
lines[].description | string | Yes | 1–1000 characters |
lines[].quantity | number | Yes | 0.001 to 1000000 |
lines[].unit | string | up to 20 characters | |
lines[].unitPrice | integer | Yes | 0 to … |
lines[].discount | integer | 0 to … · default 0 | |
lines[].hsnSac | string | up to 8 characters | |
lines[].rateBps | integer | 0 to … · default 0 | |
lines[].treatment | "taxable" | "exempt" | "nil" | "non_gst" | default "taxable" | |
lines[].sgTaxCode | "SR" | "ZR" | "ES" | "OS" | default "SR" | |
lines[].catalogueItemId | string or null | ||
lines[].source | object | default {"kind":"manual","timeLogIds":[]} | |
lines[].source.kind | "time" | "milestone" | "item" | "manual" | "expense" | Yes | |
lines[].source.timeLogIds | array of string | ||
lines[].source.milestoneId | string or null | ||
lines[].source.expenseId | string or null |
Example
curl -X POST https://app.msmepulse.com/api/v1/invoices \
-H "Authorization: Bearer $MSMEPULSE_TOKEN" \
-H "Content-Type: application/json" \
-d '{"clientId":"65f0c2a1b4e8d9f0a1b2c3d4","issueDate":"2026-10-26","currency":"INR","lines":[{"description":"Rollout support","quantity":1,"unitPrice":100000}]}'
Response 201
| Field | Type | Notes |
|---|---|---|
id | string | The new record's id |
Unbilled approved time and completed milestones for a client
GET /invoices/billable Invoices and payments: read and write
Example
curl https://app.msmepulse.com/api/v1/invoices/billable \
-H "Authorization: Bearer $MSMEPULSE_TOKEN"
Answers 200 with the same data the MSMEPulse web app shows for it.
Work out an invoice's tax and totals without saving it
POST /invoices/preview Invoices and payments: read and write
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
clientId | string | Yes | at least 1 characters |
projectId | string or null | ||
issueDate | string | Yes | format ^\d{4}-\d{2}-\d{2}$ |
dueDate | string or null | format ^\d{4}-\d{2}-\d{2}$ | |
currency | "INR" | "SGD" | "USD" | "EUR" | "GBP" | "AED" | "AUD" | "MYR" | "CAD" | "CHF" | "HKD" | "NZD" | Yes | |
exchangeRate | number or null | ||
poNumber | string | up to 40 characters | |
notes | string | up to 2000 characters | |
exportUnderLut | boolean | default false | |
reverseCharge | boolean | default false | |
lines | array of object | Yes | at most 200 items |
lines[].description | string | Yes | 1–1000 characters |
lines[].quantity | number | Yes | 0.001 to 1000000 |
lines[].unit | string | up to 20 characters | |
lines[].unitPrice | integer | Yes | 0 to … |
lines[].discount | integer | 0 to … · default 0 | |
lines[].hsnSac | string | up to 8 characters | |
lines[].rateBps | integer | 0 to … · default 0 | |
lines[].treatment | "taxable" | "exempt" | "nil" | "non_gst" | default "taxable" | |
lines[].sgTaxCode | "SR" | "ZR" | "ES" | "OS" | default "SR" | |
lines[].catalogueItemId | string or null | ||
lines[].source | object | default {"kind":"manual","timeLogIds":[]} | |
lines[].source.kind | "time" | "milestone" | "item" | "manual" | "expense" | Yes | |
lines[].source.timeLogIds | array of string | ||
lines[].source.milestoneId | string or null | ||
lines[].source.expenseId | string or null |
Example
curl -X POST https://app.msmepulse.com/api/v1/invoices/preview \
-H "Authorization: Bearer $MSMEPULSE_TOKEN" \
-H "Content-Type: application/json" \
-d '{"clientId":"65f0c2a1b4e8d9f0a1b2c3d4","issueDate":"2026-10-26","currency":"INR","lines":[{"description":"Rollout support","quantity":1,"unitPrice":100000}]}'
Answers 200 with the same data the MSMEPulse web app shows for it.
Get an invoice, with its lines, tax and payments
GET /invoices/{id} Invoices and payments: read
id
Example
curl https://app.msmepulse.com/api/v1/invoices/{id} \
-H "Authorization: Bearer $MSMEPULSE_TOKEN"
Response 200
| Field | Type | Notes |
|---|---|---|
invoice | object | |
invoice.id | string | |
invoice.number | string or null | |
invoice.kind | string | |
invoice.status | string | |
invoice.clientId | string | |
invoice.clientName | string | |
invoice.projectId | string or null | |
invoice.issueDate | string or null | YYYY-MM-DD |
invoice.dueDate | string or null | YYYY-MM-DD |
invoice.currency | string | |
invoice.exchangeRate | number or null | |
invoice.lines | array of object | |
invoice.lines[].description | string | |
invoice.lines[].quantity | number | |
invoice.lines[].unitPrice | integer | Price, in minor units (paise or cents) |
invoice.lines[].hsnSac | string or null | |
invoice.lines[].rateBps | number or null | |
invoice.lines[].taxable | integer | Taxable value, in minor units (paise or cents) |
invoice.placeOfSupply | string or null | |
invoice.taxable | integer | Taxable value, in minor units (paise or cents) |
invoice.cgst | integer | CGST, in minor units (paise or cents) |
invoice.sgst | integer | SGST, in minor units (paise or cents) |
invoice.utgst | integer | UTGST, in minor units (paise or cents) |
invoice.igst | integer | IGST, in minor units (paise or cents) |
invoice.gst | integer | All GST, in minor units (paise or cents) |
invoice.total | integer | Total, in minor units (paise or cents) |
invoice.balance | integer | Still to pay, in minor units (paise or cents) |
invoice.overdue | boolean | |
invoice.daysOverdue | number | |
invoice.payments | array of object | |
invoice.payments[].id | string | |
invoice.payments[].date | string | YYYY-MM-DD |
invoice.payments[].amount | integer | Received, in minor units (paise or cents) |
invoice.payments[].tdsAmount | integer | TDS deducted by the client, in minor units (paise or cents) |
invoice.payments[].method | string | |
invoice.payments[].reference | string |
Replace a draft invoice
PUT /invoices/{id} Invoices and payments: read and write
id
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
clientId | string | Yes | at least 1 characters |
projectId | string or null | ||
issueDate | string | Yes | format ^\d{4}-\d{2}-\d{2}$ |
dueDate | string or null | format ^\d{4}-\d{2}-\d{2}$ | |
currency | "INR" | "SGD" | "USD" | "EUR" | "GBP" | "AED" | "AUD" | "MYR" | "CAD" | "CHF" | "HKD" | "NZD" | Yes | |
exchangeRate | number or null | ||
poNumber | string | up to 40 characters | |
notes | string | up to 2000 characters | |
exportUnderLut | boolean | default false | |
reverseCharge | boolean | default false | |
lines | array of object | Yes | at most 200 items |
lines[].description | string | Yes | 1–1000 characters |
lines[].quantity | number | Yes | 0.001 to 1000000 |
lines[].unit | string | up to 20 characters | |
lines[].unitPrice | integer | Yes | 0 to … |
lines[].discount | integer | 0 to … · default 0 | |
lines[].hsnSac | string | up to 8 characters | |
lines[].rateBps | integer | 0 to … · default 0 | |
lines[].treatment | "taxable" | "exempt" | "nil" | "non_gst" | default "taxable" | |
lines[].sgTaxCode | "SR" | "ZR" | "ES" | "OS" | default "SR" | |
lines[].catalogueItemId | string or null | ||
lines[].source | object | default {"kind":"manual","timeLogIds":[]} | |
lines[].source.kind | "time" | "milestone" | "item" | "manual" | "expense" | Yes | |
lines[].source.timeLogIds | array of string | ||
lines[].source.milestoneId | string or null | ||
lines[].source.expenseId | string or null |
Example
curl -X PUT https://app.msmepulse.com/api/v1/invoices/{id} \
-H "Authorization: Bearer $MSMEPULSE_TOKEN" \
-H "Content-Type: application/json" \
-d '{"clientId":"65f0c2a1b4e8d9f0a1b2c3d4","issueDate":"2026-10-26","currency":"INR","lines":[{"description":"Rollout support","quantity":1,"unitPrice":100000}]}'
Answers 200 with the same data the MSMEPulse web app shows for it.
Delete a draft invoice
DELETE /invoices/{id} Invoices and payments: read and write
id
Example
curl -X DELETE https://app.msmepulse.com/api/v1/invoices/{id} \
-H "Authorization: Bearer $MSMEPULSE_TOKEN"
Answers 200 with the same data the MSMEPulse web app shows for it.
Issue a draft invoice (gives it its number)
POST /invoices/{id}/issue Invoices and payments: read and write
id
Example
curl -X POST https://app.msmepulse.com/api/v1/invoices/{id}/issue \
-H "Authorization: Bearer $MSMEPULSE_TOKEN"
Answers 200 with the same data the MSMEPulse web app shows for it.
Email an invoice to the client
POST /invoices/{id}/send Invoices and payments: read and write
id
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
to | string | Yes | an email address |
message | string | up to 2000 characters |
Example
curl -X POST https://app.msmepulse.com/api/v1/invoices/{id}/send \
-H "Authorization: Bearer $MSMEPULSE_TOKEN" \
-H "Content-Type: application/json" \
-d '{"to":"someone@example.com"}'
Answers 200 with the same data the MSMEPulse web app shows for it.
Create an online payment link
POST /invoices/{id}/pay-link Invoices and payments: read and write
id
Example
curl -X POST https://app.msmepulse.com/api/v1/invoices/{id}/pay-link \
-H "Authorization: Bearer $MSMEPULSE_TOKEN"
Answers 200 with the same data the MSMEPulse web app shows for it.
Record a payment (with TDS in India)
POST /invoices/{id}/payments Invoices and payments: read and write
id
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
date | string | Yes | format ^\d{4}-\d{2}-\d{2}$ |
amount | integer | Yes | 0 to … |
method | "bank_transfer" | "upi" | "paynow" | "cheque" | "cash" | "card" | "other" | Yes | |
reference | string | up to 80 characters | |
tdsAmount | integer | 0 to … · default 0 | |
tdsSection | string | up to 20 characters | |
note | string | up to 500 characters |
Example
curl -X POST https://app.msmepulse.com/api/v1/invoices/{id}/payments \
-H "Authorization: Bearer $MSMEPULSE_TOKEN" \
-H "Content-Type: application/json" \
-d '{"date":"2026-10-26","amount":100000,"method":"bank_transfer"}'
Response 200
| Field | Type | Notes |
|---|---|---|
status | string | |
balance | integer | Still to pay, in minor units (paise or cents) |
Remove a recorded payment
DELETE /invoices/{id}/payments/{pid} Invoices and payments: read and write
id · pid
Example
curl -X DELETE https://app.msmepulse.com/api/v1/invoices/{id}/payments/{pid} \
-H "Authorization: Bearer $MSMEPULSE_TOKEN"
Answers 200 with the same data the MSMEPulse web app shows for it.
Record the client's TDS certificate for a payment
PATCH /invoices/{id}/payments/{pid}/tds-certificate Invoices and payments: read and write
id · pid
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
received | boolean | Yes |
Example
curl -X PATCH https://app.msmepulse.com/api/v1/invoices/{id}/payments/{pid}/tds-certificate \
-H "Authorization: Bearer $MSMEPULSE_TOKEN" \
-H "Content-Type: application/json" \
-d '{"received":false}'
Answers 200 with the same data the MSMEPulse web app shows for it.
Cancel an issued invoice
POST /invoices/{id}/cancel Invoices and payments: read and write
id
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
reason | string | Yes | 3–500 characters |
Example
curl -X POST https://app.msmepulse.com/api/v1/invoices/{id}/cancel \
-H "Authorization: Bearer $MSMEPULSE_TOKEN" \
-H "Content-Type: application/json" \
-d '{"reason":"Duplicate charge"}'
Answers 200 with the same data the MSMEPulse web app shows for it.
Raise a credit note against an invoice
POST /invoices/{id}/credit-notes Invoices and payments: read and write
id
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
issueDate | string | Yes | format ^\d{4}-\d{2}-\d{2}$ |
reason | "discount" | "deficiency" | "overcharge" | "return" | "other" | Yes | |
reasonNote | string | up to 500 characters | |
lines | array of object | Yes | |
lines[].index | integer | Yes | 0 to … |
lines[].amount | integer | Yes | 0 to … |
Example
curl -X POST https://app.msmepulse.com/api/v1/invoices/{id}/credit-notes \
-H "Authorization: Bearer $MSMEPULSE_TOKEN" \
-H "Content-Type: application/json" \
-d '{"issueDate":"2026-10-26","reason":"discount","lines":[{"index":1,"amount":100000}]}'
Answers 200 with the same data the MSMEPulse web app shows for it.
Raise a debit note against an invoice
POST /invoices/{id}/debit-notes Invoices and payments: read and write
id
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
issueDate | string | Yes | format ^\d{4}-\d{2}-\d{2}$ |
dueDate | string or null | format ^\d{4}-\d{2}-\d{2}$ | |
reason | "undercharge" | "additional" | "tax_shortfall" | "other" | Yes | |
reasonNote | string | up to 500 characters | |
lines | array of object | Yes | at most 50 items |
lines[].description | string | Yes | 1–1000 characters |
lines[].quantity | number | Yes | 0.001 to 1000000 |
lines[].unit | string | up to 20 characters | |
lines[].unitPrice | integer | Yes | 0 to … |
lines[].discount | integer | 0 to … · default 0 | |
lines[].hsnSac | string | up to 8 characters | |
lines[].rateBps | integer | 0 to … · default 0 | |
lines[].treatment | "taxable" | "exempt" | "nil" | "non_gst" | default "taxable" | |
lines[].sgTaxCode | "SR" | "ZR" | "ES" | "OS" | default "SR" |
Example
curl -X POST https://app.msmepulse.com/api/v1/invoices/{id}/debit-notes \
-H "Authorization: Bearer $MSMEPULSE_TOKEN" \
-H "Content-Type: application/json" \
-d '{"issueDate":"2026-10-26","reason":"undercharge","lines":[{"description":"Rollout support","quantity":1,"unitPrice":100000}]}'
Answers 200 with the same data the MSMEPulse web app shows for it.
Record a refund
POST /invoices/{id}/refunds Invoices and payments: read and write
id
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
date | string | Yes | format ^\d{4}-\d{2}-\d{2}$ |
amount | integer | Yes | 1 to … |
method | "bank_transfer" | "upi" | "paynow" | "cheque" | "cash" | "card" | "other" | Yes | |
reference | string | up to 80 characters |
Example
curl -X POST https://app.msmepulse.com/api/v1/invoices/{id}/refunds \
-H "Authorization: Bearer $MSMEPULSE_TOKEN" \
-H "Content-Type: application/json" \
-d '{"date":"2026-10-26","amount":100000,"method":"bank_transfer"}'
Answers 200 with the same data the MSMEPulse web app shows for it.