Sari la conținut
Pagini APISuppliers

Documentație API

Această documentație este disponibilă doar în limba engleză.

Suppliers

A supplier is a company that invoices a client. It is the "from whom" on every invoice row and on every missing document.

Suppliers are scoped to the client company, not to the organization. Two clients that both buy electricity from the same utility hold two supplier rows. One firm's counterparty data never leaks into another client's list, and merging is always within one client.

Separate from that is the supplier directory: a shared, read-only list of companies Syllevo already knows how to collect invoices from, with setup instructions for each. A supplier row can be backed by a directory entry, in which case it carries a directorySlug.

Routes

Method Path Needs
GET /v1/suppliers View, profileId required
GET /v1/suppliers/{id} View
POST /v1/suppliers/{id}/merge ManageSources
GET /v1/organization/suppliers Any member
GET /v1/suppliers/connections View, profileId required
POST /v1/suppliers ManageSources
POST /v1/suppliers/from-directory ManageSources
PUT /v1/suppliers/{id}/connection-methods ManageSources
GET /v1/supplier-directory Any credential
GET /v1/vat-validations View
GET /v1/vat-validations/count View

The supplier shape

Field Type Means
id uuid The supplier row
profileId uuid The client company it invoices
name string The supplier's name
taxIdentifierType TaxIdentifierType 0 VAT number, 1 national registration, 2 other
taxIdentifierValue string or null The identifier itself, null when none is known
countryCode string or null Two letters
email string or null The address invoices arrive from, when one is known
directorySlug string or null The directory entry behind this row, null for a local one

GET /v1/suppliers

One page of a client's suppliers, ordered by name. View on the client.

Parameter Type Required Means
profileId uuid yes The client company
search string no Matches anywhere in the name, case-insensitively
page integer no Default 1
pageSize integer no Default 25, clamped to 200

profileId is required here because this is the door where the client company is the question being asked. A caller with no claim on it is refused with 403 rather than handed an empty page, which is the opposite of how the document and review lists behave.

GET /v1/suppliers/{id}

One supplier. View on the client it belongs to. A supplier the caller cannot see answers 404.

GET /v1/organization/suppliers

The same rows, across every client the caller can see, in one request. A firm with three hundred clients would otherwise need three hundred calls to draw one roster.

Parameter Type Required Means
profileId uuid no Narrow to one client
search string no Matches anywhere in the name, case-insensitively
page integer no Default 1
pageSize integer no Default 25, clamped to 200

Here profileId narrows and never widens, so naming a client the caller cannot see gives an empty page, not a refusal.

GET /v1/suppliers/connections

A client's suppliers with their connection state: how invoices from each one reach Syllevo today. View. profileId is required.

Field Type Means
supplier object The supplier shape above
connectionMethods array of SupplierConnectionMethod How invoices can arrive, directory and row together
senderAddresses array of string Addresses invoices from this supplier come from
directorySlug string or null The directory entry behind it
tutorialContentKey string or null The key of the setup instructions, for directory rows

SupplierConnectionMethod is a flags enum, so the array lists the methods that apply:

Value Name Means
0 None Nothing is connected
1 EmailForwarding Invoices arrive by mail from a known address
2 EFactura They arrive through ANAF
4 Connector A portal connector fetches them

connectionMethods is the union of three sources: what the directory entry behind this supplier advertises, what the firm declared on its own supplier row when it added one by hand, and what an arrival has proven. An invoice downloaded from ANAF puts 2 on the supplier that issued it, because a route invoices actually travel by is better evidence than a box somebody did or did not tick. None of the three can remove a method another added, and 1 is always in the list. A supplier that matches no directory entry answers with whatever the row holds, which is 1 alone until a firm says otherwise or one of its invoices arrives through e-Factura.

tutorialContentKey names a piece of copy held in the Syllevo web app, not a URL. It is there so the app can show the right setup steps. A server integration can ignore it.

POST /v1/suppliers/from-directory

Connects a listed supplier to a client company. ManageSources, because this is connecting a source, not filing a document.

Field Type Required Means
profileId uuid yes The client company
slug string yes The directory entry, from the catalog

Answers 200 with the connection. Calling it again for a supplier the client already holds finds the existing row rather than creating a second one, so it is safe to repeat.

This is the route to prefer. A directory-backed supplier arrives with its sender addresses already known, so invoices from it are recognized on the first arrival instead of landing in review.

POST /v1/suppliers

Adds a supplier the directory does not list. ManageSources.

Field Type Required Means
profileId uuid yes The client company
name string yes The supplier's name
senderAddresses array of string no Addresses its invoices arrive from
taxIdentifierType TaxIdentifierType no 0 VAT, 1 national registration, 2 other
taxIdentifierValue string no The identifier
countryCode string no Two letters
connectionMethods array no How its invoices arrive

Fill in countryCode and taxIdentifierValue together if you fill them in at all. A tax identifier stored without a country is matched differently from one stored with it, and that is how a company ends up with two rows.

connectionMethods says how the firm expects this supplier's invoices to arrive. Leave it out, or send an empty array, and the supplier is email forwarding only. Send 2 to say the supplier invoices through ANAF, so an invoice missing from it is chased on e-Factura instead of by mail. 1 is accepted and redundant: email forwarding is always included whether or not it is listed. 0 and 4 are refused with 400 - 0 is not a route, and a connector needs a slug only the directory holds, so it can only come from POST /v1/suppliers/from-directory.

A supplier declared for e-Factura that carries a fiscal identifier and no countryCode is given RO, for the reason written down under PUT /v1/suppliers/{id}/connection-methods.

Answers 200 with the connection.

PUT /v1/suppliers/{id}/connection-methods

Replaces the routes the firm declares for one supplier it already holds. ManageSources.

Field Type Required Means
profileId uuid yes The client company
connectionMethods array yes The routes the firm declares now

This is the toggle behind the e-Factura tick on the sources panel, and it replaces rather than adds. POST /v1/suppliers folds what you send into what the row already holds, so it can turn e-Factura on and never off. This route can do both: send [2] to say the supplier invoices through ANAF, and send [] or [1] to say it no longer does.

connectionMethods is required. Leaving it out is 400, not an empty list: an omitted field and an empty array would otherwise mean the same thing, and a caller that forgot the field would untick e-Factura and be told it worked.

Two things the request cannot change. 1 stays on the row whatever you send, because email forwarding asks nothing of the supplier and a row without it describes a company nobody can connect. 4 is left exactly as it is, neither added nor removed, because a connector needs a slug only the shared directory holds. Sending 0 or 4 is refused with 400, the same as on POST /v1/suppliers.

A supplier that ends up declared for e-Factura, carries a fiscal identifier, and has no countryCode yet is given RO. ANAF carries Romanian companies and nobody else, and the country is what lets an incoming e-Factura invoice find the row: matching is on the country and the fiscal identifier together, so a supplier typed in as a bare CUI with no country beside it is a row the invoice walks past. A supplier that already has a country keeps it, and one with no fiscal identifier is left alone.

Answers 200 with the connection, the same shape GET /v1/suppliers/connections returns, so the connectionMethods on it are the new set. A supplier that belongs to another client company answers 404. Sending the routes the row already has changes nothing and writes nothing, so it is safe to repeat.

A supplier flagged 2 here is, together with every other supplier flagged 2 on the same client, exactly the "listed suppliers" set that an e-Factura enrollment's listedSuppliers collection scope files against - see e-Factura and SPV. The enrollment screen can add to that set on its own: when the client has not already added a supplier by hand, it creates a minimal one from just a name and a Romanian tax identifier through POST /v1/suppliers. So does a filed e-Factura invoice: its issuer joins the set, which means a client that collected everything and later narrows to listedSuppliers keeps receiving from the suppliers it has been receiving from.

GET /v1/supplier-directory

Every listed supplier, alphabetical. Any signed-in credential. Answers a plain array, not a paged envelope.

Parameter Type Means
search string Optional match against the display name
Field Type Means
id uuid The directory entry
slug string Pass this to POST /v1/suppliers/from-directory
displayName string The company's name
aliases array of string Other names it invoices under
countryCode string or null Two letters
taxIdentifierType TaxIdentifierType Its identifier kind, when one is published
taxIdentifierValue string or null Its identifier
senderAddresses array of string Addresses its invoices come from
connectionMethods array How invoices from it can arrive
connectorSlug string or null The portal connector, when there is one
tutorialContentKey string The key of its setup instructions

This is a shared catalog, the same for every organization. It is how Syllevo recognizes a supplier on the first invoice rather than the third.

Not every entry has a taxIdentifierValue. Some companies do not publish one that is usable for matching, and a blank field is honest about that rather than guessed at.

POST /v1/suppliers/{id}/merge

Folds two supplier rows for one company into one. ManageSources. Both rows must belong to the same client company.

The supplier in the path is the one being removed. Everything hanging off it, invoices, documents, sender addresses, moves to the survivor first.

Name the survivor exactly one of two ways:

Field Type Means
intoSupplierId uuid Another supplier the client already holds
intoDirectorySlug string A directory entry, connected to the client on the way through

Sending both is 400. Sending neither is 400.

The intoDirectorySlug form is how a row that was extracted off an invoice becomes the official directory-backed row. If the client already holds the directory row, it is found rather than duplicated.

POST /v1/suppliers/44444444-4444-4444-8444-444444444444/merge HTTP/1.1
Host: api.syllevo.com
X-Api-Key: syl_live_examplekeynotreal000000000000
Content-Type: application/json

{ "intoDirectorySlug": "example-utilities" }

Answers 200 with the surviving supplier. Refusals:

Status Code Means
400 supplier_merge_same_supplier Both halves are the same supplier
409 supplier_merge_profile_mismatch The two belong to different client companies
409 supplier_merge_official_supplier The row being removed is the directory-backed one. Merge the other way
409 supplier_merge_already_official It is already the directory entry it was aimed at

Merging is not reversible. Read both rows first.

VAT validation

What the European Commission says about a client's foreign suppliers. Read-only, and that is the design rather than a first slice: the verdict is the Commission's, so there is nothing here to dismiss or override. A row changes when somebody corrects the supplier's VAT number and the next pass gets a different answer.

Only EU suppliers appear. Domestic suppliers are not in this list.

GET /v1/vat-validations

One page, worst news first.

Parameter Type Required Means
profileId uuid no Narrow to one client
page integer no Default 1
pageSize integer no Default 25
Field Type Means
supplierId uuid The supplier
profileId uuid The client company
supplierName string Its name on file
countryCode string Two letters, upper case, always an EU member state
vatNumber string or null Normalized, upper case, without the country prefix
status string invalid, missing, unchecked, or valid
checkedAt date-time, null When the Commission last answered
viesName string or null The trading name the Commission holds for that number

status is a lower-case word rather than a number, unlike every other enum on this API. Two of its four values are not stored anywhere, so there is no enum for it to be the wire form of. See Conventions.

checkedAt is never moved by a failed check. A row that says it was checked three weeks ago was checked three weeks ago.

Show viesName next to the supplier's name. A VAT number can be perfectly valid and belong to somebody else entirely, and this is the only field on the row that would say so. It is null for the member states that publish no trader details.

GET /v1/vat-validations/count

The badge, over the clients the caller can see.

Field Type Means
invalid integer Suppliers whose VAT number the Commission says is not registered
missing integer EU suppliers with no VAT identifier on file at all

Only the two states somebody has to act on. unchecked is not counted because Syllevo's own pass clears it within the hour, and valid is not counted because a badge that is never zero is not a badge.