Sparky Invoices API

Read invoices, clients and payments; create clients and draft invoices; pull clients in from Contacts. Sending and recording payments stay in the app.

Address
https://invoices.sparkyli.com/api/v1
Plan
Plus and Max, with API access switched on for the organization

Endpoints

GET /clients

Clients, by name.

Inputs

NameTypeWhat it is
limitwhole number 1 to 100Page size. Default 50.
offsetwhole numberUse next_offset from the previous page.

Answer: clients (a list) and next_offset

NameTypeWhat it is
idtextUse this as client_id when you create an invoice.
nametextThe name the client is billed as.
contact_name, email, phone, gstin, websitetext or nullAs entered.
payment_terms, currencytext or nullThe client's usual terms and three-letter currency.
created_at, updated_attextUTC time.
next_offsetwhole number or nullnull on the last page.

POST /clients

Create a client, like New client in the app.

Needs a role that may create clients and a plan with Clients. It does not look for a client with the same name or email: GET /clients first if unsure.

Inputs

NameTypeWhat it is
Idempotency-Keyheader, text up to 120 charactersNew for each client. A retry with the same key returns the first answer.

Body (JSON)

NameTypeWhat it is
name*text, up to 200The name the client is billed as.
contact_nametext, up to 200The person at the client.
emailtext, up to 200Must look like an email address. Invoices are emailed here.
phonetext, up to 40
billing_addresstext, up to 500
gstintext, up to 20The client's GSTIN. It also sets the place of supply on their invoices.
payment_termstext, up to 100For example Net 15.
websitetext, up to 200
currency3 lettersA supported code such as INR or USD.

Answer: client

NameTypeWhat it is
idtextThe new client's id, for POST /invoices.
the fields aboveAs saved, with created_at and updated_at.

Errors (besides the common ones)

  • 400 bad_request: name is missing, the email or currency is not valid, or a field is too long.

Example body

{ "name": "Asha Traders", "email": "accounts@asha.example", "currency": "INR", "payment_terms": "Net 15" }

Example answer (201)

{ "client": { "id": "cli_5f0c1d52-7c1e-4e55-9a0b-3d7a8f6c2b10", "name": "Asha Traders", "email": "accounts@asha.example", "currency": "INR", "payment_terms": "Net 15", "created_at": "2026-11-03 07:09:01" } }

POST /clients/sync

Pull contacts from Sparky Contacts in as clients, as the Sync page does.

Needs the permission to manage integrations and a plan with syncing from other products. A client edited here is overwritten by its contact's details.

Body (JSON)

NameTypeWhat it is
contact_idtextSync only this contact (its id in Contacts). Leave out to sync every contact changed since the last sync.

Answer: (top level)

NameTypeWhat it is
createdwhole numberClients created.
updatedwhole numberExisting clients updated.
linkslistOne { contact_id, client_id } per contact synced. Use client_id in POST /invoices.

Errors (besides the common ones)

  • 404 not_found: contact_id does not exist or is archived.
  • 502 upstream_unavailable: Sparky Contacts could not be reached. Try again.

Example body

{ "contact_id": "con_8c1f0f3e-1b8e-4a3e-9d0c-6a2c1e5b7a10" }

Example answer (201)

{ "created": 1, "updated": 0, "links": [ { "contact_id": "con_8c1f0f3e-1b8e-4a3e-9d0c-6a2c1e5b7a10", "client_id": "cli_5f0c1d52-7c1e-4e55-9a0b-3d7a8f6c2b10" } ] }

GET /invoices

Invoices, newest first, with the amount paid so far.

Inputs

NameTypeWhat it is
statusdraft, sent, paid or voidOnly invoices in this state.
client_idtextOnly this client's invoices.
limit, offsetwhole numbersPaging, as for clients.

Answer: invoices (a list) and next_offset

NameTypeWhat it is
id, client_id, invoice_numbertextThe invoice, its client and its number, like INV-0004.
statusdraft, sent, paid or void
invoice_typeregular, export_with_tax or export_without_tax
is_credit_note, is_debit_note0 or 1
currency3 letters
issue_date, due_datedate, YYYY-MM-DDdue_date can be null.
subtotal, tax_total, total, paidwhole number, minor unitsFor example paise or cents. total is subtotal plus tax.
bill_to_name, recipient_email, payment_termstext or null
sent_at, created_at, updated_attext or nullUTC time.

GET /invoices/{id}

One invoice with its lines, and its payments if your role may see them.

Inputs

NameTypeWhat it is
id*textThe invoice's id.

Answer: invoice

NameTypeWhat it is
(all the list fields, and these)
notes, place_of_supply, original_invoice_idtext or nulloriginal_invoice_id is set on a credit or debit note.
lineslistdescription, quantity, unit_price, tax_rate, hsn_sac_code, line_total.
paymentslistamount, currency, paid_on, method, label. Only if your role may see payments.

Errors (besides the common ones)

  • 404 not_found: No such invoice in this organization.

GET /payments

Payments recorded against invoices, newest first.

Needs a role that may view payments.

Inputs

NameTypeWhat it is
invoice_idtextOnly payments on this invoice.
methodtextOnly this method, for example upi or bank_transfer.
from, todate, YYYY-MM-DDEarliest and latest payment date.
limit, offsetwhole numbersPaging: limit 1 to 100 (default 50); offset from next_offset.

Answer: payments (a list) and next_offset

NameTypeWhat it is
id, invoice_id, invoice_number, client_idtextThe payment and the invoice and client it belongs to.
bill_to_nametextThe client's name as it was on the invoice.
amountwhole number, minor unitsAs paid, including any tax collected at source.
currency3 letters
paid_ondate
methodtext or nullFor example upi, bank_transfer, razorpay or cash.
labeltext or nullTags a part payment, such as deposit or balance.
tcs_amount, tds_amountwhole number, minor unitsTax collected at source, and tax the payer deducted at source (no cash moved, but it settles the invoice).
created_attextUTC time.

GET /payments/{id}

One payment with the invoice it settled. The payment gateway's own reference is never returned.

Inputs

NameTypeWhat it is
id*textThe payment's id.

Answer: payment

NameTypeWhat it is
(all the list fields, and these)
invoice_totalwhole number, minor unitsThe invoice's total.
invoice_statusdraft, sent, paid or void

Errors (besides the common ones)

  • 404 not_found: No such payment in this organization.

POST /invoices

Create a DRAFT invoice for an existing client.

It never creates a client and never sends anything: a person reviews and sends it in the app. It gets the next invoice number and the organization's tax details, as in the app. Needs the permission to create invoices; the plan's monthly invoice limit applies.

Inputs

NameTypeWhat it is
Idempotency-Keyheader, text up to 120 charactersNew for each invoice. A retry with the same key returns the same invoice, so a monthly job can be re-run safely.

Body (JSON)

NameTypeWhat it is
client_id*textAn existing client in this organization: from GET /clients, POST /clients or the sync result.
line_items*list of 1 to 100The lines, below.
currency3 lettersDefault INR.
issue_datedate, YYYY-MM-DDDefault today.
due_datedate, YYYY-MM-DD
payment_termstext, up to 100
notestext, up to 2000Shown on the invoice.
invoice_typeregular, export_with_tax or export_without_taxDefault regular.
place_of_supplytext, up to 10GST state code. Default: the client's GSTIN state.
line_items[].description*text, up to 500
line_items[].unit_price*whole number, minor unitsPrice of one unit; 5000000 is 50,000.00.
line_items[].quantitynumberDefault 1.
line_items[].tax_ratenumber 0 to 100Percent, for example 18. Default 0.
line_items[].hsn_sac_codetext, up to 20

Answer: invoice

NameTypeWhat it is
id, invoice_number, statustextstatus is draft.
subtotal, tax_total, totalwhole number, minor unitsWorked out from the lines.
line_itemslistThe saved lines with their ids and line_total.
the other invoice fieldsAs in GET /invoices/{id}.

Errors (besides the common ones)

  • 404 client_not_found: No client with that client_id in this organization. Create it first.
  • 400 bad_request: A field is missing or wrong; the message names it (for example line_items[0].unit_price).
  • 403 plan_limit: The plan's invoice limit for this month is reached.

Example body

{ "client_id": "cli_5f0c1d52-7c1e-4e55-9a0b-3d7a8f6c2b10", "issue_date": "2026-12-01", "due_date": "2026-12-15", "line_items": [ { "description": "Monthly retainer", "quantity": 1, "unit_price": 5000000, "tax_rate": 18 } ] }

Example answer (201)

{ "invoice": { "id": "inv_0b7a6d4e-2f4b-4b0b-8e57-6a9c1f2d3e44", "client_id": "cli_5f0c1d52-7c1e-4e55-9a0b-3d7a8f6c2b10", "invoice_number": "INV-0004", "status": "draft", "currency": "INR", "subtotal": 5000000, "tax_total": 900000, "total": 5900000, "line_items": [ { "description": "Monthly retainer", "quantity": 1, "unit_price": 5000000, "tax_rate": 18, "line_total": 5000000 } ] } }

Example

curl -s -H "authorization: Bearer $TOKEN" "https://invoices.sparkyli.com/api/v1/invoices?status=sent"

New here? Start with the three things first, then sign in. Errors are explained under errors and limits.