Update expense
- Sandbox: your partner domain on the Keep sandbox:
PATCH https://<partner_domain>.keep.co.il/api/public/expenses/{expenseId}
- Production: your partner domain:
PATCH https://<partner_domain>.keep.co.il/api/public/expenses/{expenseId}
Credentials
- Header
Authorization: Bearer <token>
Partially update an existing expense document. Only expenses with pending status can be updated.
The partner can only update expenses within their own scope, and the expense must belong to the provided sellerId.
Immutable fields (ignored if provided): id, uid, partnerId, createdAt, updatedAt, updatedBy, seller, supplierSnapshot, vatReportSnapshot, isAbleToAutoApprove, status.
Parameters
| Name |
In |
Type |
Required |
Description |
expenseId |
path |
string |
yes |
Expense UUID to update |
Request body
Content type: application/json
| Field |
Type |
Required |
Description |
sellerId |
string |
yes |
Seller UUID the expense belongs to |
valueDate |
string |
no |
Expense value date (ISO 8601 UTC) |
totalAmount |
number |
no |
Total expense amount, minimum 0. |
vatAmount |
number |
no |
VAT amount (must be ≤ totalAmount), minimum 0. Required when totalAmount is sent. |
currency |
string |
no |
Currency code. Allowed values: ILS, USD, EUR, GBP, TRY, CHF, SEK, NOK, CAD, ZAR, JPY, AUD, AED, ARS, BHD, BRL, CNY, INR, KRW, KWD, KZT, MXN, NGN, PLN, RSD, RUB, SAR, UAH, PHP, VND. |
docType |
string |
no |
Document type. Allowed values: invoice, invrec, receipt, deal, unknown. |
docRegulationId |
string |
no |
Document regulation ID |
classification |
integer |
no |
Classification ID from the Keep expense classification table. An unknown ID is refused with 422 Invalid classification. |
deductibleIncomeTaxPercent |
number |
no |
Deductible income tax percentage (0–100). Decimals are accepted. |
deductibleVatPercent |
number |
no |
Deductible VAT percentage (0–100). Decimals are accepted. |
assetVatRefundPercent |
number |
no |
Asset VAT refund percentage (0–100). Decimals are accepted. |
comment |
string |
no |
Optional partner note, at most 1024 characters. |
supplierName |
string |
no |
Supplier name, at most 256 characters. Applied only together with supplierVatId. |
supplierVatId |
string |
no |
Supplier VAT ID, digits. An invalid ID is refused with 422 Provided supplier ID is invalid. |
Request example
{
"sellerId": "a6a9700f-8571-4f9b-bfae-ba943fb96982",
"valueDate": "2025-10-28T00:00:00.000Z",
"totalAmount": 15000,
"vatAmount": 2288,
"currency": "ILS",
"docType": "invrec",
"docRegulationId": "5132277",
"classification": 6,
"deductibleIncomeTaxPercent": 100,
"deductibleVatPercent": 100,
"assetVatRefundPercent": 0,
"comment": "Optional partner note",
"supplierName": "Supplier Ltd",
"supplierVatId": "123456789"
}
Code samples
curl
curl -X PATCH 'https://<partner_domain>.keep.co.il/api/public/expenses/<expenseId>' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <YOUR_TOKEN>' \
--data-raw '{
"sellerId": "a6a9700f-8571-4f9b-bfae-ba943fb96982",
"valueDate": "2025-10-28T00:00:00.000Z",
"totalAmount": 15000,
"vatAmount": 2288,
"currency": "ILS",
"docType": "invrec",
"docRegulationId": "5132277",
"classification": 6,
"deductibleIncomeTaxPercent": 100,
"deductibleVatPercent": 100,
"assetVatRefundPercent": 0,
"comment": "Optional partner note",
"supplierName": "Supplier Ltd",
"supplierVatId": "123456789"
}'
Node.js
const response = await fetch("https://<partner_domain>.keep.co.il/api/public/expenses/<expenseId>", {
method: "PATCH",
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer <YOUR_TOKEN>",
},
body: JSON.stringify({
"sellerId": "a6a9700f-8571-4f9b-bfae-ba943fb96982",
"valueDate": "2025-10-28T00:00:00.000Z",
"totalAmount": 15000,
"vatAmount": 2288,
"currency": "ILS",
"docType": "invrec",
"docRegulationId": "5132277",
"classification": 6,
"deductibleIncomeTaxPercent": 100,
"deductibleVatPercent": 100,
"assetVatRefundPercent": 0,
"comment": "Optional partner note",
"supplierName": "Supplier Ltd",
"supplierVatId": "123456789"
}),
});
console.log(await response.text());
Python
import requests
response = requests.patch(
"https://<partner_domain>.keep.co.il/api/public/expenses/<expenseId>",
headers={
"Authorization": "Bearer <YOUR_TOKEN>",
},
json={
"sellerId": "a6a9700f-8571-4f9b-bfae-ba943fb96982",
"valueDate": "2025-10-28T00:00:00.000Z",
"totalAmount": 15000,
"vatAmount": 2288,
"currency": "ILS",
"docType": "invrec",
"docRegulationId": "5132277",
"classification": 6,
"deductibleIncomeTaxPercent": 100,
"deductibleVatPercent": 100,
"assetVatRefundPercent": 0,
"comment": "Optional partner note",
"supplierName": "Supplier Ltd",
"supplierVatId": "123456789",
},
)
print(response.text)
PHP
<?php
$body = <<<'BODY'
{
"sellerId": "a6a9700f-8571-4f9b-bfae-ba943fb96982",
"valueDate": "2025-10-28T00:00:00.000Z",
"totalAmount": 15000,
"vatAmount": 2288,
"currency": "ILS",
"docType": "invrec",
"docRegulationId": "5132277",
"classification": 6,
"deductibleIncomeTaxPercent": 100,
"deductibleVatPercent": 100,
"assetVatRefundPercent": 0,
"comment": "Optional partner note",
"supplierName": "Supplier Ltd",
"supplierVatId": "123456789"
}
BODY;
$ch = curl_init('https://<partner_domain>.keep.co.il/api/public/expenses/<expenseId>');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PATCH',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Authorization: Bearer <YOUR_TOKEN>',
],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
Responses
200 — Expense updated successfully (success)
| Field |
Type |
Description |
payload |
object |
|
payload.id |
string |
Expense UUID |
payload.sellerId |
string |
Seller UUID |
payload.valueDate |
string |
Expense value date |
payload.totalAmount |
number |
Total expense amount |
payload.vatAmount |
number |
VAT amount |
payload.currency |
string |
Currency code |
payload.docType |
string |
Document type |
payload.docRegulationId |
string |
Document regulation ID |
payload.classification |
integer |
Classification ID |
payload.capturedDate |
string |
Timestamp when expense was captured |
{
"payload": {
"id": "edc855f7-cb7c-4d82-8c26-baf5c296d391",
"sellerId": "a6a9700f-8571-4f9b-bfae-ba943fb96982",
"valueDate": "2025-10-28T00:00:00.000Z",
"totalAmount": 15000,
"vatAmount": 2288,
"currency": "ILS",
"docType": "invrec",
"docRegulationId": "5132277",
"classification": 6,
"capturedDate": "2025-10-28T09:13:37.423Z"
}
}
400 — Validation error, and the message Bad identifier when the expense does not exist. (error)
| Field |
Type |
Description |
statusCode |
integer |
HTTP status code |
message |
string |
Error message(s) |
error |
string |
Error type |
{
"statusCode": 400,
"message": [
"Validation failed"
],
"error": "Bad Request"
}
401 — Unauthorized (error)
| Field |
Type |
Description |
statusCode |
integer |
|
message |
string |
|
{
"statusCode": 401,
"message": "Unauthorized"
}
403 — Partner is not authorized to update this expense (error)
| Field |
Type |
Description |
statusCode |
integer |
HTTP status code |
message |
string |
Error message(s) |
422 — Unprocessable Entity. Messages: Only expenses with pending status can be updated, Could not resolve seller, Provided supplier ID is invalid, Invalid classification. (error)
| Field |
Type |
Description |
statusCode |
integer |
HTTP status code |
message |
string |
Error message(s) |
error |
string |
Error type |
429 — Rate limit exceeded (error)