Clients

Manage your client records. Clients can be individuals (MURSHE), companies (COMPANY), or exempt dealers (PATOOR).

Use cases: Use the Clients API to sync your CRM contacts, create clients before issuing invoices, or look up balances.
GET/clients

List all clients with optional filtering and pagination.

Each client carries `balance` (negative = the client owes you) and `uninvoiced`: the open orders and delivery notes not yet invoiced, by document status — `count` documents for `amount` in total. What the client owes plus what is not yet invoiced is the exposure the client card measures against the credit limit: `uninvoiced.amount - balance`. `expectedBalance` is still returned for existing integrations but should not be relied on (see GET /clients/id/:visibleId). `sortBy` takes `id`, `name`, `email`, `taxId`, `type` or `debt`. `debt` sorts by the same debt the filters use, computed on the server, so the order holds across pages. An invalid `groupId`, `customFieldId`, `debtStatus`, `minDebt`, `ids` or `leads` returns 400 `INVALID_FIELD` instead of being ignored. `GET /clients/inactive` takes the same parameters and returns clients that have been deactivated. Reading clients — this list, GET /clients/id/:visibleId, GET /clients/entity/:entityId and its addresses — needs the `viewer` role or the `clients.view` action role.

Query Parameters

NameTypeDescription
search
stringFree-text search across relevant fields.
type
stringClient type filter. One of "MURSHE", "COMPANY", or "PATOOR".
email
stringFilter by email — a substring match, so `acme.com` finds every address at that domain. Use `exactEmail` to find one customer.
exactEmail
stringFilter by one exact email address. Surrounding spaces are ignored and the comparison is case-insensitive, so `Dana@Example.com ` finds `dana@example.com` — and never `adana@example.com`.
phone
stringFilter by phone number. Only the digits are compared, so `050-123 4567` finds `0501234567`, and an Israeli number matches in both its local (`05x…`) and international (`9725x…`) form.
taxId
stringFilter by tax ID.
hasContacts
booleanIf true, return only clients that have contacts.
groupId
numberOnly clients in this customer group.
customFieldId
numberOnly clients with a value in this custom field. Add `customFieldValue` to narrow it.
customFieldValue
stringWith `customFieldId`: only clients whose value contains this text. Without it, any non-empty value matches.
debtStatus
string"owes" (the client owes you), "credit" (you owe the client) or "settled" (zero). The debt is the one the list shows: what the client owes on documents and on external income invoices.
minDebt
numberOnly clients whose debt is at least this amount.
ids
stringComma-separated numeric client ids, up to 2,000 — only these clients, e.g. the rows selected on a list.
leads
string"exclude" or "only". With the CRM module, a client card on an open or lost stage of the leads board is a lead. Omitted, the list includes leads, as before.
sortBy
stringColumn to sort by.
sortOrder
string"asc" or "desc".
limit
numberItems per page. Default 50, clamped to 1-200.
offset
numberRow offset to start from (default 0).
page
number1-based page number (default 1). Converted to an offset; an explicit `offset` wins over it.
pageSize
numberAlias of `limit`. Wins over `limit` when both are sent.

Request

curl -X GET "https://api.glance.co.il/clients" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json"

Response

Response
{
  "data": [
    {
      "id": 5531,
      "visibleId": "7c1a9e40-2b3d-4f8a-9c6e-1d5b7a3f2e08",
      "name": "Acme Corp",
      "taxId": "515000000",
      "email": "info@acme.com",
      "phoneNumber": "03-5550000",
      "type": "COMPANY",
      "clientInternalCode": 104,
      "balance": -5000,
      "expectedBalance": 0,
      "uninvoiced": {
        "count": 2,
        "amount": 1180
      },
      "contacts": []
    }
  ],
  "pagination": {
    "total": 42,
    "limit": 50,
    "offset": 0,
    "hasMore": false,
    "page": 1,
    "pageSize": 50,
    "totalPages": 1
  }
}
GET/clients/export

The clients list as an Excel file, with the same filters and sorting as GET /clients.

Takes every filter GET /clients takes (`type`, `email`, `groupId`, `debtStatus`, `ids`, …), with no pagination. Columns: client code, name, type, tax id, email, phone, customer groups and debt. Sorted by name unless `sortBy` says otherwise. Up to 20,000 rows. Needs the `viewer` role or the `clients.view` action role.

Query Parameters

NameTypeDescription
search
stringFree-text search across relevant fields.
sortBy
stringColumn to sort by.
sortOrder
string"asc" or "desc".

Request

curl -X GET "https://api.glance.co.il/clients/export" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json"

Response

Response
(binary — an .xlsx file, with Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet)
GET/clients/duplicates

Existing clients that look like the one you are about to create — check before opening a second card for the same party.

Returns up to 5 clients, strongest match first: tax id, then phone or email, then name. `matchedOn` names the values each card shares with what you sent. Inactive clients are included, with `isActive: false`; cards merged into another are not. With no usable value, `data` is empty. Needs the `viewer` role or the `clients.view` action role.

Query Parameters

NameTypeDescription
taxId
stringMatched by digits only, so `51-500000-0` finds `515000000`. Ignored below 5 digits.
phoneNumber
stringMatched as an Israeli number, so `054-1234567` and `+972 54 1234567` are the same. Ignored below 8 digits.
email
stringExact match, ignoring case and surrounding spaces.
name
stringExact match, ignoring case and extra spaces. Ignored below 2 characters.
exclude
stringA client visibleId to leave out — the card being edited.

Request

curl -X GET "https://api.glance.co.il/clients/duplicates" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json"

Response

Response
{
  "data": [
    {
      "visibleId": "7c1a9e40-2b3d-4f8a-9c6e-1d5b7a3f2e08",
      "name": "Acme Corp",
      "taxId": "515000000",
      "phoneNumber": "054-1234567",
      "email": "info@acme.com",
      "isActive": true,
      "matchedOn": [
        "taxId",
        "phoneNumber"
      ]
    }
  ]
}
GET/clients/id/:visibleId

Get a single client with contacts, addresses, balance and what makes it up.

The client is returned flat, not wrapped in `data`. A visibleId that matches nothing returns `null` with status 200 — check for it rather than relying on a 404. **Client and vendor.** `isVendor` is true when the same card is also one of your vendors (same `visibleId` on GET /vendors/id/:visibleId), and `vendorPayable` is what you owe it as a vendor — positive = you owe. Both are `false` / `null` for a client that is only a client. Add the vendor role with POST /clients/id/:visibleId/vendor-role. **Merged cards.** A card merged into another (POST /clients/merge) is inactive and carries `mergedIntoId`. `GET /clients/id/:visibleId/merged-into` returns `{ visibleId, name }` of the card it now lives in, following later merges, or `null` when it was not merged. **What the client owes.** `balance` is the debt: invoices minus receipts and credit notes, negative = the client owes you; it equals the last `runningBalance` of GET /clients/id/:visibleId/statement (with the sign flipped). `openDocuments` lists what is still open by document status — `unpaidInvoices`, `unallocatedReceipts`, and `openOrders` / `openDeliveries`, the work not yet invoiced. Exposure against the credit limit is `-balance + openDocuments.openOrders.amount + openDocuments.openDeliveries.amount`. `expectedBalance` and `obligationBreakdown` are an older operational ledger and are kept for existing integrations only: an invoice issued from an order used to release its own full total there, so for a client invoiced above the order amount they show an expected credit that does not exist. Read open orders and delivery notes from `openDocuments` instead. `GET /clients/entity/:entityId` takes the internal numeric id instead and is deliberately lighter: it returns `id`, `visibleId`, `name`, `phoneNumber`, `email`, `balance`, `expectedBalance`, `creditLimit`, `specialVat`, `roundDocumentTotal`, `documentEmailOverrides`, `currencyPolicyJson`, `addresses`, `totalObligation` and `exceedsCredit` — no contacts, `obligationBreakdown` or `openDocuments`. `totalObligation` is the debt plus the open orders and delivery notes not yet invoiced, and `exceedsCredit` compares it with `creditLimit`. When the company has `overdueBlockDays` set, it also returns `overdueBlockDays`, `overdueBlocked`, `overdueAmount` and `maxDaysOverdue`. A non-numeric id returns 400 `INVALID_FIELD`; an id that matches no client returns `null` with status 200.

Path Parameters

NameTypeDescription
visibleId
stringrequiredThe client's visibleId (UUID).

Request

curl -X GET "https://api.glance.co.il/clients/id/:visibleId" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json"

Response

Response
{
  "id": 5531,
  "visibleId": "7c1a9e40-2b3d-4f8a-9c6e-1d5b7a3f2e08",
  "name": "Acme Corp",
  "taxId": "515000000",
  "email": "info@acme.com",
  "phoneNumber": "03-5550000",
  "type": "COMPANY",
  "clientInternalCode": 104,
  "paymentTermType": "CURRENT_PLUS_DAYS",
  "paymentTermDays": 30,
  "address": {
    "id": 88,
    "city": "תל אביב",
    "street": "הרצל",
    "streetNumber": "12"
  },
  "addresses": [
    {
      "id": 88,
      "isPrimary": true,
      "city": "תל אביב"
    }
  ],
  "contacts": [
    {
      "id": 71,
      "firstName": "Efi",
      "lastName": "Levi",
      "email": "efi@acme.com"
    }
  ],
  "logoFile": null,
  "balance": -5000,
  "expectedBalance": -1180,
  "obligationBreakdown": {
    "…": "what the balance is made of"
  },
  "openDocuments": {
    "…": "the open documents behind it"
  },
  "isVendor": true,
  "vendorPayable": 1180
}
GET/clients/id/:visibleId/statement

The client's statement (כרטסת): every document issued to the client, oldest first, with its debit or credit and a running balance.

`debit` raises what the client owes and `credit` lowers it; both are always ≥ 0, and `runningBalance` / `finalBalance` are positive when the client owes you — `finalBalance` equals `-balance` on GET /clients/id/:visibleId. Operational documents (quotations, orders, delivery notes, returns) are listed with their `status` but `financial: false` and no debit or credit, since they do not change the debt. Manual balance adjustments appear as `kind: "MANUAL"` rows with a `manual:<id>` key. `status` is one of `OPEN`, `PARTIALLY_PAID`, `CLOSED`, `REFUNDED`, `CANCELLED`. `issue` flags a financial document whose balance entries do not match it: `MISSING` (no entry at all), `DUPLICATE` (the same entry twice) or `AMOUNT` (entries net to a different amount than the document); `issues` counts them. `checksEnabled` is false for a company that does not record client balances (an exempt dealer outside full double-entry) — `issue` is then always null. A visibleId that matches no client returns `null` with status 200.

Path Parameters

NameTypeDescription
visibleId
stringrequiredThe client's visibleId (UUID).

Request

curl -X GET "https://api.glance.co.il/clients/id/:visibleId/statement" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json"

Response

Response
{
  "rows": [
    {
      "key": "doc:90211",
      "date": "2026-09-02T09:14:00.000Z",
      "kind": "DOCUMENT",
      "documentId": 90211,
      "documentVisibleId": "b2e7c4a1-0d3f-4e9b-8a6c-5f1d2e3a4b5c",
      "documentType": "INVOICE",
      "documentTypeLabel": "חשבונית מס",
      "documentNumber": 150162,
      "description": "ריטיינר ספטמבר",
      "total": 7847,
      "currencyCode": "ILS",
      "debit": 7847,
      "credit": 0,
      "runningBalance": 7847,
      "financial": true,
      "status": "OPEN",
      "isOpen": true,
      "remainingAmount": 7847,
      "cancelled": false,
      "issue": null
    },
    {
      "key": "doc:90240",
      "date": "2026-09-05T11:02:00.000Z",
      "kind": "DOCUMENT",
      "documentId": 90240,
      "documentVisibleId": "c9a1f3e2-7b4d-4c6e-9d8f-2a1b3c4d5e6f",
      "documentType": "ORDER",
      "documentTypeLabel": "הזמנה",
      "documentNumber": 3012,
      "description": null,
      "total": 590,
      "currencyCode": "ILS",
      "debit": 0,
      "credit": 0,
      "runningBalance": 7847,
      "financial": false,
      "status": "OPEN",
      "isOpen": true,
      "remainingAmount": 590,
      "cancelled": false,
      "issue": null
    }
  ],
  "finalBalance": 7847,
  "issues": 0,
  "checksEnabled": true
}
GET/clients/id/:visibleId/aging

The client's open invoices by days past their due date — the aging report for one client.

Each open invoice is bucketed by how many days past its due date (`payBy`) it is today: `current` is not yet due, then 1–30, 31–60, 61–90 and over 90 days. `debts` is oldest-overdue first. The same engine as GET /reports/aging, without needing the advanced reports plan — any `viewer` can read it for a client. A visibleId that matches no client returns `null` with status 200.

Path Parameters

NameTypeDescription
visibleId
stringrequiredThe client's visibleId (UUID).

Request

curl -X GET "https://api.glance.co.il/clients/id/:visibleId/aging" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json"

Response

Response
{
  "asOfDate": "2026-10-15T20:59:59.999Z",
  "currencyCode": "ILS",
  "buckets": [
    {
      "key": "current",
      "label": "שוטף"
    },
    {
      "key": "d0_30",
      "label": "0-30"
    },
    {
      "key": "d31_60",
      "label": "31-60"
    },
    {
      "key": "d61_90",
      "label": "61-90"
    },
    {
      "key": "d90_plus",
      "label": "90+"
    }
  ],
  "totals": {
    "current": 1200,
    "d0_30": 0,
    "d31_60": 7847,
    "d61_90": 0,
    "d90_plus": 0
  },
  "total": 9047,
  "debts": [
    {
      "documentVisibleId": "b2e7c4a1-0d3f-4e9b-8a6c-5f1d2e3a4b5c",
      "documentNumber": 150162,
      "documentType": "INVOICE",
      "creationDate": "2026-09-02T09:14:00.000Z",
      "payBy": "2026-09-02",
      "remainingAmount": 7847,
      "daysOverdue": 43,
      "bucket": "d31_60"
    }
  ]
}
POST/clients/create

Create a new client.

The response acknowledges the creation; it does not echo the client. Read it back with GET /clients/id/:visibleId using the `visibleId` returned here.

Body Parameters

NameTypeDescription
name
stringrequiredClient name.
taxId
stringTax ID / company number. Optional for a client (unlike a vendor, where it is required).
email
stringClient email address.
phoneNumber
stringPhone number, up to 20 characters.
type
stringClient type: "MURSHE" (licensed dealer), "COMPANY", or "PATOOR" (exempt dealer).
addressId
numberId of an existing address to attach.
logoFileId
numberId of an uploaded file to use as the client's logo.
paymentTermType
string"CURRENT_PLUS_DAYS" (end of month plus N days) or "DAYS_ONLY" (N days from the document date).
paymentTermDays
numberThe N in the payment term. Zero or more.
bankNumber
stringBank code, up to 20 characters.
branchNumber
stringBranch number, up to 20 characters.
accountNumber
stringAccount number, up to 50 characters.
existingContactId
numberAttach a contact that already exists instead of creating one.
contact
objectCreate a contact along with the client. Only accepted here — the edit endpoint does not take it; use the Contacts API afterwards.
firstName
stringrequiredContact first name.
lastName
stringContact last name.
phoneNumber
stringContact phone number.
email
stringContact email.
addressId
numberAddress to attach to the contact.
hashavshevetEntityAccountKey
stringExternal bookkeeping account key, up to 8 characters. Saved only for users permitted to map accounting exports. This is the *external* key — distinct from `clientInternalCode`, the running number Glance assigns.
documentEmailOverrides
objectPer-document-type email recipients, e.g. send delivery notes to the warehouse and invoices to accounts payable.
asLead
booleanOpen the card as a lead, on the first open stage of the leads board. Only with the CRM module; ignored without it. No `client.created` webhook goes out for a lead until it becomes a client.

Request

curl -X POST "https://api.glance.co.il/clients/create" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "example_name",
  "taxId": "example_taxId",
  "email": "example_email",
  "phoneNumber": "example_phoneNumber",
  "type": "example_type",
  "addressId": 0,
  "logoFileId": 0,
  "paymentTermType": "example_paymentTermType",
  "paymentTermDays": 0,
  "bankNumber": "example_bankNumber",
  "branchNumber": "example_branchNumber",
  "accountNumber": "example_accountNumber",
  "existingContactId": 0,
  "contact": {},
  "hashavshevetEntityAccountKey": "example_hashavshevetEntityAccountKey",
  "documentEmailOverrides": {},
  "asLead": true
}'

Response

Response
{
  "success": true,
  "clientId": 5531,
  "id": 5531,
  "visibleId": "7c1a9e40-2b3d-4f8a-9c6e-1d5b7a3f2e08"
}
PUT/clients/edit/:visibleId

Update an existing client. All fields are optional.

There is no `contact` field here — contacts are created with the client or through the Contacts API. `PUT /clients/deactivate/:visibleId` and `PUT /clients/reactivate/:visibleId` take a client out of the active list and back.

Path Parameters

NameTypeDescription
visibleId
stringrequiredThe client's visibleId.

Body Parameters

NameTypeDescription
name
stringClient name.
taxId
stringTax ID.
email
stringEmail address.
phoneNumber
stringPhone number, up to 20 characters.
type
string"MURSHE", "COMPANY", or "PATOOR".
addressId
numberAddress to attach; `null` detaches it.
logoFileId
numberFile id to use as the client's logo.
paymentTermType
string"CURRENT_PLUS_DAYS" or "DAYS_ONLY"; `null` clears the term and falls back to the company default.
paymentTermDays
numberDays for the payment term; `null` clears it.
bankNumber
stringBank code.
branchNumber
stringBranch number.
accountNumber
stringAccount number.
creditLimit
numberCredit limit for this client; `null` removes it.
specialVat
numberA VAT rate for this client only, 0-100. `null` restores the company rate.
roundDocumentTotal
string"use_default", "round" or "none" — whether documents for this client round to whole shekels.
clientInternalCode
number | stringOverride the running internal client code. `null` or an empty string clears it; omit to leave it as it is.
accountingCustomerNumber
stringCustomer number in your accounting system.
taxDeductionsFileNumber
stringWithholding-tax file number.
hashavshevetEntityAccountKey
stringExternal bookkeeping account key. An empty string leaves it unchanged rather than clearing it.
documentEmailOverrides
objectPer-document-type email recipients. `null` clears them.
currencyPolicyJson
objectPer-currency exchange-rate policy for this client. A currency absent from the map inherits the company policy; `null` removes the override entirely.
balance
numberSet the client's balance directly. An accounting correction, not an ordinary update — the balance is otherwise derived from documents.
expectedBalance
numberSet the client's expected balance (what they still owe once open orders and delivery notes turn into invoices) directly. Like `balance`, a correction: the difference is written as an opening-balance transaction, and only when it exceeds an agora.

Request

curl -X PUT "https://api.glance.co.il/clients/edit/:visibleId" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "example_name",
  "taxId": "example_taxId",
  "email": "example_email",
  "phoneNumber": "example_phoneNumber",
  "type": "example_type",
  "addressId": 0,
  "logoFileId": 0,
  "paymentTermType": "example_paymentTermType",
  "paymentTermDays": 0,
  "bankNumber": "example_bankNumber",
  "branchNumber": "example_branchNumber",
  "accountNumber": "example_accountNumber",
  "creditLimit": 0,
  "specialVat": 0,
  "roundDocumentTotal": "example_roundDocumentTotal",
  "clientInternalCode": "example_clientInternalCode",
  "accountingCustomerNumber": "example_accountingCustomerNumber",
  "taxDeductionsFileNumber": "example_taxDeductionsFileNumber",
  "hashavshevetEntityAccountKey": "example_hashavshevetEntityAccountKey",
  "documentEmailOverrides": {},
  "currencyPolicyJson": {},
  "balance": 0,
  "expectedBalance": 0
}'

Response

Response
{
  "success": true,
  "visibleId": "7c1a9e40-2b3d-4f8a-9c6e-1d5b7a3f2e08"
}
POST/clients/id/:visibleId/vendor-role

Make an existing client a vendor too, so a party you both sell to and buy from has one card instead of two.

No body. The card keeps its `visibleId`, so the same id now works on GET /vendors/id/:visibleId and on purchase documents. A vendor code (קוד ספק) is assigned when the card has none. Calling it again is safe: it answers 200 with `alreadyHadRole: true`. 404 when the client does not exist in your company. The reverse is POST /vendors/id/:visibleId/client-role. A client that is also a vendor cannot be hard-deleted from the client side, since that would delete the vendor card too. Needs the `editor` role or the `vendors.create` action role (`clients.create` for the reverse).

Path Parameters

NameTypeDescription
visibleId
stringrequiredThe client's visibleId.

Request

curl -X POST "https://api.glance.co.il/clients/id/:visibleId/vendor-role" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json"

Response

Response
{
  "success": true,
  "entityId": 5531,
  "visibleId": "7c1a9e40-2b3d-4f8a-9c6e-1d5b7a3f2e08",
  "alreadyHadRole": false
}
GET/clients/merge/preview

What merging one client card into another would move — call it before POST /clients/merge.

`moves` counts the records pointing at the duplicate, by kind, with a Hebrew label. Nothing is changed. Same errors and permission as POST /clients/merge.

Query Parameters

NameTypeDescription
source
stringrequiredvisibleId of the duplicate card, the one that goes away.
target
stringrequiredvisibleId of the card that stays.

Request

curl -X GET "https://api.glance.co.il/clients/merge/preview" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json"

Response

Response
{
  "source": {
    "name": "Acme Corp",
    "taxId": null
  },
  "target": {
    "name": "Acme Corp Ltd",
    "taxId": "515000000"
  },
  "moves": [
    {
      "label": "מסמכים",
      "count": 35
    },
    {
      "label": "תנועות יתרה",
      "count": 61
    }
  ]
}
POST/clients/merge

Merge a duplicate client card into another. Everything that points at the duplicate moves to the card that stays.

Runs in one transaction. Documents, balance transactions, payments, saved cards, contacts, addresses and the rest move to the target; the target's balance is then the sum of both. Its empty tax id, email, phone or address is filled from the duplicate. The duplicate becomes inactive with `mergedIntoId` set, and old links can be resolved with GET /clients/id/:visibleId/merged-into. Documents already issued keep the details printed on them. `moved` counts what moved, by table. Subscribed webhook endpoints receive `client.merged` for the duplicate. Errors: 400 `SAME_CLIENT` (source and target are the same card), `ALREADY_MERGED` (the source was already merged), `TARGET_INACTIVE` (the target is inactive or merged), `TAX_ID_MISMATCH` (both cards have a tax id and they differ — probably two different parties), `INVALID_FIELD` (missing ids); 404 `CLIENT_NOT_FOUND` when either card is not one of your clients. Needs the `editor` role or the `clients.delete` action role.

Body Parameters

NameTypeDescription
sourceVisibleId
stringrequiredThe duplicate card, which becomes inactive.
targetVisibleId
stringrequiredThe card that stays.

Request

curl -X POST "https://api.glance.co.il/clients/merge" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "sourceVisibleId": "example_sourceVisibleId",
  "targetVisibleId": "example_targetVisibleId"
}'

Response

Response
{
  "success": true,
  "moved": {
    "documents.entityId": 35,
    "balanceTransactions.entityId": 61,
    "ledgers": 1
  }
}

Last updated