Customers

Create a customer

Creates a customer in the authenticated user's company. company_id and created_by are always derived from the bearer token — neither can be set from the body.

Required: customer_type. Everything else is optional.

Returns the fully materialized customer (re-fetched so computed fields like last_vehicle_* and next_appointment populate consistently with GET).

Foreign-key references in the body (price_list_id, etc.) must resolve to resources owned by the authenticated user's company. Unreachable refs return 422 parameter_invalid pointing at the offending field.

custom_fields carries custom field values keyed by the ids from GET /v1/customer-field-settings (see CustomerCustomFieldValues).

As on the web, creating a customer schedules its agenda events: the birthday (when birthday is set and the company keeps birthday events on) and each opted-in custom date field.

post/v1/customers

Request

  • Base URL: https://api.officina.it
  • URL: https://api.officina.it/v1/customers
  • Auth: HTTP bearer

Request body

customer_typestring required
full_namestring nullable
emailstring email nullable
phonestring nullable

National number as typed (e.g. "333 1234567"). Combined with phone_dial_code and validated server-side via the web customer-form rules ("+39" allows Italian mobiles and landlines; other known dial codes get a basic E.164 check); stored and returned as one E.164 string. Invalid pairs are rejected with 422 parameter_invalid.

phone_dial_codestring nullable

E.164 dial code (default "+39"). Only read alongside phone.

addressstring nullable
citystring nullable
zip_codestring nullable
provincestring nullable
tax_idstring nullable

Partita IVA, or the VAT number of a business in another EU country. Checked on every revision against the country's format and check digits (see "Partita IVA e numeri IVA UE"): 422 parameter_invalid on /tax_id when it fails. Stored without country prefix, spaces or dots.

fiscal_codestring nullable
pecstring nullable
destination_codestring nullable
payment_methodstring nullable
commentsstring nullable
birthdaystring date-time nullable

Nullable client-supplied RFC 3339 timestamp. Same 1900-01-01 … 2100-12-31 window as WritableTimestamp; null clears the field.

price_list_idstring nullable
custom_fieldsCustomerCustomFieldValues nullable

The customer's custom field values, keyed by definition id from GET /v1/customer-field-settings (e.g. cf_9b20d3). Same rules as VehicleCustomFieldValues: every key is checked against the company's definitions and each value against its field's type (string trimmed; integer as a JSON integer or a string holding one; datetime as YYYY-MM-DD or RFC 3339, stored as YYYY-MM-DD, years 1900–2100). A date field whose definition sets reminder_days_before (and is visible) gets an agenda event on that date.

A null or empty value clears that field. An unknown key or a value that does not fit its type is a 422 parameter_invalid with param pointing at it (/custom_fields/<id>). A value sent back exactly as the customer stores it is never refused. On PATCH the object replaces the stored one as a whole: a visible field left out is cleared, a hidden field keeps its stored value unless its key is sent.

A stored value that no longer fits its field's type (text left under a field later turned into a date or number) is likewise kept unless its key is sent — clients cannot show it in a typed input, so leaving it out is not a request to clear it. Send the key with null to clear it.

Example request

{
  "custom_fields": {
    "cf_4c1e7a": "Idraulico",
    "cf_9b20d3": "2027-03-15"
  }
}

Response

Customer created.

object'customer' required
idstring required
customer_typestring required

Tax-status discriminator (e.g. "private", "company").

full_namestring nullable
emailstring email nullable
phonestring nullable

Stored E.164 value, e.g. "+393331234567".

phone_dial_codestring nullable

phone split server-side for the edit form's dial-code selector (e.g. "+39"). Null when phone is null.

phone_nationalstring nullable

phone minus the dial code, for the edit form's national-number input. Null when phone is null.

addressstring nullable
citystring nullable
zip_codestring nullable
provincestring nullable
tax_idstring nullable

Partita IVA for an Italian customer; the VAT number without country prefix for a business elsewhere in the EU; free text otherwise. See "Partita IVA e numeri IVA UE".

fiscal_codestring nullable

Italian fiscal code (codice fiscale) for individuals.

pecstring nullable

Italian certified-email address for e-invoicing.

destination_codestring nullable

Italian SDI destination code for e-invoicing.

payment_methodstring nullable
commentsstring nullable
birthdaystring date-time nullable
last_vehicle_namestring nullable

Display string of the customer's most recent vehicle (e.g. "Fiat Panda"). Pre-computed on the entity for list-row rendering without a second request.

last_vehicle_licensestring nullable
total_spentnumber double

Lifetime spend (worksheet totals net of discounts), computed by the list query for row rendering. Money — render via the locale formatter; avoid arithmetic.

custom_fieldsobject nullable

Single-customer responses only (GET, POST, PATCH). Raw stored values keyed by custom field definition id (see CustomerCustomFieldValues for the stored shapes). Includes hidden fields. Omitted on lists.

next_appointmentstring date-time nullable
created_atstring date-time required
updated_atstring date-time required
deleted_atstring date-time nullable

Soft-deletion timestamp. Populated on the response from DELETE /v1/customers/{id}. Customers with a non-null deleted_at are not returned by list/detail endpoints — this field appears for the delete response only.

Example response

{
  "id": "4c911f08-7713-4e83-bdf6-a0692a1b43fd",
  "documents": [
    {
      "url": "/v1/customers/0b6b…/documents/77c2…/download"
    }
  ]
}

Changes

No recorded changes to this operation across all 1 revision of this API.