Skip to content

Sync clients with a CRM or ERP

The client exists in your CRM or ERP and in Faturei Hoje. This guide shows how to move the record from one side to the other without creating duplicate clients.

There are two directions, and each has its own tool:

DirectionHow
From your system to FatureiLook up, then create or update. This is what this page shows
From Faturei to your systemThe client.created, client.updated and client.deleted events tell you right away, and incremental sync makes sure nothing was left behind
PermissionWhat for
clients:readLook the client up before writing
clients:createCreate whoever does not exist yet
clients:updateUpdate whoever already exists

The safest way to link the two records is the id. The first time you find or create the client, store the Faturei Hoje id in your system’s record. From then on, update straight through it with PATCH /public/v1/clients/{id}, without looking it up again.

Looking up by email, phone or document is for the first link, when you do not have the id yet.

POST /public/v1/clients does not check whether the client already exists: two calls with the same email create two records. So look up first. GET /public/v1/clients takes three exact-match filters:

FilterHow it compares
emailSame email, ignoring upper and lower case
phoneThe same phone, with or without the ninth digit. An invalid phone returns 422
cpf_cnpjThe same digits, with or without punctuation

There is also search, the same search as the clients screen, by name, email, phone or document. It is good for people searching, not for deciding on its own whether two clients are the same.

The base may already have duplicate records from before the integration. If the lookup returns more than one, do not pick blindly: log the case and sort it out with the company.

Terminal window
# 1. Look up by email
curl "https://api.fatureihoje.com/public/v1/clients?email=contato%40marcenariasouza.com.br&limit=2" \
-H "Authorization: Bearer $FH_API_KEY"
# 2a. Not found: create
# Generate the key once and keep it: on a retry, repeat with the same value.
CREATE_KEY=$(uuidgen)
curl -X POST "https://api.fatureihoje.com/public/v1/clients" \
-H "Authorization: Bearer $FH_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $CREATE_KEY" \
-d '{
"name": "Marcenaria Souza",
"email": "contato@marcenariasouza.com.br",
"phone": "+5511988887777",
"cpf_cnpj": "12345678000190",
"person_type": "pj"
}'
# 2b. Found: update through the id that came back in the lookup
CLIENT_ID="0d9a7c5e-3f1b-4d2a-8c6e-4a2b0c8e6f1d"
curl -X PATCH "https://api.fatureihoje.com/public/v1/clients/$CLIENT_ID" \
-H "Authorization: Bearer $FH_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "phone": "+5511988887777" }'

The record takes the same fields as the dashboard form, including the tax ones (legal name, registrations, tax address). The full list, with the format and length of each, is in the Reference.

ResponseWhat to do
422 validation_failedFix the field listed in errors (an invalid phone in the filter, for example)
404 resource_not_foundThe client in the PATCH no longer exists, or does not belong to the company
429 rate_limit_exceededWait for Retry-After and retry. See Rate limits
5xx or network failureRetry; on POST, with the same Idempotency-Key

PATCH changes only the fields that come in the call. A field that is not sent stays exactly as it is, and null clears an optional field.

Use that in your favor: send only the fields your system owns. If the team handles the notes in the dashboard and your ERP handles the document and the tax address, the ERP never sends notes, and nobody wipes out the other side’s work.

With both directions on, a loop is easy to create: your system updates the client, Faturei Hoje sends client.updated, your system writes again, and so on.

  • Compare before writing. If the incoming value equals what you already have, do not write and do not call the API.
  • In a client.updated, changed_fields tells you what changed. If those are only fields your system just sent, with the same values, the event is the echo of your own write.

A client created with an address already starts with the “Principal” address in the address list. Extra addresses (job site, branch, beach house) live in GET /public/v1/clients/{client_id}/addresses and POST /public/v1/clients/{client_id}/addresses.

DELETE /public/v1/clients/{id} removes the record for good, as in the dashboard, together with addresses, notes, group links, portal access, inventory and projects. Service orders, sales, quotes, tasks, transactions, contracts and invoices stay, without the client. There is no undo.

If in your system “delete” means “no longer a client”, what you may want is status: "inactive" in a PATCH. The decision is yours; the API does what you ask.