Skip to main content
A Partner is any counterparty on your books: a customer, a supplier, an employee, or a tax authority. Partners are referenced from Invoices, Ledger Lines with Open Items, and Bank Movement matches. This page covers Partner CRUD, the paginated Partner listing, Partner options for pickers, the Organization’s Partners, Aliases, merging duplicate Partners, Bank Details, and Booking Templates. Amounts are integers in the minor units of the Entity’s functional currency. Timestamps are ISO 8601.
Entities with Books. When the Entity has at least one Book, GET /partners/pages requires a bookId query parameter — the openReceivable and openPayable totals on the page rows are then computed inside that Book. GET /partners and the Partner rows returned by create, update, and delete stay outside the rule and surface open totals across every Book. GET /partners/counts, GET /partners/options, and GET /partners/:partnerId carry no open totals and take no bookId.
Open in the app. This resource has a page in the Sintropix web app at https://app.sintropix.com/{entityId}/partner-ledger?partners={partnerId}, where each id in braces is the same UUID as in the API route or response. Partners have no detail page; that link is the statement filtered to the Partner. The customer and supplier lists are /{entityId}/partners and /{entityId}/vendors. When you mention a record to a user, include that link. See Link to the App for the full URL grammar.

Partners belong to the Organization

A Partner belongs to the Organization, not to one Entity. One real-world party is one Partner, whichever Entities of the Organization deal with it. An Entity starts using a Partner when something names it in that Entity: a create, an Invoice, a Ledger Line, a Bank Movement, a Payment Order, or a sync. You can also use an existing Partner explicitly. The routes under /api/entities/:entityId/partners serve the Partners that Entity uses. A Partner the Entity doesn’t use answers 404. What a change reaches depends on the field: For example, when one Entity corrects a supplier’s legal name, every other Entity sees the new name. When it sets a Default Purchase Account for that supplier, the other Entities keep their own.

Roles

A Partner has no type. Whether an Entity buys from a Partner or sells to it is read from that Entity’s books, so the same Partner can be a supplier of one Entity and a customer of another. The roles field of a Partner row lists what this Entity’s books say: A Partner can have both roles, or none. In the app, Contactos filters by Relación (Proveedor or Cliente).

Representing Partners

Each Entity is represented by one Partner of its Organization. That Partner carries the Entity’s tax identity (country and taxId), and its representsEntityId is the Entity’s id. Sintropix creates it with the Entity. The other Entities of the Organization use it to name that Entity as their counterparty, for example for what they owe each other.
  • An Entity never uses the Partner that represents it. A write that names it in that Entity is refused with 422 and PARTNER_REPRESENTS_ENTITY_ERROR, with params.partnerId and params.entityId. This applies to creating or using the Partner, and to naming it on a Ledger Line, an Invoice, a Bank Movement, or a Payment Order.
  • A bank feed lands a Movement whose counterparty is the Entity itself with no Partner. A Source Feed document addressed to the Entity itself is rejected alone, with PARTNER_REPRESENTS_ENTITY_ERROR, and the rest of the sync lands.
  • Its country and taxId are the Entity’s. Correct them on the Entity. Changing them on the Partner is refused with 422 and PARTNER_REPRESENTS_ENTITY_TAX_IDENTITY_ERROR.

GET /partners

List every Partner the Entity uses, each row enriched with this Entity’s Open Item totals (unsettled AR and AP balances). The list includes Merged Partners. To keep only active Partners, drop rows where mergedIntoPartnerId is not null. Response: an array of Partner objects. An open line on the other side of the account, such as a payment on account or an open credit note, is never netted against these totals. It stays open until an Allocation applies it.

GET /partners/pages

Paginated listing of the Partners the Entity uses, for UI use. Merged Partners are never listed. Query parameters. Unknown parameters are rejected with 400. Response The page carries no counts. Read them from GET /partners/counts. Each element of partners is a Partner row: every field of the Partner object above, plus: The type of group.value depends on group.by:

GET /partners/counts

Count the Partners the Entity uses, for the tabs of a Partner listing. Merged Partners are never counted. The counts don’t depend on a search or any filter other than role, so read them once per tab, not on every page. Query parameters. Unknown parameters are rejected with 400. Response

GET /partners/options

Search the Partners the Entity uses, a short page at a time, to fill a Partner picker or filter. Each option carries only what identifies the Partner. Use it instead of GET /partners when you need to offer a choice of Partners: it reads no open totals and doesn’t return every Partner at once. It answers in one of two ways:
  • Search. Without partnerIds, it lists Partners in name order, a page at a time. A search never finds a Merged Partner.
  • By id. With partnerIds, it returns those Partners, in name order, on one page, so a field that already holds Partners can show them. Merged Partners are included. An id the Entity doesn’t use is left out. cursor, limit, and search are ignored.
Query parameters. Unknown parameters are rejected with 400. Response Show the Partner’s logo next to an option when its website is set.
In the app, the Partner pickers and Partner filters read their options this way. A picker loads more options as you scroll it. When the read fails, the picker shows the error and a button to retry.

GET /partners/:partnerId

Read one Partner the Entity uses, with this Entity’s settings for it. Use it, for example, to read the defaultPurchaseAccountId a bill booking should propose. Response: the Partner’s shared fields (id, organizationId, representsEntityId, name, legalName, country, taxId, website, aliases, mergedIntoPartnerId, createdAt, and updatedAt), plus this Entity’s entityId, defaultPurchaseAccountId, and booksAutomatically. It carries no open totals and no roles. Each field is described under GET /partners. A Partner the Entity doesn’t use answers 404 with PARTNER_NOT_FOUND_ERROR.

POST /partners

Create a Partner in the Organization and start using it in this Entity. Body. Unknown keys are rejected with 400. A country and taxId pair belongs to one Partner of the Organization:
  • When another Partner of the Organization already holds it, the create is refused with 409 and PARTNER_TAX_IDENTITY_ALREADY_EXISTS_ERROR. params.partnerId names that Partner. Use it in this Entity instead. In the app, the refusal offers Usar with the existing Partner’s name.
  • The Entity’s own tax identity belongs to its representing Partner, so it is refused with 422 and PARTNER_REPRESENTS_ENTITY_ERROR.
Response (201): the created Partner row, as GET /partners/pages would list it.
Example response:

PUT /partners/:partnerId

Use a Partner of the Organization in this Entity. Call it when a create is refused with PARTNER_TAX_IDENTITY_ALREADY_EXISTS_ERROR, or to pick a Partner another Entity already uses. Using a Partner the Entity already uses changes nothing, so you can retry safely. No request body. Response: the Partner row, as GET /partners/pages lists it.

PATCH /partners/:partnerId

Update Partner attributes. A change to name, legalName, country, taxId, website, or aliases reaches every Entity of the Organization. A change to defaultPurchaseAccountId or booksAutomatically reaches this Entity only. Body: any subset of the fields below. At least one is required; unknown keys are rejected with 400. Send null to clear a nullable field. A Merged Partner cannot be updated (409, PARTNER_MERGED_ERROR). A tax identity another Partner of the Organization holds is refused as on create. On a representing Partner, country and taxId can’t change (422, PARTNER_REPRESENTS_ENTITY_TAX_IDENTITY_ERROR). Response: { "partner": <Partner row>, "previousPartner": <Partner row> }, the row after and before the update.

DELETE /partners/:partnerId

Stop using the Partner in this Entity. Sintropix also deletes the Partner itself when no other Entity uses it and it represents no Entity. Otherwise the Partner stays for the Entities that use it. A Partner this Entity’s records still reference, such as Ledger Lines with Open Items, is refused (409, PARTNER_IN_USE_ERROR). A Merged Partner is never deleted (409, PARTNER_MERGED_ERROR). Response: the deleted Partner row, as GET /partners/pages listed it. Read the Partner’s logo: a 64 × 64 PNG that Sintropix takes from the icon of the Partner’s website. The app shows it in place of the Partner’s initial. The logo belongs to the Organization, like the Partner and its website, so this route lives under the Organization. There is no logo route under /api/entities/:entityId. Response
  • 200 with the PNG itself (Content-Type: image/png). The response carries Cache-Control: private, max-age=31536000, immutable, so a browser keeps it for up to a year. The URL stays the same when the website changes, so a cached logo can outlive it. Add the website to the URL, for example ?website=acme.cl, to fetch the new logo after a change.
  • 404 with PARTNER_LOGO_NOT_FOUND_ERROR when the Partner has no website, or its site shows no usable icon. A 404 carries no cache header. A site that could not be reached is tried again on the next request; a site that answered with no usable icon is not.

Organization Partners

GET /api/organizations/:organizationId/partners

List the Organization’s Partners in name order, each with the Entities that use it. Use it to find a Partner another Entity already uses before you create one. Merged Partners are never listed. This route lives under the Organization, not under an Entity. It needs the books read permission in the Organization. An API key confined to one Entity can call it for that Entity’s Organization; any other Organization answers 404. Query parameters. Unknown parameters are rejected with 400. Response Each element of partners has the Partner’s shared fields: id, organizationId, representsEntityId, name, legalName, country, taxId, website, aliases, mergedIntoPartnerId, createdAt, and updatedAt. It also has entities, the { id, name } of each Entity that uses the Partner, in name order. A representing Partner never lists the Entity it represents. A row carries no open totals and no per-Entity settings: read those from the Entity routes.

Aliases

An Alias is another name that finds a Partner. Use Aliases when one counterparty appears under several spellings, such as AMAZON WEB SERVICES and Amazon Web Services, Inc..
  • Two names count as the same name when they differ only in case, accents, punctuation, or spacing.
  • Each name belongs to at most one Partner per Organization. An Alias that matches another Partner’s display name or Alias is refused with 409 (PARTNER_ALIAS_TAKEN_ERROR). The error params hold the alias, plus the partnerId and partnerName of the Partner that already has it.
  • An Alias needs at least one letter or digit (400).
  • Partner search on GET /partners/pages, GET /partners/options, and in the app’s Partner pickers matches Aliases.
  • An Alias never sets a Partner on a Bank Movement.
Aliases also decide where Source Feed documents from foreign counterparties land. The SII gives every counterparty outside Chile the RUT 55555555-5, so Sintropix finds a foreign Partner by the name the provider states. It first looks for the Partner that holds that name as an Alias. It then looks for a Partner whose display name is the same name, and takes the oldest if several match. It never picks a Merged Partner. Add a spelling as an Alias to route future documents with that spelling to the right Partner. Set Aliases with the aliases field of PATCH /partners/:partnerId. The list replaces the current Aliases:

Merge Partners

Merge a duplicate Partner into the Partner you want to keep. Both belong to the same Organization, and the merge runs in every Entity that uses the duplicate. The duplicate becomes a Merged Partner, and its name and Aliases become Aliases of the kept Partner. In the app, use the Fusionar row action on the Partners page.
A merge cannot be undone.

POST /api/organizations/:organizationId/partners/:partnerId/merge

Merge the Partner in the path into targetPartnerId, the Partner that stays. The merge runs all-or-nothing across every Entity, and the Audit Trail records every row it changes. There is no merge route under /api/entities/:entityId. The route needs the books write permission in the Organization. An API key confined to one Entity can merge only a Partner that no other Entity uses, because a merge moves the books of every Entity that uses it. Otherwise it gets 403 with PERMISSION_DENIED_ERROR. Body. Unknown keys are rejected with 400. Response (200): { "partner": <Organization Partner row>, "mergedPartner": <Organization Partner row> }, in the shape GET /api/organizations/:organizationId/partners lists. partner is the kept Partner after the merge. mergedPartner is the merged one, with mergedIntoPartnerId set. The moved lines, Invoices, and Bank Movements are not included; read them back through their own endpoints.

What a merge moves

Every Entity that used the merged Partner now uses the kept Partner. In each of those Entities, Sintropix moves these records from the merged Partner to the kept Partner:
  • Every Ledger Line in an Entry dated after that Entity’s Lock Date, unless the Entry is deleted or cancelled.
  • Every Invoice that is unbooked or whose booking entry holds a line that moves.
  • Every Bank Movement that is unbooked or whose bank line moves.
Lines on or before an Entity’s Lock Date stay on the merged Partner, because the Lock Date freezes them. The Partner Ledger shows that history under the merged Partner’s name. The kept Partner takes these shared fields from the merged Partner only where its own value is empty: the tax identity (country and taxId), legalName, and website. When the merged Partner represents an Entity, the kept Partner takes that role with the tax identity. In each Entity, the kept Partner takes the merged Partner’s defaultPurchaseAccountId when it has none there. It takes the merged Partner’s Booking Template, with its documentKind, and booksAutomatically only when it has no template in that Entity. Otherwise, Sintropix removes the merged Partner’s template. The kept Partner also takes every Payment Order and Expense Claim of the merged Partner, and its Bank Details when the kept Partner has none. The merge also clears every Follow-up that names the merged Partner. A Partner merged earlier into the merged Partner now points at the kept Partner.

After a merge

A Merged Partner:
  • Does not appear in GET /partners/pages, Partner search, or pickers. GET /partners still returns it, and so does GET /partners/options when you name it in partnerIds.
  • Is never matched by a Source Feed.
  • Cannot be edited, deleted, merged, used in another Entity, or given a Booking Template (409, PARTNER_MERGED_ERROR).
  • Cannot be named on a new or updated Ledger Line, Invoice, or Bank Movement. Those writes return 409 with LEDGER_ENTRY_LINE_PARTNER_MERGED_ERROR, INVOICE_PARTNER_MERGED_ERROR, or BANK_MOVEMENT_PARTNER_MERGED_ERROR. Use the Partner in mergedIntoPartnerId instead.

When a merge is refused

A merge is also refused when an Invoice without a DTE would collide with an Invoice of the kept Partner that has the same direction, kind, and number.

Bank Details

Bank Details state where a Partner receives a bank transfer. A Payment Batch pays each Partner to these details, and can’t be marked Ready while a payee has none. A Partner holds at most one set. The name and RUT the transfer carries are the Partner’s own name and taxId. Bank Details are shared by every Entity that uses the Partner. They appear as bankDetails on every Partner row. When the Partner itself is deleted, they go too.

PUT /partners/:partnerId/bank-details

Set the Partner’s Bank Details. The body states the whole set and replaces any details the Partner already has. Body Response: the Partner row, as GET /partners/pages lists it, with its bankDetails.

DELETE /partners/:partnerId/bank-details

Remove the Partner’s Bank Details. A Partner without them is refused with 404 and PARTNER_BANK_DETAILS_NOT_FOUND_ERROR. Response: the Partner row, as GET /partners/pages lists it, with bankDetails: null.

Booking Templates

A Booking Template tells Sintropix how one Entity books a Partner’s purchase invoices. It states the Document Kind it books and an ordered list of lines. Each line takes one amount from the Invoice or its DTE and posts it to a Ledger Account on a side. With the Partner’s booksAutomatically switch on in that Entity, Sintropix books each new purchase invoice of that Partner in that Entity when it is created, but only when the Invoice fits the template exactly. Use a template for a vendor whose invoices you always book with the same entry shape, such as a hosting provider billed to one expense account plus IVA. Invoices that do not fit land unbooked, and you book them by hand with POST /invoices/:invoiceId/book. Each Entity keeps its own template and switch for a Partner, so a template saved in one Entity never books another Entity’s invoices. Saving a template gives the Partner the vendor role in that Entity. The Partner’s default purchase account is unaffected.

Document kind

A template’s documentKind is invoice or tax_only:
  • An invoice template books the Invoice’s total as a payable on its Control Line.
  • A tax_only template books tax only, with no Control Line. The Invoice it books becomes a tax_only document. Use it for a vendor whose facturas de compra (type 46) only declare the IVA of a purchase abroad, while the foreign vendor’s own Invoice holds the payable.
In the app, pick Documento por pagar or Solo impuesto in the template’s Clase de documento.

Template lines

A template needs at least 2 and at most 10,000 lines. An invoice template has exactly one line that uses invoice_total: the Control Line. A tax_only template has none, and none of its lines may post to an account whose sub-type is payable, expense_rendition_payable, or receivable (409, TAX_ONLY_LINE_ON_CONTROL_ACCOUNT_ERROR). A wrong number of invoice_total lines is refused with 400. On an invoice template, the Control Line must follow the control line rules of Book invoice for a payable invoice: a credit on an open-item payable liability account. Other lines may post to the Control Line’s account too. They book as ordinary open items of the Partner. Only the invoice_total line becomes the Invoice’s Control Line. While a template uses an account as its Control Line, that account’s type, subtype, and tracking cannot change (LEDGER_ACCOUNT_FACT_PINNED_ERROR). An account any template line uses cannot be deleted.

When an Invoice is booked automatically

Sintropix books a new Invoice from the template only when all of these hold:
  1. The create request sent no bookingEntryWithLines. An explicit booking always wins.
  2. The Invoice is created as direction: "payable" and documentKind: "invoice". Credit notes are never booked automatically. With a tax_only template, the Invoice becomes tax_only in the same act that books it.
  3. The same request creates the DTE. An Invoice whose DTE is attached later is not booked. A source-feed sync never books a DTE that lands with the Standing claimed, annulment_requested, or annulled.
  4. The Invoice and its DTE are in the Entity’s functional currency.
  5. The Partner has booksAutomatically set to true in the Entity.
  6. Every line’s source has a value on the DTE, and none is negative. A DTE that withholds no IVA gives a dte_withheld_iva_amount line 0.
  7. On an invoice template, the Control Line amount is not 0. Other lines with an amount of 0 are dropped.
  8. At least two lines remain, and they balance exactly. There is no rounding tolerance.
The booking follows every rule of Book invoice, including the Lock Date. If any condition fails, the Invoice and its DTE are still created, unbooked, and Sintropix stores no reason. An Invoice that a tax_only template couldn’t book stays invoice. In POST /invoices/bulk and the source-feed sync, one Invoice that does not fit never blocks the others. Invoices that exist before you turn the switch on are not booked. The Audit Trail credits an automatic booking to the system, with the declared actor booking-template.

GET /partners/:partnerId/booking-template

Read a Partner’s template. Response: { "partner": <Partner row>, "documentKind": "invoice" | "tax_only", "lines": [<line>] }. The Partner row has the shape GET /partners/pages lists. lines is empty and documentKind is invoice when the Partner has no template.

PUT /partners/:partnerId/booking-template

Save a template. The body replaces the whole template; the order of lines is the order of the template. Body Unknown keys are rejected with 400. Response: the saved template, in the shape GET answers.
With this template, an Invoice with a total of 1190000 and a DTE stating netAmount 1000000 and taxAmount 190000 is booked. The net and tax lines are debited, and the payable is credited. A DTE whose amounts do not add up to the total leaves the Invoice unbooked. To also book the vendor’s facturas de compra (type 46), add a credit line with dte_withheld_iva_amount on the withheld IVA account. A 46 with a total of 1000000, netAmount 1000000, taxAmount 190000, and withheldIvaAmount 190000 is booked with the withheld IVA credited. On a 33, which withholds no IVA, that line is 0 and is dropped, so the same template books both.
The wasabil Source Feed lands every 46 with withheldIvaAmount null, because Wasabil no longer states which IVA is withheld. A dte_withheld_iva_amount line has no amount on these DTEs, so the entry does not balance and the Invoice lands unbooked. For a Wasabil vendor’s 46s, book the withheld IVA credit line from dte_tax_amount instead. That template books the vendor’s 46s with a total withholding, but not its 33s.
For a foreign vendor whose 46s only declare the IVA, save a tax_only template that debits the IVA account and credits the withheld IVA account, both from dte_tax_amount:
A 46 of that vendor with a taxAmount of 190000 lands as a booked tax_only document: IVA debited 190000, withheld IVA credited 190000, and nothing owed. Then turn the switch on:

DELETE /partners/:partnerId/booking-template

Remove the template. This also turns booksAutomatically off and sets documentKind back to invoice. Response: the Partner, documentKind: "invoice", and its now empty lines, in the shape GET answers.

Error codes

A Control Line on the wrong side or on an account Book invoice refuses as a payable control account is answered with the same error Book invoice returns.

Status codes