> ## Documentation Index
> Fetch the complete documentation index at: https://docs-api.kravata.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Update User

> Updates part of the data of one of your users without sending the full registration again. Only the fields you send with a value change; everything else stays as it is.

#### Request

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| Authorization | Header | Yes | `Bearer <access_token>` obtained from **POST /api/v1/client/token**. |
| user_id | Path | Yes | Identifier of the user. |

#### Request body

All fields are optional. Send at least one.

| Field | Type | Description |
| --- | --- | --- |
| tradeName | String | Display name of the user. |
| person.firstName, person.middleName, person.firstSurname, person.lastName, person.businessName | String | Name fields of the person. |
| person.pep | Boolean | Whether the user is a Politically Exposed Person. It is stored if the user has no PEP declaration yet. Sending the same value again changes nothing; a different value is rejected with `422`. |
| person.identificationType, person.identificationNro, person.verificateDigit | String | The identity document cannot be changed. You can send the current values, but any different value is rejected with `422`. |
| person.contactsData | Array | Contacts to update. Each item has `dataTypeContact` (`EMAIL`, `PHONE` or `ADDRESS`), `dataValue` and optionally `isVerified`. Each type can appear only once. An item with only `isVerified` (no `dataValue`) changes just the verification of that contact; if the user doesn't have that contact, it is rejected with `422`. |
| person.additionalInfo | Array | Additional fields to update. Each item has `infoName` and `infoValue`. |

#### How the update works

- Fields that are not listed here are rejected with `422` (`extra_forbidden`, "field not allowed"), even if their value is `null`. Email and phone go in `person.contactsData`.
- A field that is missing, `null` or empty is ignored. Nothing is ever deleted through this endpoint.
- Contacts are matched by type and additional fields by name: an existing one is replaced, a new one is created.
- `PHONE` must be in E.164 format (for example `+573001234567`) and `EMAIL` must be a valid email address. The format is checked only for values that change; sending the current value again is accepted.
- A phone number or email cannot belong to another user of your company (`409`).
- If you change the value of a contact and don't send `isVerified`, the contact is marked as not verified. If an email differs only in upper/lower case, the stored email is updated and its verification is kept.
- The user's `status` never changes with this endpoint.
- Fields managed by Kravata cannot be changed and are rejected with `422`: any `additionalInfo` name that starts with `TERMS ` or `POLICY ` (terms and policy acceptance), KYC session and results, the KYC form completion date and the country of residence.
- `DEPARTMENT` and `CITY_HOME` must be a valid department and city of the user's country of residence.
- Name, email and phone changes are also applied to the user's login profile. If that fails, nothing is updated and you get `502`.
- Kravata keeps a history of the previous values and sends the `user.updated` webhook when something changes. If nothing changes, the response is `200` with the current data and no webhook is sent.

#### Response

The updated user: `id`, `status`, `tradeName` and `person` (names, identification, `contactsData` and `additionalInfo`).

#### Errors

Errors use the body `{"error": {"code", "message", "request_id", "details"}}`; `details` is present on validation errors.

| Status | Code | When |
| --- | --- | --- |
| 400 | `BAD_REQUEST` | The request is not valid. |
| 404 | `NOT_FOUND` | The user does not exist in your company. |
| 409 | `EMAIL_IN_USE` | The email belongs to another user. |
| 409 | `PHONE_IN_USE` | The phone belongs to another user. |
| 409 | `CONFLICT` | Another request is changing the same email or phone at that moment. Wait a few seconds and retry the same request. |
| 422 | `VALIDATION_ERROR` | Invalid format, duplicated contact type or field name, protected field, document change, unknown field, or invalid department/city. `details` lists each field. |
| 422 | `INVALID_PROFILE_DATA` | The profile data was rejected when updating the user's login profile. |
| 502 | `UPSTREAM_ERROR` | A service that Kravata depends on failed. Nothing was updated; retry the request. |



## OpenAPI

````yaml /stack/openapi.json patch /api/v1/provider/users/{user_id}
openapi: 3.1.0
info:
  title: Kravata Stack API
  version: '2.0'
  description: >-
    Kravata Stack API: users, accounts, custody wallets, liquidity ramps and
    fiat payments.
servers:
  - url: https://test-api-kore.kravata.co
    description: Test
  - url: https://partners-api.kravata.co
    description: Production (mTLS + IP allowlist)
security:
  - bearerAuth: []
tags:
  - name: Authentication
  - name: Users
  - name: Accounts
  - name: Earn
  - name: Custody
  - name: Liquidity Ramps
  - name: Payments
  - name: Webhooks
  - name: Request Logs
paths:
  /api/v1/provider/users/{user_id}:
    patch:
      tags:
        - Users
      summary: Update User
      description: >-
        Updates part of the data of one of your users without sending the full
        registration again. Only the fields you send with a value change;
        everything else stays as it is.


        #### Request


        | Field | Type | Required | Description |

        | --- | --- | --- | --- |

        | Authorization | Header | Yes | `Bearer <access_token>` obtained from
        **POST /api/v1/client/token**. |

        | user_id | Path | Yes | Identifier of the user. |


        #### Request body


        All fields are optional. Send at least one.


        | Field | Type | Description |

        | --- | --- | --- |

        | tradeName | String | Display name of the user. |

        | person.firstName, person.middleName, person.firstSurname,
        person.lastName, person.businessName | String | Name fields of the
        person. |

        | person.pep | Boolean | Whether the user is a Politically Exposed
        Person. It is stored if the user has no PEP declaration yet. Sending the
        same value again changes nothing; a different value is rejected with
        `422`. |

        | person.identificationType, person.identificationNro,
        person.verificateDigit | String | The identity document cannot be
        changed. You can send the current values, but any different value is
        rejected with `422`. |

        | person.contactsData | Array | Contacts to update. Each item has
        `dataTypeContact` (`EMAIL`, `PHONE` or `ADDRESS`), `dataValue` and
        optionally `isVerified`. Each type can appear only once. An item with
        only `isVerified` (no `dataValue`) changes just the verification of that
        contact; if the user doesn't have that contact, it is rejected with
        `422`. |

        | person.additionalInfo | Array | Additional fields to update. Each item
        has `infoName` and `infoValue`. |


        #### How the update works


        - Fields that are not listed here are rejected with `422`
        (`extra_forbidden`, "field not allowed"), even if their value is `null`.
        Email and phone go in `person.contactsData`.

        - A field that is missing, `null` or empty is ignored. Nothing is ever
        deleted through this endpoint.

        - Contacts are matched by type and additional fields by name: an
        existing one is replaced, a new one is created.

        - `PHONE` must be in E.164 format (for example `+573001234567`) and
        `EMAIL` must be a valid email address. The format is checked only for
        values that change; sending the current value again is accepted.

        - A phone number or email cannot belong to another user of your company
        (`409`).

        - If you change the value of a contact and don't send `isVerified`, the
        contact is marked as not verified. If an email differs only in
        upper/lower case, the stored email is updated and its verification is
        kept.

        - The user's `status` never changes with this endpoint.

        - Fields managed by Kravata cannot be changed and are rejected with
        `422`: any `additionalInfo` name that starts with `TERMS ` or `POLICY `
        (terms and policy acceptance), KYC session and results, the KYC form
        completion date and the country of residence.

        - `DEPARTMENT` and `CITY_HOME` must be a valid department and city of
        the user's country of residence.

        - Name, email and phone changes are also applied to the user's login
        profile. If that fails, nothing is updated and you get `502`.

        - Kravata keeps a history of the previous values and sends the
        `user.updated` webhook when something changes. If nothing changes, the
        response is `200` with the current data and no webhook is sent.


        #### Response


        The updated user: `id`, `status`, `tradeName` and `person` (names,
        identification, `contactsData` and `additionalInfo`).


        #### Errors


        Errors use the body `{"error": {"code", "message", "request_id",
        "details"}}`; `details` is present on validation errors.


        | Status | Code | When |

        | --- | --- | --- |

        | 400 | `BAD_REQUEST` | The request is not valid. |

        | 404 | `NOT_FOUND` | The user does not exist in your company. |

        | 409 | `EMAIL_IN_USE` | The email belongs to another user. |

        | 409 | `PHONE_IN_USE` | The phone belongs to another user. |

        | 409 | `CONFLICT` | Another request is changing the same email or phone
        at that moment. Wait a few seconds and retry the same request. |

        | 422 | `VALIDATION_ERROR` | Invalid format, duplicated contact type or
        field name, protected field, document change, unknown field, or invalid
        department/city. `details` lists each field. |

        | 422 | `INVALID_PROFILE_DATA` | The profile data was rejected when
        updating the user's login profile. |

        | 502 | `UPSTREAM_ERROR` | A service that Kravata depends on failed.
        Nothing was updated; retry the request. |
      operationId: update-user
      parameters:
        - name: user_id
          in: path
          required: true
          description: Identifier of the user.
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                tradeName:
                  type: string
                person:
                  type: object
                  properties:
                    firstName:
                      type: string
                    middleName:
                      type: string
                    firstSurname:
                      type: string
                    lastName:
                      type: string
                    businessName:
                      type: string
                    pep:
                      type: boolean
                    contactsData:
                      type: array
                      items:
                        type: object
                        required:
                          - dataTypeContact
                        properties:
                          dataTypeContact:
                            type: string
                            enum:
                              - EMAIL
                              - PHONE
                              - ADDRESS
                          dataValue:
                            type: string
                          isVerified:
                            type: boolean
                        additionalProperties: false
                    additionalInfo:
                      type: array
                      items:
                        type: object
                        required:
                          - infoName
                        properties:
                          infoName:
                            type: string
                          infoValue: {}
                        additionalProperties: false
                    verificateDigit:
                      type: string
                  additionalProperties: false
              additionalProperties: false
            examples:
              update-user:
                summary: Update email and phone
                value:
                  person:
                    contactsData:
                      - dataTypeContact: EMAIL
                        dataValue: john.doe@example.com
                      - dataTypeContact: PHONE
                        dataValue: '+573009876543'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: string
                  status:
                    type: string
                  tradeName:
                    type: string
                  person:
                    type: object
              examples:
                update-user:
                  summary: Update User
                  value:
                    id: 3f1a9c2e-7b6d-4e11-9a3f-2c8d6e0b5a17
                    status: APPROVED
                    tradeName: John Doe
                    person:
                      id: 3f1a9c2e-7b6d-4e11-9a3f-2c8d6e0b5a17
                      firstName: John
                      firstSurname: Doe
                      identificationType: CC
                      identificationNro: '1029384756'
                      contactsData:
                        - dataTypeContact: EMAIL
                          dataValue: john.doe@example.com
                          isVerified: false
                        - dataTypeContact: PHONE
                          dataValue: '+573009876543'
                          isVerified: false
                      additionalInfo: []
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: Access token from POST /api/v1/client/token.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.