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

# Onboard Your First User

> Ready to onboard and verify your first user

This guide walks you through Carbn's two-step user onboarding process: first generating user consent, then creating the verified user profile.

### Understanding User Types

Carbn supports two primary user types:

* **Individual Users**: Personal accounts requiring identity verification and consent
* **Business Users**: Corporate accounts requiring business verification and beneficial ownership details

***

## Step-by-Step Onboarding

<Steps>
  <Step title="Generate User Consent">
    Before creating a user, you must first generate a consent record. This captures the user's acceptance of terms and conditions and generates a consent ID that's required for user creation.

    ### Why Consent is Required

    User consent is a critical compliance requirement that:

    * **Legal Protection**: Establishes clear user agreement to terms of service
    * **Regulatory Compliance**: Meets KYC/AML requirements for financial services
    * **Audit Trail**: Creates verifiable record of user consent with timestamps
    * **Risk Management**: Ensures users understand their obligations and rights

    ### Requirements for Consent

    * User must actively accept current terms and conditions
    * Timestamp must be recorded at time of acceptance
    * Consent must be obtained before any user data processing

    <Note>
      The user must be shown a clear message where they consent to accept the terms and conditions during onborading.
    </Note>

    <CodeGroup>
      ```bash cURL theme={null}
      curl --location --request POST 'https://api.carbnconnect.com/onboarding/api/v1/tnc' \
      --header 'Content-Type: application/json' \
      --header 'x-api-key: <api-key>' \
      --data-raw '{
        "tnc_data": {
          "tnc_accepted": true,
          "accepted_at": "2024-01-01T12:00:00Z"
        }
      }'
      ```

      ```javascript JavaScript theme={null}
      const response = await fetch('https://api.carbnconnect.com/onboarding/api/v1/tnc', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'x-api-key': '<api-key>'
        },
        body: JSON.stringify({
          tnc_data: {
            tnc_accepted: true,
            accepted_at: new Date().toISOString()
          }
        })
      });
      ```

      ```python Python theme={null}
      import requests
      from datetime import datetime

      headers = {
          'Content-Type': 'application/json',
          'x-api-key': '<api-key>'
      }

      data = {
          "tnc_data": {
              "tnc_accepted": True,
              "accepted_at": datetime.utcnow().isoformat() + "Z"
          }
      }

      response = requests.post(
          'https://api.carbnconnect.com/onboarding/api/v1/tnc',
          headers=headers,
          json=data
      )
      ```
    </CodeGroup>

    <CodeGroup>
      ```json Response theme={null}
      "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
      ```
    </CodeGroup>

    The response is a unique consent ID (UUID) that you'll use in the next step. Store this securely as it's required for user creation.

    ### Importance of Consent

    * **Required Parameter**: The consent ID is mandatory for all user creation requests
    * **Compliance Link**: Connects user profiles to their consent records
    * **Audit Trail**: Enables tracking of consent to user relationship
    * **Legal Requirement**: Proves user agreed to terms before account creation
  </Step>

  <Step title="Create User Profile">
    Now create the user profile using the consent ID from the previous step. This establishes the user's identity within the Carbn network and links them to their consent record.

    ### Understanding Document Types

    The user creation request includes two distinct document categories:

    * **Identity Documents** (`identity` object): Primary identification documents like national ID, passport, or driver's license that prove the user's identity
    * **Supporting Documents** (`documents` array): Additional documents that support the user's profile, such as proof of address, tax documents, or source of funds verification

    <Note>
      Make sure to use the `consent_id` from previous step in your request.
    </Note>

    <CodeGroup>
      ```bash cURL theme={null}
      curl --location --request POST 'https://api.carbnconnect.com/onboarding/api/v1/users' \
      --header 'Content-Type: application/json' \
      --header 'x-api-key: <api-key>' \
      --header 'Idempotency-Key: <generate-a-uuid>' \
      --data-raw '{
        "first_name": "John",
        "last_name": "Doe",
        "email_address": "john.doe@example.com",
        "phone_number": "+1234567890",
        "user_type": "individual",
        "date_of_birth": "1990-01-01",
        "consent_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
        "metadata": "{}",
        "sharing_consent": true,
        "identity": {
          "identity_country_code": "DEU",
          "identity_number": "XXXXXXXXXXXX",
          "identity_document_name": "permanent_residency_id",
          "identity_document_front": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD...",
          "identity_document_back": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD..."
        },
        "documents": [
          {
            "name": "steuer_id",
            "type": "tax_document",
            "issuing_country": "DEU",
            "document_number": "<string>",
            "document_front": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD...",
            "document_back": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD..."
          }
        ],
        "address": {
          "line1": "123 Main Street",
          "city": "City Name",
          "sub_division": "ST",
          "country": "DEU",
          "postal_code": "12345"
        }
      }'
      ```

      ```javascript JavaScript theme={null}
      const response = await fetch('https://api.carbnconnect.com/onboarding/api/v1/users', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'x-api-key': '<api-key>',
          'Idempotency-Key': '<generate-a-uuid>'
        },
        body: JSON.stringify({
          first_name: "John",
          last_name: "Doe",
          email_address: "john.doe@example.com",
          phone_number: "+1234567890",
          user_type: "individual",
          date_of_birth: "1990-01-01",
          consent_id: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", // From Step 1
          metadata: "{}",
          sharing_consent: true,
          identity: {
            identity_country_code: "DEU",
            identity_number: "XXXXXXXXXXXX",
            identity_document_name: "permanent_residency_id",
            identity_document_front: "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD...",
            identity_document_back: "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD..."
          },
          documents: [
            {
              name: "steuer_id",
              type: "tax_document",
              issuing_country: "DEU",
              document_number: "<string>",
              document_front: "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD...",
              document_back: "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD..."
            }
          ],
          address: {
            line1: "123 Main Street",
            city: "City Name",
            sub_division: "ST",
            country: "DEU",
            postal_code: "12345"
          }
        })
      });
      ```

      ```python Python theme={null}
      import requests

      headers = {
          'Content-Type': 'application/json',
          'x-api-key': '<api-key>',
          'Idempotency-Key': '<generate-a-uuid>'
      }

      data = {
          "first_name": "John",
          "last_name": "Doe",
          "email_address": "john.doe@example.com",
          "phone_number": "+1234567890",
          "user_type": "individual",
          "date_of_birth": "1990-01-01",
          "consent_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",  # From Step 1
          "metadata": "{}",
          "sharing_consent": True,
          "identity": {
              "identity_country_code": "DEU",
              "identity_number": "XXXXXXXXXXXX",
              "identity_document_name": "permanent_residency_id",
              "identity_document_front": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD...",
              "identity_document_back": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD..."
          },
          "documents": [
              {
                  "name": "steuer_id",
                  "type": "tax_document",
                  "issuing_country": "DEU",
                  "document_number": "<string>",
                  "document_front": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD...",
                  "document_back": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD..."
              }
          ],
          "address": {
              "line1": "123 Main Street",
              "city": "City Name",
              "sub_division": "ST",
              "country": "DEU",
              "postal_code": "12345"
          }
      }

      response = requests.post(
          'https://api.carbnconnect.com/onboarding/api/v1/users',
          headers=headers,
          json=data
      )
      ```
    </CodeGroup>

    <CodeGroup>
      ```json Response theme={null}
      {
        "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
        "status": "under_review",
        "documents": [
          {
            "name": "national_id",
            "type": "identity_front"
          },
          {
            "name": "national_id", 
            "type": "identity_back"
          },
          {
            "name": "steuer_id",
            "type": "tax_document"
          }
        ],
        "first_name": "John",
        "last_name": "Doe",
        "email_address": "john.doe@example.com",
        "phone_number": "+1234567890",
        "date_of_birth": "1990-01-01",
        "address": {
          "line1": "123 Main Street",
          "city": "City Name",
          "sub_division": "ST",
          "country": "DEU",
          "postal_code": "12345"
        },
        "rejection_reasons": null,
        "requirements": null
      }
      ```
    </CodeGroup>
  </Step>
</Steps>

***

## Checking User Status

After creating a user, you can retrieve their current status and details using the GET user endpoint. This endpoint returns the exact same response format as the create and update user endpoints.

<CodeGroup>
  ```bash Get User Details theme={null}
  curl --location --request GET 'https://api.carbnconnect.com/onboarding/api/v1/users/{user_id}' \
  --header 'x-api-key: <api-key>'
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch(`https://api.carbnconnect.com/onboarding/api/v1/users/${userId}`, {
    method: 'GET',
    headers: {
      'x-api-key': '<api-key>'
    }
  });
  ```

  ```python Python theme={null}
  import requests

  headers = {
      'x-api-key': '<api-key>'
  }

  response = requests.get(
      f'https://api.carbnconnect.com/onboarding/api/v1/users/{user_id}',
      headers=headers
  )
  ```
</CodeGroup>

### Understanding User Status Values

The response will include a `status` field that indicates the current state of the user's verification:

<CodeGroup>
  ```json Active User theme={null}
  {
    "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "status": "active",
    "documents": [
      {
        "name": "national_id",
        "type": "identity_front"
      },
      {
        "name": "national_id", 
        "type": "identity_back"
      },
      {
        "name": "steuer_id",
        "type": "tax_document"
      }
    ],
    "first_name": "John",
    "last_name": "Doe",
    "email_address": "john.doe@example.com",
    "phone_number": "+1234567890",
    "date_of_birth": "1990-01-01",
    "address": {
      "line1": "123 Main Street",
      "city": "City Name",
      "sub_division": "ST",
      "country": "DEU",
      "postal_code": "12345"
    },
    "rejection_reasons": null,
    "requirements": null
  }
  ```

  ```json Under Review theme={null}
  {
    "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "status": "under_review",
    "documents": [
      {
        "name": "national_id",
        "type": "identity_front"
      },
      {
        "name": "national_id", 
        "type": "identity_back"
      },
      {
        "name": "steuer_id",
        "type": "tax_document"
      }
    ],
    "first_name": "John",
    "last_name": "Doe",
    "email_address": "john.doe@example.com",
    "phone_number": "+1234567890",
    "date_of_birth": "1990-01-01",
    "address": {
      "line1": "123 Main Street",
      "city": "City Name",
      "sub_division": "ST",
      "country": "DEU",
      "postal_code": "12345"
    },
    "rejection_reasons": null,
    "requirements": null
  }
  ```

  ```json Rejected User theme={null}
  {
    "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "status": "rejected",
    "documents": [
      {
        "name": "national_id",
        "type": "identity_front"
      },
      {
        "name": "national_id", 
        "type": "identity_back"
      },
      {
        "name": "steuer_id",
        "type": "tax_document"
      }
    ],
    "first_name": "John",
    "last_name": "Doe",
    "email_address": "john.doe@example.com",
    "phone_number": "+1234567890",
    "date_of_birth": "1990-01-01",
    "address": {
      "line1": "123 Main Street",
      "city": "City Name",
      "sub_division": "ST",
      "country": "DEU",
      "postal_code": "12345"
    },
    "rejection_reasons": [
      {
        "reason": "Your information could not be verified",
        "created_at": "2025-09-09T11:46:22.037Z",
        "developer_reason": "ID cannot be verified against third-party databases"
      },
      {
        "reason": "Cannot validate ID, upload a clear photo of the full ID",
        "created_at": "2025-09-09T11:47:15.142Z", 
        "developer_reason": "Missing or incomplete barcode on the ID."
      }
    ],
    "requirements": null
  }
  ```

  ```json Incomplete User theme={null}
  {
    "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "status": "incomplete",
    "documents": [
      {
        "name": "national_id",
        "type": "identity_front"
      },
      {
        "name": "national_id", 
        "type": "identity_back"
      }
    ],
    "first_name": "John",
    "last_name": "Doe",
    "email_address": "john.doe@example.com",
    "phone_number": "+1234567890",
    "date_of_birth": "1990-01-01",
    "address": {
      "line1": "123 Main Street",
      "city": "City Name",
      "sub_division": "ST",
      "country": "DEU",
      "postal_code": "12345"
    },
    "rejection_reasons": null,
    "requirements": ["tax_identification_number"]
  }
  ```
</CodeGroup>

### Status Explanations

<AccordionGroup>
  <Accordion title="active" icon="circle-check" defaultOpen>
    User has passed verification and can begin transacting. All required documents have been approved and the user is ready to use all platform features.

    **Key Characteristics:**

    * All KYC checks completed successfully
    * User can initiate transactions
  </Accordion>

  <Accordion title="under_review" icon="clock">
    Verification is in progress. Our compliance team is reviewing the submitted documents. This typically takes 2-5 minutes for automated approval.

    **Key Characteristics:**

    * Initial status when user is created
    * Documents are being processed
    * Automated checks in progress
    * User should wait for status update
  </Accordion>

  <Accordion title="rejected" icon="circle-x">
    Verification failed due to document or data issues. The `rejection_reasons` array contains detailed rejection objects with user-safe messages, timestamps, and internal developer reasons.

    **Key Characteristics:**

    * KYC verification failed
    * `rejection_reasons` array populated with detailed objects
    * Each rejection includes `reason`, `created_at`, and `developer_reason`
    * User needs to resubmit with corrections

    <Warning>
      Only share the `reason` field with end users. The `developer_reason` may contain sensitive information.
    </Warning>
  </Accordion>

  <Accordion title="incomplete" icon="circle-alert">
    Missing required information or documents. The `requirements` field lists what's needed to complete the user profile.

    **Key Characteristics:**

    * User profile is missing required data
    * `requirements` array shows what's needed
    * User must provide additional information
    * Status will change once requirements are met

    **Next Steps:**

    * Use the PUT `/onboarding/api/v1/users/{user_id}` endpoint to update user details
    * Provide the missing information listed in the `requirements` array
    * Include any additional documents or data needed
  </Accordion>
</AccordionGroup>

***

## Updating User Information

If a user needs to update their information (due to rejection or incomplete status), use the PUT endpoint to modify their details:

<CodeGroup>
  ```bash Update User theme={null}
  curl --location --request PUT 'https://api.carbnconnect.com/onboarding/api/v1/users/{user_id}' \
  --header 'Content-Type: application/json' \
  --header 'x-api-key: <api-key>' \
  --data-raw '{
    "identity": {
      "identity_document_front": "data:image/jpeg;base64,NEW_FRONT_IMAGE...",
      "identity_document_back": "data:image/jpeg;base64,NEW_BACK_IMAGE..."
    },
    "documents": [
      {
        "name": "steuer_id",
        "type": "tax_document",
        "issuing_country": "DEU",
        "document_number": "NEW_DOCUMENT_NUMBER",
        "document_front": "data:image/jpeg;base64,NEW_DOC_FRONT...",
        "document_back": "data:image/jpeg;base64,NEW_DOC_BACK..."
      }
    ]
  }'
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch(`https://api.carbnconnect.com/onboarding/api/v1/users/${userId}`, {
    method: 'PUT',
    headers: {
      'Content-Type': 'application/json',
      'x-api-key': '<api-key>'
    },
    body: JSON.stringify({
      identity: {
        identity_document_front: "data:image/jpeg;base64,NEW_FRONT_IMAGE...",
        identity_document_back: "data:image/jpeg;base64,NEW_BACK_IMAGE..."
      },
      documents: [
        {
          name: "steuer_id",
          type: "tax_document",
          issuing_country: "DEU",
          document_number: "NEW_DOCUMENT_NUMBER",
          document_front: "data:image/jpeg;base64,NEW_DOC_FRONT...",
          document_back: "data:image/jpeg;base64,NEW_DOC_BACK..."
        }
      ]
    })
  });
  ```

  ```python Python theme={null}
  import requests

  headers = {
      'Content-Type': 'application/json',
      'x-api-key': '<api-key>'
  }

  data = {
      "identity": {
          "identity_document_front": "data:image/jpeg;base64,NEW_FRONT_IMAGE...",
          "identity_document_back": "data:image/jpeg;base64,NEW_BACK_IMAGE..."
      },
      "documents": [
          {
              "name": "steuer_id",
              "type": "tax_document",
              "issuing_country": "DEU",
              "document_number": "NEW_DOCUMENT_NUMBER",
              "document_front": "data:image/jpeg;base64,NEW_DOC_FRONT...",
              "document_back": "data:image/jpeg;base64,NEW_DOC_BACK..."
          }
      ]
  }

  response = requests.put(
      f'https://api.carbnconnect.com/onboarding/api/v1/users/{user_id}',
      headers=headers,
      json=data
  )
  ```
</CodeGroup>

<Info>
  The PUT endpoint accepts the same fields as the POST endpoint, but all fields are optional. Only include the fields you want to update. The response format is identical to the GET and POST endpoints.
</Info>

***

## What's Next?

After successfully onboarding your first user, here are the essential topics to master:

<CardGroup cols={2}>
  <Card title="Rejection Reasons" icon="circle-x" href="/documentation/developer-platform/users/compliance/rejection-reasons" arrow="true">
    Understand all possible rejection reasons and how to handle them effectively
  </Card>

  <Card title="Enhanced Due Diligence" icon="shield-check" href="/documentation/developer-platform/users/compliance/enhanced-due-diligence" arrow="true">
    Learn about additional verification requirements for high-risk users
  </Card>
</CardGroup>

<CardGroup cols={2}>
  <Card title="Understanding Compliance" icon="scale" href="/documentation/developer-platform/users/compliance/overview" arrow="true">
    Deep dive into KYC/AML requirements and regulatory compliance
  </Card>

  <Card title="Setup Webhook" icon="webhook" href="/documentation/getting-started/configure-webhook" arrow="true">
    Configure real-time notifications for user status changes and events
  </Card>
</CardGroup>

## Getting Help

<Columns cols={1}>
  <Card title="Contact Support" icon="headset" href="mailto:support@carbn.xyz" arrow="true">
    When contacting support, please include:
    <Check>**User ID** from the response</Check>
    <Check>**Endpoint** you were trying to access</Check>
    <Check>**Error** response details available</Check>
    <Check>**Timestamp** when the error occurred</Check>
  </Card>
</Columns>
