Retainers
Standing arrangements that issue the same document on a schedule — a monthly invoice, a fortnightly bill. An INVOICE_RECEIPT retainer also charges a saved card on each run.
Use cases: Use this for subscriptions and ongoing fees: define the document once, and let each cycle issue it (and collect it) on its own.
GET
/retainersList retainers.
**Not paginated** — every retainer comes back, newest first, and `limit`/`offset`/`page` are ignored. Deleted retainers are excluded. `chargeFailureCount` and `lastChargeError` are how you spot a saved card that has started declining.
Request
curl -X GET "https://api.glance.co.il/retainers" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json"Response
Response
{
"success": true,
"data": [
{
"id": 1,
"type": "INVOICE",
"description": "ריטיינר חודשי",
"entityId": 7742,
"amount": 2000,
"tax": 360,
"totalWithTax": 2360,
"intervalDays": null,
"scheduleDay": 1,
"nextRunDate": "2026-09-01T00:00:00.000Z",
"endDate": null,
"maxRuns": null,
"runsCount": 7,
"ignoredDaysOfWeek": [],
"isActive": true,
"paymentTokenId": null,
"chargeAmount": null,
"chargeFailureCount": 0,
"lastChargeError": null,
"lastChargeAt": null,
"prorateFirstRun": false,
"creationDate": "2026-02-01T09:00:00.000Z",
"client": {
"id": 7742,
"name": "אלקבץ בע״מ",
"address": null,
"logoFile": null
}
}
]
}GET
/retainers/:idGet a single retainer.
404 RETAINER_NOT_FOUND when the id is unknown. `raw` holds the document body each run is issued from.
Path Parameters
| Name | Type | Description | |
|---|---|---|---|
id | number | required | The retainer's numeric id. |
Request
curl -X GET "https://api.glance.co.il/retainers/:id" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json"Response
Response
{
"success": true,
"data": {
"id": 1,
"type": "INVOICE",
"entityId": 7742,
"amount": 2000,
"tax": 360,
"totalWithTax": 2360,
"raw": {
"…": "the document template this retainer issues"
},
"scheduleDay": 1,
"nextRunDate": "2026-09-01T00:00:00.000Z",
"runsCount": 7,
"isActive": true,
"client": {
"id": 7742,
"name": "אלקבץ בע״מ"
}
}
}POST
/retainers/createCreate a retainer.
`firstRun` is present only when `runFirstNow` was set. A `documentError` alongside `issued: true` means the money moved but the PDF did not come out — the request is not a failure and must not be retried, since a retry would charge the client twice.
`POST /retainers/preview` takes the same body and returns the first document as a PDF (`Content-Type: application/pdf`) without saving anything.
Body Parameters
| Name | Type | Description | |
|---|---|---|---|
type | string | required | "BILL", "INVOICE" or "INVOICE_RECEIPT". An INVOICE_RECEIPT asserts that payment was received, so it may only be created against a saved card — `paymentTokenId` and `chargeAmount` are then both required. |
clientId | number | required | The client's numeric entity id. |
products | object[] | required | The line items each issued document carries. Same shape as the line items on `POST /documents/create/{type}`. At least one is required. |
intervalDays | number | Run every N days. Either this or `scheduleDay` is required — a retainer with neither is rejected. | |
scheduleDay | number | Run monthly on this day of the month, 1–31. A month shorter than the chosen day runs on its last day. | |
endDate | string | Stop running after this date (YYYY-MM-DD). | |
maxRuns | number | Stop after this many documents. Omit for unlimited. | |
ignoredDaysOfWeek | number[] | Weekdays to skip, 0 (Sunday) to 6 (Saturday). A run landing on one moves off it. | |
firstRunDate | string | When the first run happens (YYYY-MM-DD). Every run after it follows the cadence. Omitted, the first run is derived from `date`. | |
runFirstNow | boolean | Issue — and, for an INVOICE_RECEIPT, charge — the first document as part of this request, rather than waiting for the nightly run. The first run date is then today, whatever `firstRunDate` says. | |
prorateFirstRun | boolean | Charge only the remainder of the current cycle on the first run, so every run after it lands on `scheduleDay`. Monthly schedules only. Left off while `scheduleDay` differs from the first run's own day, the first run comes out in full and the rest still align to `scheduleDay`. | |
paymentTokenId | number | The saved card to charge on every run. See the Saved Cards section. | |
chargeAmount | number | The full per-run total including VAT. For an INVOICE_RECEIPT this is what the card is charged; for every other type it is the base a pro-rated first run takes its fraction of. Frozen at creation — what the client is charged must equal what the document says. | |
title | string | Document title. | |
payBy | string | Due date on the issued document (YYYY-MM-DD). | |
date | string | Document date (YYYY-MM-DD). Also where the first run is derived from when `firstRunDate` is not given. | |
currencyCode | string | Three-letter document currency. | |
tax | number | VAT rate override. | |
discount | number | Document-level discount. | |
discountType | string | "absolute" or "percents". | |
taxMode | string | "beforeTax" or "includeTax". | |
notes | string | Notes printed on every issued document. | |
textAboveProducts | string | Free text printed above the line items. | |
withSignature | string[] | Signature blocks to print: "company", "client". | |
signatureFileId | number | Id of an uploaded signature image. | |
producerType | string[] | Who is credited as producer: "user", "platform". | |
relatedDocuments | object[] | Documents each issued document draws from, as `{ id, amount, products }`. | |
skipInventoryActions | boolean | Issue without moving stock. Defaults to false. | |
sendToClient | boolean | Email each issued document to the client. Defaults to false. | |
emailRecipients | string[] | Extra email recipients. |
Request
curl -X POST "https://api.glance.co.il/retainers/create" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "example_type",
"clientId": 0,
"products": "example_products",
"intervalDays": 0,
"scheduleDay": 0,
"endDate": "example_endDate",
"maxRuns": 0,
"ignoredDaysOfWeek": "example_ignoredDaysOfWeek",
"firstRunDate": "example_firstRunDate",
"runFirstNow": true,
"prorateFirstRun": true,
"paymentTokenId": 0,
"chargeAmount": 0,
"title": "example_title",
"payBy": "example_payBy",
"date": "example_date",
"currencyCode": "example_currencyCode",
"tax": 0,
"discount": 0,
"discountType": "example_discountType",
"taxMode": "example_taxMode",
"notes": "example_notes",
"textAboveProducts": "example_textAboveProducts",
"withSignature": "example_withSignature",
"signatureFileId": 0,
"producerType": "example_producerType",
"relatedDocuments": "example_relatedDocuments",
"skipInventoryActions": true,
"sendToClient": true,
"emailRecipients": "example_emailRecipients"
}'Response
Response
{
"success": true,
"retainerId": 1,
"retainer": {
"…": "the created retainer row"
},
"firstRun": {
"issued": true,
"documentId": 84995,
"documentError": null
}
}PUT
/retainers/:idUpdate a retainer, including its card and charge amount. All fields are optional.
**Omitting a field means "leave it as it is", so `null` is the only way to remove a value.** It clears `intervalDays`, `scheduleDay`, `endDate`, `maxRuns`, `paymentTokenId` and `chargeAmount`; on every other field `null` is rejected. 400 RETAINER_SCHEDULE_REQUIRED when the update would leave the retainer with neither `intervalDays` nor `scheduleDay` — the check is against the row's resulting state, so clearing the only cadence that is set is refused even when the body names just that one field. `nextRunDate` is not recalculated here — it is set at creation and advanced by each run, so changing the cadence takes effect from the run after next. `PUT /retainers/edit/:id` is a narrower variant of the same update that does not touch the saved card or the charge amount; it takes the same scheduling fields with the same `null` semantics.
Path Parameters
| Name | Type | Description | |
|---|---|---|---|
id | number | required | The retainer's numeric id. |
Body Parameters
| Name | Type | Description | |
|---|---|---|---|
type | string | "BILL", "INVOICE" or "INVOICE_RECEIPT". | |
clientId | number | The client's numeric entity id. | |
products | object[] | Replacement line items. Sending this replaces the whole list. | |
paymentTokenId | number | The saved card to charge. `null` detaches the card and stops charging. | |
chargeAmount | number | Per-run total including VAT. `null` clears it. | |
isActive | boolean | Pause or resume the retainer. | |
intervalDays | number | Run every N days. `null` clears it — that is how you move a retainer off an interval and onto a monthly day, and the switch does nothing without it. Either this or `scheduleDay` must survive the update; clearing both is rejected. | |
scheduleDay | number | Run monthly on this day of the month, 1–31. A month shorter than the chosen day runs on its last day. `null` clears it — that is how you move back to an interval, and the switch does nothing without it, because a retainer that has both runs on `scheduleDay`. | |
endDate | string | Stop running after this date (YYYY-MM-DD). `null` removes the end date and the retainer runs indefinitely again; omitting it leaves whatever is on the row. | |
maxRuns | number | Stop after this many documents. `null` removes the limit; omitting it leaves whatever is on the row — unlike on create, where omitting means unlimited. | |
ignoredDaysOfWeek | number[] | Weekdays to skip, 0 (Sunday) to 6 (Saturday). A run landing on one moves off it. | |
title | string | Document title. | |
payBy | string | Due date on the issued document (YYYY-MM-DD). | |
date | string | Document date (YYYY-MM-DD). Also where the first run is derived from when `firstRunDate` is not given. | |
currencyCode | string | Three-letter document currency. | |
tax | number | VAT rate override. | |
discount | number | Document-level discount. | |
discountType | string | "absolute" or "percents". | |
taxMode | string | "beforeTax" or "includeTax". | |
notes | string | Notes printed on every issued document. | |
textAboveProducts | string | Free text printed above the line items. | |
withSignature | string[] | Signature blocks to print: "company", "client". | |
signatureFileId | number | Id of an uploaded signature image. | |
producerType | string[] | Who is credited as producer: "user", "platform". | |
relatedDocuments | object[] | Documents each issued document draws from, as `{ id, amount, products }`. | |
skipInventoryActions | boolean | Issue without moving stock. Defaults to false. | |
sendToClient | boolean | Email each issued document to the client. Defaults to false. | |
emailRecipients | string[] | Extra email recipients. |
Request
curl -X PUT "https://api.glance.co.il/retainers/:id" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "example_type",
"clientId": 0,
"products": "example_products",
"paymentTokenId": 0,
"chargeAmount": 0,
"isActive": true,
"intervalDays": 0,
"scheduleDay": 0,
"endDate": "example_endDate",
"maxRuns": 0,
"ignoredDaysOfWeek": "example_ignoredDaysOfWeek",
"title": "example_title",
"payBy": "example_payBy",
"date": "example_date",
"currencyCode": "example_currencyCode",
"tax": 0,
"discount": 0,
"discountType": "example_discountType",
"taxMode": "example_taxMode",
"notes": "example_notes",
"textAboveProducts": "example_textAboveProducts",
"withSignature": "example_withSignature",
"signatureFileId": 0,
"producerType": "example_producerType",
"relatedDocuments": "example_relatedDocuments",
"skipInventoryActions": true,
"sendToClient": true,
"emailRecipients": "example_emailRecipients"
}'Response
Response
{
"success": true,
"data": {
"…": "the updated retainer row"
}
}DELETE
/retainers/:idDeactivate a retainer, or delete an already-inactive one.
Call it twice to remove a retainer: the first call on an active retainer only deactivates it (`isActive: false`), and a second call then deletes it. The message tells you which happened. Deleting is a soft delete — the row keeps its history and drops out of `GET /retainers`.
Path Parameters
| Name | Type | Description | |
|---|---|---|---|
id | number | required | The retainer's numeric id. |
Request
curl -X DELETE "https://api.glance.co.il/retainers/:id" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json"Response
Response
{
"success": true,
"message": "Retainer deactivated successfully"
}POST
/retainers/reactivate/:idReactivate a deactivated retainer.
A retainer that is already active answers 400 RETAINER_ALREADY_ACTIVE.
Path Parameters
| Name | Type | Description | |
|---|---|---|---|
id | number | required | The retainer's numeric id. |
Request
curl -X POST "https://api.glance.co.il/retainers/reactivate/:id" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json"Response
Response
{
"success": true,
"message": "Retainer reactivated successfully"
}GET
/retainers/:id/one-time-itemsList the one-off charges queued on a retainer — an extra that rides along on one billing cycle without changing the recurring amount.
Returns APPLIED and CANCELLED items too, on purpose: an applied item is the explanation for why one document differs from the rest, and a cancelled one is the record that somebody decided to drop it.
Path Parameters
| Name | Type | Description | |
|---|---|---|---|
id | number | required | The retainer ID. |
Request
curl -X GET "https://api.glance.co.il/retainers/:id/one-time-items" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json"Response
Response
{
"success": true,
"items": [
{
"id": 71,
"retainerId": 1,
"recurringPaymentId": null,
"description": "התקנה חד-פעמית",
"units": 1,
"price": 450,
"productId": null,
"applyOn": null,
"status": "PENDING",
"createdBy": 12
}
]
}POST
/retainers/:id/one-time-itemsQueue a one-off charge onto a retainer's next document.
An item is marked APPLIED only after the document is issued. If the charge or the issue fails, it stays PENDING and rides on the next cycle instead of disappearing silently.
Path Parameters
| Name | Type | Description | |
|---|---|---|---|
id | number | required | The retainer ID. |
Body Parameters
| Name | Type | Description | |
|---|---|---|---|
description | string | required | Line description, as it will be printed. |
units | number | Quantity. Must be positive. Defaults to 1. | |
price | number | required | Price per unit. |
productId | number | Optional catalogue product to link the line to. | |
applyOn | string | ISO 8601 timestamp of the cycle this item is meant for. Empty means the next cycle; a future date keeps it waiting until that cycle comes round. |
Request
curl -X POST "https://api.glance.co.il/retainers/:id/one-time-items" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"description": "example_description",
"units": 0,
"price": 0,
"productId": 0,
"applyOn": "example_applyOn"
}'Response
Response
{
"success": true,
"id": 71
}PUT
/retainers/:id/one-time-items/:itemIdEdit a queued one-off charge.
Only a PENDING item can be edited. Once it has gone out on a document, editing returns 400 INVALID_STATUS — the document was issued and possibly paid, so changing the line here would rewrite history without changing anything real.
Path Parameters
| Name | Type | Description | |
|---|---|---|---|
id | number | required | The retainer ID. |
itemId | number | required | The one-time item ID. |
Body Parameters
| Name | Type | Description | |
|---|---|---|---|
description | string | Line description. | |
units | number | Quantity. | |
price | number | Price per unit. | |
productId | number | Linked product, or null to unlink. | |
applyOn | string | Target cycle, or null for the next one. |
Request
curl -X PUT "https://api.glance.co.il/retainers/:id/one-time-items/:itemId" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"description": "example_description",
"units": 0,
"price": 0,
"productId": 0,
"applyOn": "example_applyOn"
}'Response
Response
{
"success": true
}DELETE
/retainers/:id/one-time-items/:itemIdCancel a queued one-off charge.
Cancels rather than deletes — the row stays, with status CANCELLED, so the decision is visible on the retainer screen. An item already APPLIED cannot be cancelled (400 INVALID_STATUS): credit the document instead. The same four routes exist under /grow/recurring-payments/:id/one-time-items for standing orders.
Path Parameters
| Name | Type | Description | |
|---|---|---|---|
id | number | required | The retainer ID. |
itemId | number | required | The one-time item ID. |
Request
curl -X DELETE "https://api.glance.co.il/retainers/:id/one-time-items/:itemId" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json"Response
Response
{
"success": true
}