---
title: "Create an anagrafica"
method: POST
path: "/api/v1/rest/anagrafiche/parties"
tags: ["Contacts"]
---

# Create an anagrafica

`POST /api/v1/rest/anagrafiche/parties`

## Request

- Base URL: `https://api.custodo.ai`
- URL: `https://api.custodo.ai/api/v1/rest/anagrafiche/parties`
- Auth: HTTP bearer

Adds a company or a person to the register — the roles it holds (a customer, a supplier, both…), the fiscal block (partita IVA, codice fiscale, codice destinatario, PEC), the contact details, the owner and the GDPR basis. A partita IVA is NOT unique here (branches of one group share one, and so do a person and their ditta individuale), so nothing is refused as a duplicate: call anagrafiche_find_duplicates first and show the user what came back. Addresses are separate — add them with anagrafiche_set_address afterwards. A role outside the caller’s own role list (see `access` on anagrafiche_list_roles) is refused. It appears in the register immediately, so confirm the details with the user first.

## Headers

- `X-Tenant-Id` string, uuid

## Request body

- object
  - `kind` 'company' | 'person': `company` for an organisation, `person` for an individual or a ditta individuale.
  - `name` string, required: What people call them — «Rossi». This is the name every list shows.
  - `roles` string[]: What the anagrafica IS to the organisation — a SET, because a supplier that is also a customer holds both. Built-in keys: cliente, potenziale_cliente, ex_cliente, fornitore, agente, dipendente, collaboratore, consulente; the organisation’s own come from anagrafiche_list_roles. At most 20. Each member may be limited to some roles by an administrator; a set none of whose roles the caller may write (`access.write` on anagrafiche_list_roles) is refused.
  - `lifecycle` 'lead' | 'prospect' | 'customer' | 'former': DEPRECATED — send `roles` instead. The CRM’s old «Relazione», still accepted from callers written before it became roles: `lead` and `prospect` mean the role potenziale_cliente, `customer` means cliente, `former` means ex_cliente. Ignored whenever `roles` is also given.
  - `legal_name` string: The ragione sociale an invoice must carry — «Rossi S.r.l. Unipersonale» — when it differs from `name`.
  - `first_name` string: Only on a `person`.
  - `last_name` string: Only on a `person`.
  - `job_title` string: Their job — «Amministratore delegato». Only on a `person`.
  - `parent_id` string, uuid: The company this person works for, or the holding above this company. Another anagrafica’s id, from anagrafiche_search_parties or anagrafiche_create_party. A party can never be its own ancestor.
  - `vat_number` string: Partita IVA. Paste it as you have it: «IT 123.456.789-03» is stored as «12345678903». An Italian one is checked against its check digit; a foreign one is only shape-checked.
  - `tax_code` string: Codice fiscale: 16 characters for a person, the 11-digit partita IVA for a company. Checked.
  - `sdi_code` string: Codice destinatario for electronic invoicing: 7 characters for a private recipient, 6 for a PA. «0000000» legitimately means «no electronic channel».
  - `pec` string: The certified mailbox. A PEC is not an ordinary address — never put one in `email`.
  - `email` string: Ordinary email. What the duplicate probe matches on, and what files mail from this address under the anagrafica.
  - `phone` string: Landline, as it is dialled.
  - `mobile` string: Mobile number.
  - `whatsapp` string: The number they chat on WhatsApp, with the country code — «+39 333 123 4567». Its own field, never inferred from `mobile`: stored normalised, and what the WhatsApp module writes to.
  - `website` string: Their site: an http(s) address or a bare host, never another scheme.
  - `industry` string: Free text — «studio commercialista», «edilizia». There is no closed list.
  - `owner_user_id` string, uuid: Whose account it is. A colleague’s `user_id` from custodo_list_members, your own from custodo_whoami, or the `owner_user_id` a `detailed` anagrafiche_get_party returns.
  - `agent_user_id` string, uuid: The agente di riferimento who brought the account. A colleague’s `user_id` from custodo_list_members, or your own from custodo_whoami. Recorded only — this product computes no commission.
  - `source` string: Where they came from — «passaparola», «fiera», «sito». Free text.
  - `tags` string[]: Free labels, at most 20. REPLACES the whole list, so pass the tags the record should end up with.
  - `consent_basis` 'contract' | 'consent' | 'legitimate_interest' | 'legal_obligation': The GDPR Article 6 basis for holding their data. Never invent one — leave it out when nobody has recorded it.
  - `consent_at` string, date-time: When that basis was established, ISO-8601 with a timezone.
  - `consent_source` string: How it was obtained — «contratto firmato», «modulo sul sito».
  - `marketing_opt_out` boolean: true when they have asked not to be contacted commercially.
  - `notes` string: Free notes on the record, written by people and read by people.
  - `custom` object: The organisation’s own fields, FIELD KEY → value. The keys, types, options and which roles each field is for are `partyFields` in custodo_get_module_settings (module `anagrafiche`). A value is text, a number, a date as YYYY-MM-DD, true/false, or one of a choice field’s options exactly. Only the keys you pass change and `null` clears one. A key no field declares, or a field limited to roles the record does not hold, is refused; a required field the record’s roles want must be given.

## Response `200`

Done. `data` is the tool’s own answer.

- RestResult
  - `ok` true, required
  - `data` unknown, required

## Other responses

- `400`: The arguments did not validate: `error.message` names the field, what it expects and what arrived.
- `401`: No API key, or one that is malformed, unknown, revoked or expired.
- `403`: The call never ran: the module is off for this organisation, the credential lacks the permission or the module, the tier does not cover it, or the tool is destructive and the key was not minted for that.
- `409`: The record is in a state that does not allow it — under legal hold, already sent, already closed. `error.code` says which.
- `422`: The tool ran and refused, in a sentence of its own (`TOOL_REFUSED`): the message says what to change. Retrying the same call will not help.
- `429`: The API key has spent its minute, or its day. Every request a key makes counts. See `Retry-After`.

---

[API](https://skmtc.dev/custodo/apis/custodo-integrazioni.md) · [All operations](https://skmtc.dev/custodo/apis/custodo-integrazioni/llms.txt) · [OpenAPI document](https://skmtc.dev/custodo/apis/custodo-integrazioni/revisions/16d336d3ec2a?raw)
