Create
const url = 'https://example.com/expenses';const options = { method: 'POST', headers: { 'Idempotency-Key': '2489E9AD-2EE2-8E00-8EC9-32D5F69181C0', 'Content-Type': 'application/json' }, body: '{"categoryId":"example","jobId":"example","date":"2026-04-15","currency":"example","amount":"example","taxAmount":"example","taxRateId":"example","description":"example","paidBy":"company","receiptFileId":"example","isBillable":false}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://example.com/expenses \ --header 'Content-Type: application/json' \ --header 'Idempotency-Key: 2489E9AD-2EE2-8E00-8EC9-32D5F69181C0' \ --data '{ "categoryId": "example", "jobId": "example", "date": "2026-04-15", "currency": "example", "amount": "example", "taxAmount": "example", "taxRateId": "example", "description": "example", "paidBy": "company", "receiptFileId": "example", "isBillable": false }'Who can call it: Owners, Staff and Field users. Staff need the Team right Submit/edit own expenses (expenses.edit_own).
curl -X POST "https://spine.example.com/api/expenses" \
-H "Cookie: better-auth.session_token=<session>" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" -d '{ … }'
Parameters
Section titled “Parameters”Header Parameters
Section titled “Header Parameters”A fresh UUID per action. A retry with the same key gets the first answer instead of doing it twice.
Request Bodyrequired
Section titled “Request Bodyrequired”object
ISO 4217 currency code.
Integer minor units, as a numeric string.
Integer minor units, as a numeric string. Defaults to 0.
A file this person uploaded via POST /files that nothing else uses yet (D-250).
Responses
Section titled “Responses”Validation failed or a business rule was broken; message says what to change.
No session, or it has expired: sign in again.
The caller’s role, Team rights or ownership don’t allow it, the module is switched off, or their access was removed.
No such record in this business.
The same Idempotency-Key is still being handled, or the record conflicts with one that exists.
Too many requests: wait a minute.
Something went wrong on the server; the response carries the request id to report.