Update Invoice
Edit, publish or cancel an invoice. Publishing and cancelling are status transitions, not separate endpoints.
POST
https://api-v3.sweeppea.com/invoices/update
Description
This endpoint edits an invoice while it is still draft or pending, and is also how an invoice is published (Status: "pending") or cancelled (Status: "cancelled"). Every field is optional: anything omitted keeps its stored value, and Items and BillTo are replaced wholesale rather than merged. Publishing does not email the recipient.
Authentication
This endpoint requires Bearer token authentication via the Authorization header.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
InvoiceToken |
String | Yes | UUID v4 of the invoice to edit |
BillTo |
Object | No | Replaces the whole recipient. Still requires Name and a valid Email |
Items |
Array | No | Replaces the whole line item set. Maximum 60 items |
Title |
String | No | Invoice title / concept (max 200 characters) |
IssueDate |
String | No | ISO date (YYYY-MM-DD) |
DueDate |
String | No | ISO date (YYYY-MM-DD) |
DiscountAmount |
Number | No | Flat discount, clamped to the subtotal |
TaxEnabled |
Boolean | No | Apply tax |
TaxLabel |
String | No | Tax label |
TaxRate |
Number | No | Tax percentage from 0 to 100 |
PaymentMethod |
String | No | card, check, transfer or recipient (the payer chooses on the invoice page) |
PaymentInstructions |
String | No | Offline instructions. Forced empty when the method is card |
NotesToRecipient |
String | No | Notes shown to the recipient (max 3000 characters) |
Terms |
String | No | Terms and conditions (max 3000 characters) |
Status |
String | No | pending publishes a draft, cancelled cancels the invoice |
Code Examples
curl -X POST "https://api-v3.sweeppea.com/invoices/update" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"InvoiceToken": "uuid-v4-string",
"Title": "August retainer (revised)",
"Items": [
{
"Description": "Consulting",
"Quantity": 12,
"Rate": 450
}
],
"Status": "pending"
}'
const response = await fetch('https://api-v3.sweeppea.com/invoices/update', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
InvoiceToken: "uuid-v4-string",
Title: "August retainer (revised)",
Items: [
{
"Description": "Consulting",
"Quantity": 12,
"Rate": 450
}
],
Status: "pending"
})
});
const data = await response.json();
console.log(data);
import requests
url = "https://api-v3.sweeppea.com/invoices/update"
headers = {
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json"
}
payload = {
"InvoiceToken": "uuid-v4-string",
"Title": "August retainer (revised)",
"Items": [
{
"Description": "Consulting",
"Quantity": 12,
"Rate": 450
}
],
"Status": "pending"
}
response = requests.post(url, headers=headers, json=payload)
print(response.json())
Response
{
"Response": true,
"Telemetry": {
"DataConsumed": 0,
"APICalls": 149,
"MaxAPICalls": 1500000
},
"Data": {
"InvoiceToken": "uuid-v4-string",
"InvoiceNumber": "INV-2026-00001",
"Action": "issued",
"Status": "pending",
"PreviousStatus": "draft",
"Items": [
{
"Id": "",
"Description": "Consulting",
"Quantity": 12,
"Rate": 450,
"Amount": 5400
}
],
"Subtotal": 5400,
"DiscountAmount": 100,
"TaxEnabled": true,
"TaxRate": 8.5,
"TaxAmount": 450.5,
"AmountBeforeFees": 5750.5,
"SweeppeaFeeAmount": 172.52,
"MerchantFeeAmount": 172.52,
"FeeAmount": 345.04,
"FeesChargedToRecipient": true,
"Total": 6095.54,
"PaymentMethod": "card",
"PublicLink": "https://app.sweeppea.com/invoice?t=uuid-v4-string",
"Changes": [
{
"Field": "Title",
"From": "August retainer",
"To": "August retainer (revised)"
},
{
"Field": "Status",
"From": "draft",
"To": "pending"
}
]
},
"Message": "Invoice issued successfully."
}
Error Responses
{
"Response": false,
"Message": "Missing required parameter: InvoiceToken",
"Code": 400,
"Help": {
"ExpectedBody": {
"InvoiceToken": "string (required) \u2014 UUID v4 of the invoice to edit",
"Status": "string (optional) \u2014 \"pending\" publishes a draft, \"cancelled\" cancels the invoice. Never demotes back to draft"
}
}
}
{
"Response": false,
"Message": "An invoice can never be moved back to draft. Accepted transitions: pending (publish) or cancelled.",
"Code": 400
}
{
"Response": false,
"Message": "Invalid Status. Accepted transitions: pending or cancelled.",
"Code": 400
}
{
"Response": false,
"Message": "Missing or invalid Bearer token. Send your API token in the Authorization header as: Authorization: Bearer YOUR_API_TOKEN",
"Code": 401
}
{
"Response": false,
"Message": "Invalid API token. It does not match any account.",
"Code": 403
}
{
"Response": false,
"Message": "Invoice not found.",
"Code": 404
}
{
"Response": false,
"Message": "This invoice is paid and can no longer be modified. Only draft and pending invoices are editable.",
"Code": 409
}
{
"Response": false,
"Message": "Internal server error. Please try again; if it persists, contact support with the time of this request.",
"Code": 500
}
Important Notes
- π Module Access: The Invoices module is disabled by default. An administrator must enable it for your account before any of these endpoints will respond
- π¦ Status Machine:
draft β pending β paid, withcancelledreachable fromdraftandpending. Payment itself happens on the public page or through an administrator, never through this endpoint - β Never Demoted:
Status: "draft"is always rejected. An invoice only moves forward - π Immutable When Closed:
paidandcancelledinvoices return409β they are financial history - π§ Frozen Fees: The commission percentages are never recomputed on update β they are written back unchanged alongside the amounts they produced, so the stored figures always reconcile
- π³ Fees Are Paid By The Recipient, And Only On A Card: changing
PaymentMethodrecomputes the breakdown. Switching acardinvoice tocheckortransferremoves every fee and lowersTotalto the base; switching back adds the surcharge again. Onrecipient,Totalis the base andFeeAmountis what the payer would add by taking the card - π§ No Email: Publishing does not notify the recipient. Distribute
PublicLinkyourself - π Audit Trail: Every call appends an entry to the invoice's modifications log with the exact field-level changes returned in
Changes