> For the complete documentation index, see [llms.txt](https://docs.samesystem.dev/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.samesystem.dev/business-guides/data-models/user.md).

# User

{% hint style="info" %}
Only available in API v2. We have different user model in API v1. However, for user and contract integrations, we strongly recommend using **API v2**, and this guide therefore describes user creation using API v2 only.
{% endhint %}

A user record represents a logical person (employee) and can exist in SameSystem independently of employment status.

&#x20;The record can be uniquely identified by:

<table><thead><tr><th valign="top">Field:</th><th valign="top">Description:</th></tr></thead><tbody><tr><td valign="top"><code>id</code></td><td valign="top">Internal ID number in SameSystem.</td></tr><tr><td valign="top"><code>customId</code></td><td valign="top">External ID number created outside of SameSystem ex. from a HRIS System.</td></tr></tbody></table>

&#x20;The user record contains mainly static or slowly changing data like name, date of birth and contact details.

&#x20;It is possible to add custom fields to the user record and retrieve these in the API.

&#x20;Characteristics:

* Created once.
* Act as a parent entity for all employment contracts.
* Can exist without a contract.
* Can exist after employment ends.

### Status

A user can this status:

<table><thead><tr><th width="188">Status:</th><th>Description:</th></tr></thead><tbody><tr><td><code>ACTIVE</code></td><td>Active users.</td></tr><tr><td><code>NOT_STARTED</code></td><td>Users with a future contract that are not yet started.</td></tr><tr><td><code>ENDED</code> / <code>FINISHED</code> / <code>EXPIRED</code></td><td>Terminated users, users with expired contracts.</td></tr><tr><td><code>DRAFT</code></td><td>Users without a contract.</td></tr><tr><td><code>DISABLED</code> / <code>DELETED</code></td><td>Soft deleted users. A deleted user exits as a soft deleted user for 24 hours before the user is finally removed.</td></tr><tr><td><code>BLOCKED</code></td><td>Active user, but blocked from login.</td></tr></tbody></table>

### Use of customId field

You can use the `customId` field to uniquely identify a user based on an identifier from another system, for example an HRIS system. Several user endpoints in the v2 API support the use of `customId` to locate a user if you use the parameter `useCustomId=true`.

This is particularly useful when integrating HRIS, payroll or other external systems with SameSystem.

You should avoid reuse of custom ids, like assigning a unique employee number to a user, then terminating the user and using the same employee number to another user. SameSystem will prevent the new user from being created as terminated users still exist in the system and you will not be allowed to add the same custom id to another user.

If you need to reuse custom ids, which we will not recommend, you can either add a prefix, ex. `“DELETED”`, to the custom id fields of the terminated user or you can delete the user. A deletion will remove everything about the user in the system including all history, which is not recommended.

{% hint style="info" %}
**Notice:**

The setting “Use custom IDs for employees” must be enabled in General settings before customId can be used in the API.
{% endhint %}

### &#x20;Data sanitizing

The following fields will be automatically sanitized before saving into the system:

<table data-header-hidden data-search="false"><thead><tr><th width="176.72723388671875" valign="top"></th><th valign="top"></th></tr></thead><tbody><tr><td valign="top"><code>civilNr</code></td><td valign="top"><p>Special characters are stripped. When a user is created or updated, the <code>civilNr</code> value is automatically sanitized before saving. All characters except letters and digits are removed.</p><p>There are a few exceptions:</p><p>a)      For Finnish clients, hyphens (-) and plus signs (+) are preserved as they are part of the standard Finnish personal identity code format</p><p>b)     For Dutch clients, 8-digit numbers are automatically zero-padded to 9 digits.<br>Example: 12345678 → 012345678</p></td></tr><tr><td valign="top"><code>Address1</code></td><td valign="top">Automatically cleaned before saving: leading/trailing spaces are trimmed, multiple consecutive spaces are collapsed into one, and non-breaking spaces are converted to regular spaces.</td></tr><tr><td valign="top"><code>Address2</code></td><td valign="top">Automatically cleaned before saving: leading/trailing spaces are trimmed, multiple consecutive spaces are collapsed into one, and non-breaking spaces are converted to regular spaces.</td></tr><tr><td valign="top"><code>securityCode</code></td><td valign="top">Automatically cleaned before saving: leading/trailing spaces are trimmed, multiple consecutive spaces are collapsed into one, and non-breaking spaces are converted to regular spaces.</td></tr><tr><td valign="top"><code>firstName</code></td><td valign="top">Automatically cleaned before saving: leading/trailing spaces are trimmed, multiple consecutive spaces are collapsed into one, and non-breaking spaces are converted to regular spaces.</td></tr><tr><td valign="top"><code>lastName</code></td><td valign="top">Automatically cleaned before saving: leading/trailing spaces are trimmed, multiple consecutive spaces are collapsed into one, and non-breaking spaces are converted to regular spaces.</td></tr><tr><td valign="top"><code>fullAddress</code></td><td valign="top">This is a computed field, not stored as sent. It is automatically recalculated from <code>address1</code>, <code>city</code>, <code>postalCode</code>, and <code>country</code> as a comma-separated string.</td></tr></tbody></table>

**Blank values**\
For all the above fields, if the value is empty or whitespace-only after sanitization, it is stored as null, not as an empty string.

### Social security number/National identity number

By default, the Social security number is hidden in API responses.

* **Without the "NI number" permission:** The field is returned masked, e.g. `010120####`, showing only the date of birth (the first 6 digits) while the last 4 digits (the serial number) are hidden.
* **With the "NI number" permission:** The last 4 digits of the CPR number are also shown, so the full number is returned.

**Note:** The CPR number field itself is only visible to users who have access to edit it. The "NI number" permission solely controls whether the last 4 digits are shown or masked — it does not by itself grant access to the field.\
Without permissions:

```json
{
	"data": {
		"type": "User",
		"id": "146391",
		"attributes": {
			"civilNr": "111111####",
			"createdAt": "2016-09-09T08:22:17Z",
			"updatedAt": "2026-07-01T13:42:26Z",
			"id": "146391"
		}
	}
}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.samesystem.dev/business-guides/data-models/user.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
