CustomersCreate a customer

Create a customer

Creates a customer together with its invoice settings and returns it.

Creates a customer row and its invoice settings in one call. The response is the created customer in the short read representation (CustomerRead), including the new CustomerID. Address, owners, currency, industry and invoice settings are stored but cannot be read back through the REST v1 API.

Use it to:

  • Create customers in TimeLog from a CRM or ERP master record

Not for:

  • Dry-run validation → POST /v1/customer/validate-new-customer

Rules across fields:

  • R1: UseInvoicingAddress true → InvoicingAddressCountryID required; invoicing-address fields are ignored when it is false.
  • R2: UseEanNo true → OIOXML feature on (37697), Address + ZipCode + City set (60063), VatNo set (60064).
  • R3: Name + CustomerNo must not equal an existing customer's pair (case-insensitive).

Behaviour:

  • Not idempotent.
  • Safe to retry only under a condition. A retry with the same Name and CustomerNo fails with 38017 when the first attempt created the customer (and the caller can see it). With an empty CustomerNo and a number series active, each attempt gets a new number, so the pair differs and a duplicate is created.
  • Duplicates: Only the exact Name + CustomerNo pair is rejected (and the number alone when UniqueCustomerNumber is on). No external-key deduplication.
  • Side effect: Inserts the customer (CustomerGUID generated server-side) and its invoice settings.
  • Side effect: Assigns the next customer number from the series when CustomerNo is blank and the series is active.
  • On failure: If saving the invoice settings fails after the customer row is inserted, the customer exists without invoice settings and the call still returns 500.
  • Changes are visible to the next read immediately.

Call first: GET /v1/customerstatus, GET /v1/industry/get-all

Next: GET /v1/customer/{customerID}, PUT /v1/customer/update

See also: POST /v1/customer/validate-new-customer

Not yet documented: examples (success).

curl -X POST "https://app3.timelog.com/your-account/api/v1/customer/create" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -d '{
  "Name": "John Doe",
  "CurrencyID": 123,
  "CustomerStatusID": 123,
  "CountryID": 123,
  "CustomerNo": "example_string",
  "NickName": "John Doe",
  "PrimaryKAMID": 123,
  "SecondaryKAMID": 123,
  "CustomerSince": "2024-12-25T10:00:00Z",
  "IndustryID": 123,
  "Phone": "+1-555-0123",
  "Fax": "example_string",
  "Email": "user@example.com",
  "Website": "example_string",
  "Address": "123 Main St",
  "Address2": "123 Main St",
  "Address3": "123 Main St",
  "ZipCode": "example_string",
  "City": "New York",
  "State": "example_string",
  "UseInvoicingAddress": true,
  "InvoicingAddressCountryID": 123,
  "InvoicingAddress": "123 Main St",
  "InvoicingAddress2": "123 Main St",
  "InvoicingAddress3": "123 Main St",
  "InvoicingAddressZipCode": "123 Main St",
  "InvoicingAddressCity": "123 Main St",
  "InvoicingAddressState": "123 Main St",
  "VatNo": "example_string",
  "OrganizationNo": "example_string",
  "DefaultMileageDistance": 25,
  "ExpenseIsBillable": true,
  "MileageIsBillable": true,
  "DefaultDistIsMaxBillable": true,
  "ContactID": 123,
  "InvoiceAddressToUse": 42,
  "InternalReferenceID": 123,
  "CustomerReferenceID": 123,
  "PaymentTermID": 123,
  "DiscountPercentage": 3.14,
  "CalculateVat": true,
  "VatPercentage": 3.14,
  "UseEanNo": true,
  "EanNo": "example_string",
  "LanguageID": 123
}'
{
  "Properties": {
    "CustomerID": 123,
    "ID": "123e4567-e89b-12d3-a456-426614174000",
    "Name": "John Doe",
    "No": "example_string",
    "DefaultMileageDistance": 25,
    "CustomerStatusID": 123,
    "VATNo": "example_string",
    "OrganizationNo": "example_string"
  },
  "Links": [
    {
      "Href": "example_string",
      "Rel": "example_string"
    }
  ],
  "Actions": [
    {}
  ]
}
POST
/v1/customer/create
POST
Base URLstring

Target server for requests. Edit to use your own host.

Bearer Token
Bearer Tokenstring
Required

OAuth 2.0 bearer token, sent as Authorization: Bearer <token>. JWT and reference tokens are both accepted. The token must carry the required scope (default tlp). The token's sub claim is the acting user. A token WITHOUT sub (client-credentials) acts as the system service user. If the sub user cannot log in (inactive, locked, deleted), the request is rejected with 401 — it is no longer let through without a user. > Not yet documented: how to obtain a token. > Not yet documented: token lifetime.

OAuth 2.0 bearer token, sent as Authorization: Bearer <token>. JWT and reference tokens are both accepted. The token must carry the required scope (default tlp). The token's sub claim is the acting user. A token WITHOUT sub (client-credentials) acts as the system service user. If the sub user cannot log in (inactive, locked, deleted), the request is rejected with 401 — it is no longer let through without a user. > Not yet documented: how to obtain a token. > Not yet documented: token lifetime.
Content-Typestring
Required

The media type of the request body

Options: application/json
Namestring
Required

Company name. With CustomerNo, must not match an existing customer (case-insensitive name + number pair, 38017). Over 255 characters is not rejected by validation (server outcome unknown). > Not yet documented: notes.

Max length: 255
CurrencyIDinteger
Required

The customer's currency. Refers to CurrencyRead.CurrencyID. Look up valid values with GET /v1/currency/{status}. 0 is rejected by validation (400). Whether a non-existent ID is caught on create is unknown: the CurrencyExist rule runs only when the currency property is flagged as changed. > Not yet documented: notes.

CustomerStatusIDinteger
Required

The customer's status. Refers to CustomerStatusRead.CustomerStatusID. Look up valid values with GET /v1/customerstatus. - ID does not exist — Business rule 30018 (HTTP 500, Code 102), raised before any other check. Valid values come from GET /v1/customerstatus.

CountryIDinteger
Required

Country of the customer's address. Refers to CountryRead.CountryID. Look up valid values with GET /v1/country/get-all.

CustomerNostring

Customer number. Alternate key, unique per TimeLog site. Default: Next number of the customer-number series when that series is active; otherwise empty. - Feature UniqueCustomerNumber is on and the number is already used — 30169 'Customer number is already in use' — returned as HTTP 403 Privilege exception. - Customer-number series (AutoNumberTypes.CustomerNo) active and the value is blank — Assigned from the series.

Max length: 255
NickNamestring

Short name. Matched by the searchText of the search-for-* operations. Display of the field in TAF actions depends on feature CustomerNickName; the API stores it either way.

PrimaryKAMIDinteger

Primary owner (key account manager), given as a USER ID (not an employee ID). Refers to UserRead.UserID. - Sent as 0 or negative — Validation (400): must be greater than 0 when present. - User does not exist — 37040 (HTTP 500, Code 102). - User is inactive — 37931 (HTTP 500, Code 102). The caller's customer privilege is evaluated against the owner set here: with only the "customers where I am account manager" privilege, create succeeds only when the caller is the primary owner. Owner when omitted: unknown. > Not yet documented: notes.

SecondaryKAMIDinteger

Secondary owner, given as a USER ID. Refers to UserRead.UserID. - 0 or negative — Validation (400). - User does not exist / inactive — 37040 / 37931 (HTTP 500, Code 102). TAF display depends on feature TwoOwnersPerCustomer; the API stores it either way.

CustomerSincestring

Date the customer relationship started. Time zone: not yet documented. Default: Server's current date and time (DateTime.Now) when omitted or invalid. > Not yet documented: constraints → timezone.

Format: date-time
IndustryIDinteger

Industry classification. Refers to IndustryRead.IndustryID. Look up valid values with GET /v1/industry/get-all. - 0 or negative — Validation (400). - ID does not exist — 30019 (HTTP 500, Code 102). Inactive industries are accepted. Valid values come from GET /v1/industry/get-all.

Emailstring

Validated as an e-mail address when not blank (400).

Format: email
UseInvoicingAddressboolean

Whether the customer has a separate invoicing address.

InvoicingAddressCountryIDinteger

Country of the invoicing address. Conditional. Required (non-zero) when UseInvoicingAddress is true; ignored otherwise. Refers to CountryRead.CountryID. Look up valid values with GET /v1/country/get-all.

InvoicingAddressstring

Conditional. Stored only when UseInvoicingAddress is true; ignored otherwise.

InvoicingAddress2string

Conditional. Stored only when UseInvoicingAddress is true; ignored otherwise.

InvoicingAddress3string

Conditional. Stored only when UseInvoicingAddress is true; ignored otherwise.

InvoicingAddressZipCodestring

Conditional. Stored only when UseInvoicingAddress is true; ignored otherwise.

InvoicingAddressCitystring

Conditional. Stored only when UseInvoicingAddress is true; ignored otherwise.

InvoicingAddressStatestring

Conditional. Stored only when UseInvoicingAddress is true; ignored otherwise.

VatNostring

VAT number. Returned as VATNo.

Max length: 200
OrganizationNostring

Company registration number.

Max length: 255
DefaultMileageDistanceinteger

> Not yet documented: constraints → unit.

DefaultDistIsMaxBillableboolean

The default mileage distance is also the maximum billable distance.

ContactIDinteger

Invoice contact person. Refers to ContactRead.ContactID. -1 = the project's contact; 0 = choose when invoicing; > 0 = a contact ID (must exist: 37011).

InvoiceAddressToUseinteger

Which address invoices go to. Allowed values: | Value | Name | Meaning | |---|---|---| | 0 | NotSpecified | Not specified. Accepted by validation; downstream effect not established. | | 1 | CustomersAddress | Invoice to the customer's address. | | 2 | ContactsAddress | Invoice to the invoice contact's address. | | 4 | CustomerInvoicingAddress | Invoice to the customer's separate invoicing address. | > Not yet documented: values → members → meaning.

Options: 0, 1, 2, 4
InternalReferenceIDinteger

Internal reference on invoices. Refers to EmployeeRead.EmployeeID. -3 = project's account manager; -2 = project manager; -1 = customer's owner; 0 = choose when invoicing; > 0 = an EMPLOYEE ID (must exist: 30014).

CustomerReferenceIDinteger

Customer reference (contact) on invoices. Refers to ContactRead.ContactID. -1 = project's contact; 0 = choose when invoicing; > 0 = a contact ID (must exist: 37011).

PaymentTermIDinteger

Payment term. Refers to PaymentTermRead.ID. Look up valid values with GET /v1/payment-term. > 0 must exist (37022). Meaning of 0 (omitted) not established. Valid values come from GET /v1/payment-term. > Not yet documented: notes.

DiscountPercentagenumber

Unit: percent No range check in the API layer.

Format: double
VatPercentagenumber

Unit: percent No range check in the API layer.

Format: double
UseEanNoboolean

Invoice this customer electronically with an EAN number (OIOXML). - true and feature OIOXML is off — 37697 (HTTP 500, Code 102). - true and Address, ZipCode or City is blank — 60063. - true, address complete, VatNo blank — 60064.

EanNostring

EAN number: exactly 13 characters, or empty (any other length fails validation, 400).

Max length: 13
LanguageIDinteger

Invoice language. - Any other value — Validation (400), even when the feature below is off. - Feature InvoiceMultilingual is off — Validated, then not stored. Allowed values: | Value | Name | Meaning | |---|---|---| | 1 | Danish | Invoices in Danish. | | 2 | English | Invoices in English. | | 4 | Swedish | Invoices in Swedish. | | 15 | Norwegian | Invoices in Norwegian. | | 16 | German | Invoices in German. | | 17 | Dutch | Invoices in Dutch. | | 18 | French | Invoices in French. |

Options: 1, 2, 4, 15, 16, 17, 18
Request Preview
Response

Response will appear here after sending the request

Authentication

header
Authorizationstring
Required

Bearer token. OAuth 2.0 bearer token, sent as Authorization: Bearer <token>. JWT and reference tokens are both accepted. The token must carry the required scope (default tlp).

The token's sub claim is the acting user. A token WITHOUT sub (client-credentials) acts as the system service user. If the sub user cannot log in (inactive, locked, deleted), the request is rejected with 401 — it is no longer let through without a user.

Not yet documented: how to obtain a token.

Not yet documented: token lifetime.

Body

application/json
Namestring
Required

Company name.

With CustomerNo, must not match an existing customer (case-insensitive name + number pair, 38017). Over 255 characters is not rejected by validation (server outcome unknown).

Not yet documented: notes.

CurrencyIDinteger
Required

The customer's currency.

Refers to CurrencyRead.CurrencyID. Look up valid values with GET /v1/currency/{status}.

0 is rejected by validation (400). Whether a non-existent ID is caught on create is unknown: the CurrencyExist rule runs only when the currency property is flagged as changed.

Not yet documented: notes.

CustomerStatusIDinteger
Required

The customer's status.

Refers to CustomerStatusRead.CustomerStatusID. Look up valid values with GET /v1/customerstatus.

  • ID does not exist — Business rule 30018 (HTTP 500, Code 102), raised before any other check.

Valid values come from GET /v1/customerstatus.

CountryIDinteger
Required

Country of the customer's address.

Refers to CountryRead.CountryID. Look up valid values with GET /v1/country/get-all.

CustomerNostring

Customer number.

Alternate key, unique per TimeLog site.

Default: Next number of the customer-number series when that series is active; otherwise empty.

  • Feature UniqueCustomerNumber is on and the number is already used — 30169 'Customer number is already in use' — returned as HTTP 403 Privilege exception.

  • Customer-number series (AutoNumberTypes.CustomerNo) active and the value is blank — Assigned from the series.

NickNamestring

Short name. Matched by the searchText of the search-for-* operations.

Display of the field in TAF actions depends on feature CustomerNickName; the API stores it either way.

PrimaryKAMIDinteger

Primary owner (key account manager), given as a USER ID (not an employee ID).

Refers to UserRead.UserID.

  • Sent as 0 or negative — Validation (400): must be greater than 0 when present.

  • User does not exist — 37040 (HTTP 500, Code 102).

  • User is inactive — 37931 (HTTP 500, Code 102).

The caller's customer privilege is evaluated against the owner set here: with only the "customers where I am account manager" privilege, create succeeds only when the caller is the primary owner. Owner when omitted: unknown.

Not yet documented: notes.

SecondaryKAMIDinteger

Secondary owner, given as a USER ID.

Refers to UserRead.UserID.

  • 0 or negative — Validation (400).

  • User does not exist / inactive — 37040 / 37931 (HTTP 500, Code 102).

TAF display depends on feature TwoOwnersPerCustomer; the API stores it either way.

CustomerSincestring

Date the customer relationship started.

Time zone: not yet documented.

Default: Server's current date and time (DateTime.Now) when omitted or invalid.

Not yet documented: constraints → timezone.

IndustryIDinteger

Industry classification.

Refers to IndustryRead.IndustryID. Look up valid values with GET /v1/industry/get-all.

  • 0 or negative — Validation (400).

  • ID does not exist — 30019 (HTTP 500, Code 102). Inactive industries are accepted.

Valid values come from GET /v1/industry/get-all.

Emailstring

Validated as an e-mail address when not blank (400).

UseInvoicingAddressboolean

Whether the customer has a separate invoicing address.

InvoicingAddressCountryIDinteger

Country of the invoicing address.

Conditional. Required (non-zero) when UseInvoicingAddress is true; ignored otherwise.

Refers to CountryRead.CountryID. Look up valid values with GET /v1/country/get-all.

InvoicingAddressstring

Conditional. Stored only when UseInvoicingAddress is true; ignored otherwise.

InvoicingAddress2string

Conditional. Stored only when UseInvoicingAddress is true; ignored otherwise.

InvoicingAddress3string

Conditional. Stored only when UseInvoicingAddress is true; ignored otherwise.

InvoicingAddressZipCodestring

Conditional. Stored only when UseInvoicingAddress is true; ignored otherwise.

InvoicingAddressCitystring

Conditional. Stored only when UseInvoicingAddress is true; ignored otherwise.

InvoicingAddressStatestring

Conditional. Stored only when UseInvoicingAddress is true; ignored otherwise.

VatNostring

VAT number. Returned as VATNo.

OrganizationNostring

Company registration number.

DefaultMileageDistanceinteger

Not yet documented: constraints → unit.

DefaultDistIsMaxBillableboolean

The default mileage distance is also the maximum billable distance.

ContactIDinteger

Invoice contact person.

Refers to ContactRead.ContactID.

-1 = the project's contact; 0 = choose when invoicing; > 0 = a contact ID (must exist: 37011).

InvoiceAddressToUseinteger

Which address invoices go to.

Allowed values:

ValueNameMeaning
0NotSpecifiedNot specified. Accepted by validation; downstream effect not established.
1CustomersAddressInvoice to the customer's address.
2ContactsAddressInvoice to the invoice contact's address.
4CustomerInvoicingAddressInvoice to the customer's separate invoicing address.

Not yet documented: values → members → meaning.

Allowed values:0124
InternalReferenceIDinteger

Internal reference on invoices.

Refers to EmployeeRead.EmployeeID.

-3 = project's account manager; -2 = project manager; -1 = customer's owner; 0 = choose when invoicing; > 0 = an EMPLOYEE ID (must exist: 30014).

CustomerReferenceIDinteger

Customer reference (contact) on invoices.

Refers to ContactRead.ContactID.

-1 = project's contact; 0 = choose when invoicing; > 0 = a contact ID (must exist: 37011).

PaymentTermIDinteger

Payment term.

Refers to PaymentTermRead.ID. Look up valid values with GET /v1/payment-term.

0 must exist (37022). Meaning of 0 (omitted) not established.

Valid values come from GET /v1/payment-term.

Not yet documented: notes.

DiscountPercentagenumber

Unit: percent

No range check in the API layer.

VatPercentagenumber

Unit: percent

No range check in the API layer.

UseEanNoboolean

Invoice this customer electronically with an EAN number (OIOXML).

  • true and feature OIOXML is off — 37697 (HTTP 500, Code 102).

  • true and Address, ZipCode or City is blank — 60063.

  • true, address complete, VatNo blank — 60064.

EanNostring

EAN number: exactly 13 characters, or empty (any other length fails validation, 400).

LanguageIDinteger

Invoice language.

  • Any other value — Validation (400), even when the feature below is off.

  • Feature InvoiceMultilingual is off — Validated, then not stored.

Allowed values:

ValueNameMeaning
1DanishInvoices in Danish.
2EnglishInvoices in English.
4SwedishInvoices in Swedish.
15NorwegianInvoices in Norwegian.
16GermanInvoices in German.
17DutchInvoices in Dutch.
18FrenchInvoices in French.
Allowed values:12415161718

Responses

Propertiesobject

A customer as the REST v1 API returns it: the identifiers, name, number, status and tax numbers only.

Linksarray
Actionsobject[]