---
title: "Upsert up to 50 users at a time based on nectar_id (recommended), email, or employee_id"
method: PUT
path: "/v1/users"
---

# Upsert up to 50 users at a time based on nectar_id (recommended), email, or employee_id

`PUT /v1/users`

Creates or updates users. Supports inviting users via the `user_invited` field and `send_invites` query parameter.

**Invite behavior:**
- Setting `user_invited: true` on a user in the request body will mark that user as invited in the database.
- Invite emails are **only sent** when `send_invites=true` is passed as a query parameter.
- When `send_invites=true`, invite emails are sent to all users that have `user_invited: true` **in the current request body**,
  including users that were already invited previously.

- When `send_invites=false` or omitted, `user_invited: true` still updates the database, but no emails are sent.
- `user_invited` can only be set to `true`. Setting it to `false` is not allowed and will return an error.
- The response includes an `invite_email_sent` field for each user indicating whether an invite email was sent during this request.

**Duplicate identifiers:**
- When multiple users in the request share the same `email`, `employee_id`, or `phone_number`, the request still returns 200
  but the response `warnings` array describes which duplicates were detected and how they were handled.

- Duplicate `email` or `employee_id`: all users sharing that value are skipped (not created or updated).
- Duplicate `phone_number`: if the user has another identifier (email, employee_id, nectar_id), the phone number is stripped
  and the user is still processed; otherwise the user is skipped.

- Callers should inspect `warnings` after every upsert to reconcile their source data.

## Query parameters

- `expand` string[]
- `lookup_keys` string[]
- `send_invites` boolean

## Request body

- UserUpsertBody[]
  - `email` string, email
  - `nectar_id` string
  - `first_name` string
  - `last_name` string
  - `employee_id` string
  - `department` string, nullable
  - `office_location` string, nullable
  - `job_title` string, nullable
  - `active` boolean
  - `phone_number` string, nullable
  - `inactive_date` string, date, nullable
  - `hire_date` string, date, nullable
  - `birth_date` string, date, nullable
  - `preferred_name` string, nullable
  - `manager_email` string, email, nullable
  - `language` string, nullable
  - `role` 'Administrator' | 'Manager' | 'Employee' — Nectar platform permission role. This controls access permissions within Nectar, not the user's company or HRIS role. Administrator: full admin access (also grants Manager permissions). Manager: receives a manager-level point allowance and can access analytics for direct reports. Employee: standard user with an employee-level point allowance. Warning: sending this field on an update will overwrite the user's existing role. Omit this field to preserve the current role.
  - `custom_properties` object
  - `user_invited` boolean — Set to true to mark the user as invited. Can only be set to true (setting to false will return an error). When combined with the send_invites query parameter, an invite email will be sent to the user. Without send_invites, the user will be marked as invited in the database but no email will be sent.

## Response `200`

OK

- object
  - `status` 'success'
  - `links` Links
    - `self` string, uri
    - `related` object[]
      - `type` string
      - `href` string, uri
  - `data` object
    - `total` integer
    - `users` union[]
      - union
        - BaseUser
          - `id` string
          - `email` string, email
          - `employee_id` string, nullable
          - `first_name` string
          - `last_name` string
          - `username` string
          - `phone_number` string, nullable
          - `department` string, nullable
          - `office_location` string, nullable
          - `job_title` string, nullable
          - `language` string, nullable
          - `active` boolean
          - `invite_email_sent` boolean — Indicates whether an invite email was sent for this user during this request. Only present in PUT responses. Returns true when the send_invites query parameter is present and user_invited is true in the request body for this user.
          - `self` string, uri
          - `related` object[]
            - `type` string
            - `href` string, uri
        - ExpandedUser
          - `id` string
          - `email` string, email
          - `employee_id` string, nullable
          - `first_name` string
          - `last_name` string
          - `username` string
          - `phone_number` string, nullable
          - `department` string, nullable
          - `office_location` string, nullable
          - `job_title` string, nullable
          - `language` string, nullable
          - `active` boolean
          - `invite_email_sent` boolean — Indicates whether an invite email was sent for this user during this request. Only present in PUT responses. Returns true when the send_invites query parameter is present and user_invited is true in the request body for this user.
          - `self` string, uri
          - `related` object[]
            - `type` string
            - `href` string, uri
          - `user_role` 'Administrator' | 'Manager' | 'Employee'
          - `preferred_name` string, nullable
          - `birth_date` string, nullable
          - `hire_date` string, date, nullable
          - `inactive_date` string, date, nullable
          - `user_invited` boolean
          - `user_onboarded` boolean
          - `manager_email` string, email, nullable
          - `workspaces` string[]
          - `giveable_points` number
          - `redeemable_points` number
          - `logged_in_once` boolean
          - `custom_properties` object
    - `warnings` string[] — Non-fatal issues detected while processing the request (e.g., duplicate email, employee_id, or phone_number values within the batch). The request still succeeds, but affected users may have been skipped or had fields stripped. Review these to reconcile your source data.

## Other responses

- `400` — `BAD REQUEST`: Body or Query Params are malformed (missing, extra, or invalid values)
- `401` — `UNAUTHORIZED`: Request was sent with an expired or missing API Key
- `403` — `FORBIDDEN`: Request was authenticated but the resource requested is missing or not accessible with that key
- `404` — `NOT FOUND`: The requested resource was not found
- `429` — `TOO MANY REQUESTS`: Company is being rate limited
- `500` — `INTERNAL SERVER ERROR`: Request was unable to be processed due to a server error. Contact our support team.
- `501` — `NOT IMPLEMENTED`: Method is not implemented on that endpoint.

---

[API](https://skmtc.net/nectarhr/apis/nectar-public-api.md) · [All operations](https://skmtc.net/nectarhr/apis/nectar-public-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/nectarhr/nectar-public-api/revisions/c0dcbcafc495/schema)
