Invoices & Estimates
Invoices bill a contact for payment; estimates quote work that a contact can accept and turn into an invoice. Both live in your SMBcrm account and are managed through the same API. Templates store reusable invoice and estimate content, and recurring schedules send an invoice on a repeating basis.
Base URL: https://services.smbcrm.com · Version header: v3 ·
Scopes: invoices.readonly, invoices.write, invoices/estimate.readonly, invoices/estimate.write, invoices/template.readonly, invoices/template.write, invoices/schedule.readonly, invoices/schedule.write. See Scopes.
Invoices
Section titled “Invoices”altId, altType, limit, and offset are required. Filter with status, contactId, search (invoice ID, name, email, or phone), paymentMode (default, live, or test), and startAt/endAt (YYYY-MM-DD). Sort with sortField=issueDate and sortOrder=ascend or descend.
curl "https://services.smbcrm.com/invoices/?altId=<location_id>&altType=location&limit=20&offset=0" \ -H "Authorization: Bearer <token>" \ -H "Version: v3"{ "invoices": [ { "_id": "<invoice_id>", "status": "sent", "name": "July retainer", "invoiceNumber": 1042, "currency": "USD", "total": 500, "amountDue": 500, "contactDetails": { "id": "<contact_id>", "name": "Jordan Lee", "email": "jordan@example.com" }, "issueDate": "2026-07-08", "dueDate": "2026-07-22" } ], "total": 1}Invoice status is one of draft, sent, payment_processing, paid, void, or partially_paid.
The invoice returns its line items in invoiceItems.
curl "https://services.smbcrm.com/invoices/<invoice_id>?altId=<location_id>&altType=location" \ -H "Authorization: Bearer <token>" \ -H "Version: v3"Required fields: altId, altType, name, businessDetails, currency, items, discount, contactDetails (id, name, phoneNo, and email), issueDate, sentTo.email, and liveMode. Each entry in items needs name, currency, amount, and qty. discount.type is percentage or fixed.
Optional fields include dueDate, title, termsNotes, invoiceNumber, invoiceNumberPrefix, automaticTaxesEnabled, lateFeesConfiguration, tipsConfiguration, paymentSchedule, paymentMethods, attachments, and miscellaneousCharges.
curl -X POST https://services.smbcrm.com/invoices/ \ -H "Authorization: Bearer <token>" \ -H "Version: v3" \ -H "Content-Type: application/json" \ -d '{ "altId": "<location_id>", "altType": "location", "name": "July retainer", "currency": "USD", "businessDetails": { "name": "<business_name>" }, "contactDetails": { "id": "<contact_id>", "name": "Jordan Lee", "phoneNo": "+15125550142", "email": "jordan@example.com" }, "items": [ { "name": "Consulting", "currency": "USD", "amount": 500, "qty": 1 } ], "discount": { "value": 0, "type": "percentage" }, "issueDate": "2026-07-08", "dueDate": "2026-07-22", "sentTo": { "email": ["jordan@example.com"] }, "liveMode": true }'Required fields: altId, altType, name, currency, invoiceItems, issueDate, and dueDate. Each entry in invoiceItems needs name, currency, amount, and qty. This endpoint takes line items as invoiceItems, not items.
Optional fields include title, description, businessDetails, invoiceNumber, contactId, contactDetails, termsNotes, discount, automaticTaxesEnabled, liveMode, paymentSchedule, tipsConfiguration, invoiceNumberPrefix, paymentMethods, attachments, and miscellaneousCharges. The response is the updated invoice.
curl -X PUT https://services.smbcrm.com/invoices/<invoice_id> \ -H "Authorization: Bearer <token>" \ -H "Version: v3" \ -H "Content-Type: application/json" \ -d '{ "altId": "<location_id>", "altType": "location", "name": "July retainer", "currency": "USD", "invoiceItems": [ { "name": "Consulting", "currency": "USD", "amount": 600, "qty": 1 } ], "issueDate": "2026-07-08", "dueDate": "2026-07-29" }'altId and altType go in the query string. The response is the deleted invoice.
curl -X DELETE "https://services.smbcrm.com/invoices/<invoice_id>?altId=<location_id>&altType=location" \ -H "Authorization: Bearer <token>" \ -H "Version: v3"Send altId and altType in the body. The response is the updated invoice.
curl -X POST https://services.smbcrm.com/invoices/<invoice_id>/void \ -H "Authorization: Bearer <token>" \ -H "Version: v3" \ -H "Content-Type: application/json" \ -d '{ "altId": "<location_id>", "altType": "location" }'Required fields: altId, altType, mode, card (brand and last4), cheque (number), and notes. mode is cash, card, cheque, bank_transfer, or other. Optional fields are amount (the amount to apply to the invoice), paymentScheduleIds (the payment schedule entries to record against), fulfilledAt, and meta.
curl -X POST https://services.smbcrm.com/invoices/<invoice_id>/record-payment \ -H "Authorization: Bearer <token>" \ -H "Version: v3" \ -H "Content-Type: application/json" \ -d '{ "altId": "<location_id>", "altType": "location", "mode": "cheque", "card": { "brand": "visa", "last4": "4242" }, "cheque": { "number": "1001" }, "notes": "Paid by check", "amount": 500 }'The response has the shape { "success": true, "invoice": { ... } }.
action selects how the invoice is delivered: email, sms, sms_and_email, or send_manually. userId must be the ID of a user with access to your account. The optional sentFrom object (fromName and fromEmail) sets the sender name and email on the notification and doesn’t apply to send_manually. The optional autoPayment object (enable is required inside it) turns on automatic payment for the invoice.
curl -X POST https://services.smbcrm.com/invoices/<invoice_id>/send \ -H "Authorization: Bearer <token>" \ -H "Version: v3" \ -H "Content-Type: application/json" \ -d '{ "altId": "<location_id>", "altType": "location", "userId": "<user_id>", "action": "email", "liveMode": true }'The response contains invoice, smsData, and emailData.
Required fields: altId, altType, name, currency, items, contactDetails (id, name, phoneNo, and email), issueDate, sentTo.email, liveMode, action, and userId. action is draft to save the invoice without sending it, or send to send it. Pass id to update an existing invoice; leave it out to create a new one.
curl -X POST https://services.smbcrm.com/invoices/text2pay \ -H "Authorization: Bearer <token>" \ -H "Version: v3" \ -H "Content-Type: application/json" \ -d '{ "altId": "<location_id>", "altType": "location", "name": "Service call", "currency": "USD", "items": [ { "name": "On-site repair", "currency": "USD", "amount": 180, "qty": 1 } ], "contactDetails": { "id": "<contact_id>", "name": "Jordan Lee", "phoneNo": "+15125550142", "email": "jordan@example.com" }, "issueDate": "2026-07-08", "sentTo": { "email": ["jordan@example.com"], "phoneNo": ["+15125550142"] }, "liveMode": true, "action": "send", "userId": "<user_id>" }'The response contains invoice and invoiceUrl.
Send altId, altType, and lateFeesConfiguration. Inside it, enable, value, type (fixed or percentage), and frequency are required. frequency takes intervalCount and interval (minute, hour, day, week, month, or one_time). The optional grace object takes intervalCount and interval (day), and maxLateFees takes type (fixed) and value. The response is the updated invoice.
curl -X PATCH https://services.smbcrm.com/invoices/<invoice_id>/late-fees-configuration \ -H "Authorization: Bearer <token>" \ -H "Version: v3" \ -H "Content-Type: application/json" \ -d '{ "altId": "<location_id>", "altType": "location", "lateFeesConfiguration": { "enable": true, "value": 25, "type": "fixed", "frequency": { "intervalCount": 1, "interval": "week" }, "grace": { "intervalCount": 3, "interval": "day" } } }'Estimates
Section titled “Estimates”altId, altType, limit, and offset are required. Filter with status (all, draft, sent, accepted, declined, invoiced, viewed), contactId, search (matches the estimate name), and startAt/endAt (YYYY-MM-DD).
curl "https://services.smbcrm.com/invoices/estimate/list?altId=<location_id>&altType=location&limit=20&offset=0" \ -H "Authorization: Bearer <token>" \ -H "Version: v3"The example abbreviates each estimate.
{ "estimates": [ { "_id": "<estimate_id>", "name": "Website build", "total": 4000, "currency": "USD" } ], "total": 1, "traceId": "<trace_id>"}Required fields: altId, altType, name, businessDetails, currency, items, discount, contactDetails (id, name, phoneNo, and email), and frequencySettings. frequencySettings takes enabled and schedule, both required. To repeat an estimate on a schedule, set enabled to true and include intervalType, interval, and startDate in schedule.rrule.
Optional fields include issueDate, expiryDate, estimateNumber, estimateNumberPrefix, sentTo, sendEstimateDetails (send the estimate as you save it), autoInvoice, paymentScheduleConfig, termsNotes, and attachments.
curl -X POST https://services.smbcrm.com/invoices/estimate \ -H "Authorization: Bearer <token>" \ -H "Version: v3" \ -H "Content-Type: application/json" \ -d '{ "altId": "<location_id>", "altType": "location", "name": "Website build", "currency": "USD", "businessDetails": { "name": "<business_name>" }, "contactDetails": { "id": "<contact_id>", "name": "Jordan Lee", "phoneNo": "+15125550142", "email": "jordan@example.com" }, "items": [ { "name": "Design & build", "currency": "USD", "amount": 4000, "qty": 1 } ], "discount": { "value": 0, "type": "percentage" }, "frequencySettings": { "enabled": false, "schedule": {} } }'The response is 201 Created and returns the estimate with a traceId.
{ "_id": "<estimate_id>", "altId": "<location_id>", "altType": "location", "name": "Website build", "currency": "USD", "total": 4000, "traceId": "<trace_id>"}Takes the same required fields as create. It also accepts estimateStatus (all, draft, sent, accepted, declined, invoiced, or viewed). The response is the updated estimate.
curl -X PUT https://services.smbcrm.com/invoices/estimate/<estimate_id> \ -H "Authorization: Bearer <token>" \ -H "Version: v3" \ -H "Content-Type: application/json" \ -d '{ "altId": "<location_id>", "altType": "location", "name": "Website build", "currency": "USD", "businessDetails": { "name": "<business_name>" }, "contactDetails": { "id": "<contact_id>", "name": "Jordan Lee", "phoneNo": "+15125550142", "email": "jordan@example.com" }, "items": [ { "name": "Design & build", "currency": "USD", "amount": 4500, "qty": 1 } ], "discount": { "value": 0, "type": "percentage" }, "frequencySettings": { "enabled": false, "schedule": {} } }'Send altId and altType in a JSON body, not the query string. The response is the deleted estimate.
curl -X DELETE https://services.smbcrm.com/invoices/estimate/<estimate_id> \ -H "Authorization: Bearer <token>" \ -H "Version: v3" \ -H "Content-Type: application/json" \ -d '{ "altId": "<location_id>", "altType": "location" }'Required fields: altId, altType, action (email, sms, sms_and_email, or send_manually), liveMode, and userId. The optional sentFrom object (fromName and fromEmail) sets the sender name and email on the notification and doesn’t apply to send_manually. The response is 201 Created and returns the estimate.
curl -X POST https://services.smbcrm.com/invoices/estimate/<estimate_id>/send \ -H "Authorization: Bearer <token>" \ -H "Version: v3" \ -H "Content-Type: application/json" \ -d '{ "altId": "<location_id>", "altType": "location", "action": "email", "liveMode": true, "userId": "<user_id>" }'Required fields: altId, altType, and markAsInvoiced. When markAsInvoiced is true, the estimate’s status changes to invoiced. The optional version is v1 or v2.
curl -X POST https://services.smbcrm.com/invoices/estimate/<estimate_id>/invoice \ -H "Authorization: Bearer <token>" \ -H "Version: v3" \ -H "Content-Type: application/json" \ -d '{ "altId": "<location_id>", "altType": "location", "markAsInvoiced": true }'The response has the shape { "estimate": { ... }, "invoice": { ... } }.
Numbers and defaults
Section titled “Numbers and defaults”Use these reads to set invoiceNumber and estimateNumber on new records and to find your account’s default due and expiry windows. All three take altId and altType as query parameters.
curl "https://services.smbcrm.com/invoices/generate-invoice-number?altId=<location_id>&altType=location" \ -H "Authorization: Bearer <token>" \ -H "Version: v3"{ "invoiceNumber": 1043 }curl "https://services.smbcrm.com/invoices/estimate/number/generate?altId=<location_id>&altType=location" \ -H "Authorization: Bearer <token>" \ -H "Version: v3"{ "estimateNumber": 12, "traceId": "<trace_id>" }The response includes termsNote, estimatesTermsNote, title, estimatesTitle, invoiceNumberPrefix, estimateNumberPrefix, dueAfterXDays, and estimatesExpireAfterXDays, along with the account’s late fee, tip, reminder, and payment method defaults.
curl "https://services.smbcrm.com/invoices/settings?altId=<location_id>&altType=location" \ -H "Authorization: Bearer <token>" \ -H "Version: v3"Estimate templates
Section titled “Estimate templates”Estimate templates store reusable estimate content. They use the same invoices/estimate.readonly and invoices/estimate.write scopes as estimates.
altId, altType, limit, and offset are required. search matches a template ID or name. The response has the shape { "data": [ ... ], "totalCount": 1, "traceId": "<trace_id>" }.
curl "https://services.smbcrm.com/invoices/estimate/template?altId=<location_id>&altType=location&limit=20&offset=0" \ -H "Authorization: Bearer <token>" \ -H "Version: v3"altId, altType, and templateId are required query parameters.
curl "https://services.smbcrm.com/invoices/estimate/template/preview?altId=<location_id>&altType=location&templateId=<template_id>" \ -H "Authorization: Bearer <token>" \ -H "Version: v3"Required fields: altId, altType, name, businessDetails, currency, items, and discount. Optional fields include title, termsNotes, estimateNumberPrefix, automaticTaxesEnabled, attachments, and miscellaneousCharges. The response is 201 Created and returns the template.
curl -X POST https://services.smbcrm.com/invoices/estimate/template \ -H "Authorization: Bearer <token>" \ -H "Version: v3" \ -H "Content-Type: application/json" \ -d '{ "altId": "<location_id>", "altType": "location", "name": "Website build template", "currency": "USD", "businessDetails": { "name": "<business_name>" }, "items": [ { "name": "Design & build", "currency": "USD", "amount": 4000, "qty": 1 } ], "discount": { "value": 0, "type": "percentage" } }'Takes the same required fields as create. The response is the updated template.
Send altId and altType in a JSON body, not the query string. The response is the deleted template.
curl -X DELETE https://services.smbcrm.com/invoices/estimate/template/<template_id> \ -H "Authorization: Bearer <token>" \ -H "Version: v3" \ -H "Content-Type: application/json" \ -d '{ "altId": "<location_id>", "altType": "location" }'Invoice templates
Section titled “Invoice templates”Invoice templates store reusable invoice content. Reads need invoices/template.readonly; writes need invoices/template.write.
altId, altType, limit, and offset are required. Filter with search, status, paymentMode (default, live, or test), and startAt/endAt (YYYY-MM-DD). The response has the shape { "data": [ ... ], "totalCount": 1 }.
curl "https://services.smbcrm.com/invoices/template?altId=<location_id>&altType=location&limit=20&offset=0" \ -H "Authorization: Bearer <token>" \ -H "Version: v3"altId and altType are required query parameters.
curl "https://services.smbcrm.com/invoices/template/<template_id>?altId=<location_id>&altType=location" \ -H "Authorization: Bearer <token>" \ -H "Version: v3"Required fields: altId, altType, name, businessDetails, currency, and items. Optional fields include title, termsNotes, discount, invoiceNumberPrefix, automaticTaxesEnabled, tipsConfiguration, lateFeesConfiguration, paymentMethods, attachments, and miscellaneousCharges.
curl -X POST https://services.smbcrm.com/invoices/template \ -H "Authorization: Bearer <token>" \ -H "Version: v3" \ -H "Content-Type: application/json" \ -d '{ "altId": "<location_id>", "altType": "location", "name": "Monthly retainer template", "currency": "USD", "businessDetails": { "name": "<business_name>" }, "items": [ { "name": "Consulting", "currency": "USD", "amount": 500, "qty": 1 } ] }'Required fields: altId, altType, name, businessDetails, currency, and items. The response is the updated template.
altId and altType go in the query string. The response is { "success": true }.
curl -X DELETE "https://services.smbcrm.com/invoices/template/<template_id>?altId=<location_id>&altType=location" \ -H "Authorization: Bearer <token>" \ -H "Version: v3"Send altId, altType, and lateFeesConfiguration, which takes the same fields as PATCH /invoices/{invoiceId}/late-fees-configuration. The response is the updated template.
Send altId, altType, and paymentMethods. The response is the updated template.
Recurring invoice schedules
Section titled “Recurring invoice schedules”A schedule sends an invoice to a contact on a repeating basis. Reads need invoices/schedule.readonly; writes need invoices/schedule.write.
altId, altType, limit, and offset are required. Filter with search, status, paymentMode (default, live, or test), and startAt/endAt (YYYY-MM-DD). The response has the shape { "schedules": [ ... ], "total": 1 }.
curl "https://services.smbcrm.com/invoices/schedule?altId=<location_id>&altType=location&limit=20&offset=0" \ -H "Authorization: Bearer <token>" \ -H "Version: v3"altId and altType are required query parameters.
curl "https://services.smbcrm.com/invoices/schedule/<schedule_id>?altId=<location_id>&altType=location" \ -H "Authorization: Bearer <token>" \ -H "Version: v3"Required fields: altId, altType, name, contactDetails (id, name, phoneNo, and email), schedule, liveMode, businessDetails, currency, items, and discount.
schedule.rrule sets the repeat pattern. It requires intervalType (yearly, monthly, weekly, daily, hourly, minutely, or secondly), interval, and startDate (YYYY-MM-DD). Optional rrule fields are startTime, endDate, endTime, dayOfMonth, dayOfWeek, numOfWeek, monthOfYear, count, daysBefore, useStartAsPrimaryUserAccepted, and endType. Optional schedule fields include title, termsNotes, automaticTaxesEnabled, tipsConfiguration, lateFeesConfiguration, invoiceNumberPrefix, paymentMethods, attachments, and miscellaneousCharges.
curl -X POST https://services.smbcrm.com/invoices/schedule \ -H "Authorization: Bearer <token>" \ -H "Version: v3" \ -H "Content-Type: application/json" \ -d '{ "altId": "<location_id>", "altType": "location", "name": "Monthly retainer", "contactDetails": { "id": "<contact_id>", "name": "Jordan Lee", "phoneNo": "+15125550142", "email": "jordan@example.com" }, "schedule": { "rrule": { "intervalType": "monthly", "interval": 1, "startDate": "2026-11-01" } }, "liveMode": true, "businessDetails": { "name": "<business_name>" }, "currency": "USD", "items": [ { "name": "Consulting", "currency": "USD", "amount": 500, "qty": 1 } ], "discount": { "value": 0, "type": "percentage" } }'Takes the same required fields as create. The response is the updated schedule.
altId and altType go in the query string. The response is { "success": true }.
curl -X DELETE "https://services.smbcrm.com/invoices/schedule/<schedule_id>?altId=<location_id>&altType=location" \ -H "Authorization: Bearer <token>" \ -H "Version: v3"Required fields: altId, altType, and liveMode. The optional autoPayment object (enable is required inside it) turns on automatic payment for the schedule. The response is the schedule.
curl -X POST https://services.smbcrm.com/invoices/schedule/<schedule_id>/schedule \ -H "Authorization: Bearer <token>" \ -H "Version: v3" \ -H "Content-Type: application/json" \ -d '{ "altId": "<location_id>", "altType": "location", "liveMode": true }'Required fields: altId, altType, id, and autoPayment. Inside autoPayment, enable is required. The response is the schedule.
Send altId and altType in the body. The response is the schedule.
curl -X POST https://services.smbcrm.com/invoices/schedule/<schedule_id>/cancel \ -H "Authorization: Bearer <token>" \ -H "Version: v3" \ -H "Content-Type: application/json" \ -d '{ "altId": "<location_id>", "altType": "location" }'Takes no request body. The response is the schedule.
Related
Section titled “Related”- Payments overview: all payment resources.
- Products & Prices: the catalog you bill from.
- Contacts: the contact an invoice bills.
