Invoices | FieldCamp API
Use the FieldCamp Invoices API to create, list, update, void, and collect on v1 invoices with line items, discounts, markup, and Stripe payment links.
The FieldCamp Invoices API is how your integration turns completed work into money in the bank — create draft invoices, attach line items with document-level or item-level discounts and markup, push status changes, and hand the customer a hosted Stripe payment link. With release_v2, the resource is available under the versioned path /api/v1/invoices, which adds server-side clientId, status, and since filters and a dedicated payment-link endpoint. If you want the in-app workflow instead, the Creating invoices guide walks through the UI step by step.
What changed in release_v2
The /api/v1/invoices namespace is now the recommended path for new integrations. The unversioned /api/invoices endpoints still exist for backward compatibility, but they do not expose the new filters or the Stripe payment-link helper.
- Versioned base path:
/api/v1/invoices(instead of/api/invoices). - Server-side filters on the list endpoint:
clientId,status, andsince. - Status vocabulary aligned with the in-app invoice views and analytics:
unpaid,paid,partial, andoverdue. - Document-level and item-level
discountandmarkupfields on the same payload. - New
GET /api/v1/invoices/{id}/payment-linkendpoint that returns a hosted Stripe checkout URL.
This endpoint requires an fc_live_ API key. See Authentication for header conventions, Errors for the error envelope, and Rate limits for throttling rules.
When to use the Invoices API
Most integrations hit /api/v1/invoices the moment a job is wrapped — the technician marks the job complete, and your backend rolls up the products and services used on the visit into one invoice for the client. You can also use it to:
- Bulk-import historic invoices when migrating from another field-service system.
- Auto-issue invoices on a schedule for recurring jobs.
- Generate a Stripe payment link the second a job is closed out.
- Sync invoice status changes nightly into your data warehouse for custom dashboards and boards.
How an invoice is structured
Every FieldCamp invoice has three layers — header, line items, and totals — and the API mirrors that shape one-for-one.
- Header —
clientId, billing/property address, invoice number, issue date, due date, currency, notes, optional reference to the originating job, and optional document-leveldiscountandmarkup. - Line items — an array of items pulled from your price book and bundles. Each line carries
itemId,description,quantity,unitPrice, an item-levelmarkup(percent or amount), an item-leveldiscount(percent or amount), andtaxIdsresolved from Taxes. - Totals —
subTotal,discountTotal,markupTotal,taxTotal, andtotalare calculated server-side from the line items so totals always match the audit trail.
Reuse the same itemId values you use on jobs. That keeps the client detail page consistent and avoids creating duplicate items in your price book.
Filtering and search
GET /api/v1/invoices accepts the following query parameters:
clientId— return invoices for a single client. Useful for portals and statement views.status— exact match againstunpaid,paid,partial, oroverdue.partialcovers any invoice with deposits applied but a balance remaining.since— ISO 8601 timestamp. Returns invoices whoseupdatedAtis greater than or equal to the supplied value. Ideal for nightly delta syncs.limitandcursor— standard pagination parameters used across the API.
Example: invoices for one client
curl "https://api.fieldcamp.ai/api/v1/invoices?clientId=$CLIENT_ID" \
-H "Authorization: Bearer $FIELDCAMP_API_KEY"Example: pull overdue invoices
curl "https://api.fieldcamp.ai/api/v1/invoices?status=overdue&limit=100" \
-H "Authorization: Bearer $FIELDCAMP_API_KEY"Example: incremental sync
curl "https://api.fieldcamp.ai/api/v1/invoices?since=2026-05-01T00:00:00Z" \
-H "Authorization: Bearer $FIELDCAMP_API_KEY"Create an invoice with line items, discounts, and markup
Send a POST /api/v1/invoices request with the header and a lineItems array. Discounts and markup can be applied at the line level on each item, or as a single document-level value that applies to the whole invoice. Markup is computed on unitPrice before tax; discounts are computed after markup.
Look up or create the client
Call GET /api/v1/clients?search=<email> to find an existing record, or POST /api/v1/clients to create one. Reuse the returned id as the clientId on the invoice.
Resolve item and tax IDs
Pull itemId values from Items and taxId values from Taxes. Cache them locally — they almost never change between invoices.
Build the line items
For each line, set quantity, unitPrice, optional markup ({ type: "percent" | "amount", value }), optional discount ({ type: "percent" | "amount", value }), and taxIds. The server multiplies, marks up, discounts, then taxes — in that order.
POST the invoice
Send the payload to POST /api/v1/invoices. The response includes the server-calculated subTotal, discountTotal, markupTotal, taxTotal, and total so you can reconcile before persisting locally.
Store the returned ID
Keep the returned id alongside your internal record. You will need it for status updates, edits, and the Stripe payment-link call below.
Example request
curl -X POST https://api.fieldcamp.ai/api/v1/invoices \
-H "Authorization: Bearer $FIELDCAMP_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"clientId": "cli_123",
"jobId": "job_456",
"issueDate": "2026-05-29",
"dueDate": "2026-06-12",
"status": "unpaid",
"currency": "USD",
"discount": { "type": "percent", "value": 5 },
"lineItems": [
{
"itemId": "itm_789",
"description": "Annual HVAC tune-up",
"quantity": 1,
"unitPrice": 199.00,
"markup": { "type": "percent", "value": 10 },
"taxIds": ["tax_001"]
}
],
"notes": "Thanks for your business!"
}'Send monetary values as numbers in major units of the invoice's currency (e.g. 199.50). Mixing strings and numbers across line items is the most common cause of 400 validation errors. See Errors for the full catalog.
Update invoices and move statuses
- Fetch one —
GET /api/v1/invoices/{id}returns the full invoice including computed totals and any signature blocks captured in the field. - Update —
PUT /api/v1/invoices/{id}accepts the same body as create. Send only the fields you want to change; omitted fields are left untouched. - Status transitions — set
statustounpaid,paid,partial, oroverdue. Status drives where the invoice shows up in the invoice views and analytics and which clients see it in their portal. - Delete —
DELETE /api/v1/invoices/{id}removes a draft. Once an invoice has been sent or partially paid, prefer keeping the record and changingstatusinstead so your reporting stays intact.
overdue is set automatically by FieldCamp when dueDate passes and the invoice is not fully paid. You can also set it explicitly via PUT if your billing rules require it earlier.
Issue a Stripe payment link
If your tenant has connected Stripe, call GET /api/v1/invoices/{id}/payment-link to generate a hosted Stripe checkout URL for the invoice. The response includes the url, the expiresAt timestamp, and the underlying stripePaymentIntentId for reconciliation.
curl https://api.fieldcamp.ai/api/v1/invoices/$INVOICE_ID/payment-link \
-H "Authorization: Bearer $FIELDCAMP_API_KEY"You can email the same link to the client via two-way text messaging, or embed it in your own customer portal. Stripe handles the card capture; FieldCamp posts the payment back against the invoice automatically and moves the status from unpaid (or partial) to paid when the balance hits zero. For deposit-style up-front payments, see Deposits and partial payments.
Endpoints
GET /api/v1/invoices— list invoices filtered byclientId,status, and/orsince.POST /api/v1/invoices— create an invoice with line items, discounts, markup, and tax.GET /api/v1/invoices/{id}— fetch a single invoice including computed totals.PUT /api/v1/invoices/{id}— update header fields, line items, or status.DELETE /api/v1/invoices/{id}— delete a draft (prefer a status change for sent invoices).GET /api/v1/invoices/{id}/payment-link— return a Stripe hosted payment URL for the invoice.
Best practices
After a job is marked complete, pull its line items and POST them straight into an invoice. Reusing IDs keeps the audit trail clean.
Pull your taxId list at startup and pass them on every line. The server recomputes taxTotal from those IDs every time.
Use since and clientId to find existing invoices before creating. On a retry you reuse the record instead of double-billing the client.
Bulk back-fills should respect the per-tenant rate limit. Batch in chunks and back off on 429 responses.
FAQs
Which statuses can I send to POST and PUT?
unpaid, paid, partial, and overdue. New invoices default to unpaid if no status is sent.
How do document-level and item-level discounts combine?
Item-level markup and discount are applied first while computing each line. The document-level discount is then applied to the resulting subTotal before tax. The final total is subTotal - documentDiscount + taxTotal.
Can I filter the list endpoint by both clientId and status?
Yes. All three filters (clientId, status, since) are independent and can be combined in any order on GET /api/v1/invoices.
Does the payment link expire?
The response includes expiresAt. Generate a fresh link if more than 24 hours have passed since issuance, or whenever the invoice balance changes.
What happens if Stripe is not connected?
GET /api/v1/invoices/{id}/payment-link returns a 409 error. Connect Stripe via Connect Stripe for online payments and retry.
Troubleshooting
400 lineItems is required—POST /api/v1/invoicesrequires at least one line item. Add a placeholder labour line if you have nothing else to bill.- Totals don't match my upstream system — remember the calculation order: per-line markup, per-line discount, per-line tax, then document-level discount. Compute totals in the same order before comparing.
statusignored on update — onlyunpaid,paid,partial, andoverdueare accepted. Other values are silently dropped; check the response body for the canonical status.sincenot returning new rows —sincematchesupdatedAt, notissueDate. Use the most recentupdatedAtyou have seen as the next cursor.
Related articles
- Authentication
- Errors
- Idempotency
- Rate limits
- Webhooks
- Clients (API)
- Jobs (API)
- Visits (API)
- Items (API)
- Taxes (API)
- Creating invoices
- Invoice views and analytics
- Digital signatures on estimates and invoices
- Connect Stripe for online payments
- Deposits and partial payments
- Managing products and services
- Price book and bundles
- Custom dashboards and boards
- Job and visit statuses
- Client detail page
- Two-way text messaging
- Recurring jobs
Calendar & Accounting Sync API for Google Calendar, Outlook & QuickBooks | FieldCamp
FieldCamp's calendar sync API lets you trigger Google Calendar, Outlook and QuickBooks syncs and pull incremental changes from one place.
Changelog | FieldCamp API
Notable changes to the FieldCamp public API and documentation.