Glossary & data model
Terms
API Config Dentolize's outbound webhook system. Settings → Integrations → API Config, gated by the Company.apiEnabled flag. Each configured row is one URL plus a list of event types it should receive.
Webhook / API Config row Stored as JSON in Company.apiConfig (a Prisma Json? column — not a separate table). Each entry has { id, url, secret, apis } after this PR (type removed). apis is an array of event-type strings like "NEW_BALANCE_INVOICE".
Event type One string constant per kind of thing that can happen (NEW_PATIENT, NEW_INVOICE, NEW_PAYMENT, ..., and now NEW_BALANCE_INVOICE, NEW_BALANCE_PAYMENT). Defined once in apiTypes (packages/server/src/apis/apiConfig/mutationsApiConfig.js) and reused by both the resolvers that fire events and the payload builder that shapes them.
Balance Invoice An Invoice record with balanceInvoice: true and details: 'Balance Invoice'. Not a separate model — same Invoice table as regular invoices, distinguished by that boolean flag. Always created fully paid (paidInFull: true).
Balance Payment A Payment record tied to a Balance Invoice, same distinction pattern — same Payment table, identified by being linked to a balance invoice and (for the direct top-up path) details ending in "Balance Payment".
Patient balance / Patient.balance A running credit total on the patient record. Incremented by Add Balance and by the overpaid portion of a regular payment. Spent down when a future invoice payment is marked to draw fromBalance.
handleCallApi The function that actually sends a webhook: looks up the company's stored apiConfig, finds every row subscribed to the given event type, builds the payload via getOtherDataFromPayload, HMAC-signs it if a secret is configured, and POSTs it. Located in packages/server/src/apis/apiConfig/mutationsApiConfig.js. Failures inside it are caught and discarded — see For Quality.
getOtherDataFromPayload The single payload-shaping function (in packages/server/src/apis/apiConfig/otherAPIs.js) that converts an internal record into the JSON body sent to a webhook. Used for every event type — formerly one of three (other/nphies/zatca), now the only one.
Data model notes
Company.createdById— the user who created the company (typically the
owner). Used as the default doctor on balance invoices/payments, since there's no natural doctor for a balance top-up the way there is for a clinical appointment. Must be non-null for Add Balance or overpayment-to-balance conversion to work at all — see the edge case in For Quality.
InsurancePolicyhas nonamefield — the display name for a policy is
holderName. This tripped up the webhook payload builder before this PR (see Payload accuracy fixes) and is worth remembering anywhere else InsurancePolicy data is surfaced.
Invoice.referenceId/Paymentreference numbers are assigned
post-creation via updateInvoiceReferenceId / updateTransactionReferenceId (packages/server/src/utils/queryUtils.js), not at insert time — which is why it's possible (and, before this PR, was a bug) to assign the returned reference number onto the wrong in-memory object.