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

# Create Customer

> Create a new customer record with comprehensive validation and optional integrations

<Note>
  This endpoint creates a new customer and can optionally create associated accounts in integrated systems like Stripe.
</Note>

## Request Body

<ParamField body="email" type="string" required>
  Customer's email address. Must be unique and valid format.

  **Example:** `customer@example.com`
</ParamField>

<ParamField body="first_name" type="string" required>
  Customer's first name. Must be 1-50 characters.

  **Example:** `John`
</ParamField>

<ParamField body="last_name" type="string" required>
  Customer's last name. Must be 1-50 characters.

  **Example:** `Doe`
</ParamField>

<ParamField body="phone" type="string">
  Customer's phone number in E.164 format (recommended) or local format.

  **Examples:** `+1-555-123-4567`, `(555) 123-4567`
</ParamField>

<ParamField body="date_of_birth" type="string">
  Customer's date of birth in ISO 8601 format (YYYY-MM-DD).

  **Example:** `1990-05-15`
</ParamField>

<ParamField body="address" type="object">
  Customer's primary address information.

  <Expandable title="Address Properties">
    <ParamField body="street1" type="string" required>
      Primary street address
    </ParamField>

    <ParamField body="street2" type="string">
      Secondary address line (apartment, suite, etc.)
    </ParamField>

    <ParamField body="city" type="string" required>
      City name
    </ParamField>

    <ParamField body="state" type="string" required>
      State or province code (e.g., "CA", "NY", "ON")
    </ParamField>

    <ParamField body="postal_code" type="string" required>
      ZIP or postal code
    </ParamField>

    <ParamField body="country" type="string" required>
      ISO 3166-1 alpha-2 country code (e.g., "US", "CA", "GB")
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="marketing_consent" type="boolean" default="false">
  Whether the customer has consented to marketing communications.
</ParamField>

<ParamField body="customer_tier" type="string" default="bronze">
  Customer tier for loyalty programs. Options: `bronze`, `silver`, `gold`, `platinum`
</ParamField>

<ParamField body="referral_source" type="string">
  How the customer found your business.

  **Options:** `organic`, `paid_search`, `social_media`, `referral`, `email`, `direct`, `other`
</ParamField>

<ParamField body="stripe_customer_id" type="string">
  Existing Stripe customer ID if you're syncing with an external Stripe account.

  **Note:** If not provided and Stripe integration is enabled, a new Stripe customer will be created automatically.
</ParamField>

<ParamField body="notes" type="string">
  Internal notes about the customer (not visible to customer).

  **Max length:** 1000 characters
</ParamField>

<ParamField body="tags" type="array">
  Array of tags for customer segmentation and organization.

  **Example:** `["vip", "wholesale", "early-adopter"]`
</ParamField>

<ParamField body="custom_fields" type="object">
  Additional custom fields as key-value pairs. Keys must be alphanumeric with underscores.

  **Example:**

  ```json theme={null}
  {
    "company_name": "Acme Corp",
    "industry": "Technology",
    "employee_count": "50-100"
  }
  ```
</ParamField>

<ParamField body="preferences" type="object">
  Customer communication preferences.

  <Expandable title="Preference Properties">
    <ParamField body="email_notifications" type="boolean" default="true">
      Allow email notifications
    </ParamField>

    <ParamField body="sms_notifications" type="boolean" default="false">
      Allow SMS notifications
    </ParamField>

    <ParamField body="language" type="string" default="en">
      Preferred language (ISO 639-1 code)
    </ParamField>

    <ParamField body="timezone" type="string" default="UTC">
      Customer's timezone (IANA timezone identifier)
    </ParamField>
  </Expandable>
</ParamField>

## Response

<ResponseField name="id" type="string">
  Unique identifier for the created customer

  **Example:** `cust_1NXWPnCo6bFb1KQto6C8OWvE`
</ResponseField>

<ResponseField name="email" type="string">
  Customer's email address
</ResponseField>

<ResponseField name="first_name" type="string">
  Customer's first name
</ResponseField>

<ResponseField name="last_name" type="string">
  Customer's last name
</ResponseField>

<ResponseField name="full_name" type="string">
  Customer's full name (computed field)
</ResponseField>

<ResponseField name="phone" type="string">
  Customer's phone number
</ResponseField>

<ResponseField name="date_of_birth" type="string">
  Customer's date of birth
</ResponseField>

<ResponseField name="address" type="object">
  Customer's address information
</ResponseField>

<ResponseField name="customer_tier" type="string">
  Customer's loyalty tier
</ResponseField>

<ResponseField name="marketing_consent" type="boolean">
  Marketing consent status
</ResponseField>

<ResponseField name="stripe_customer_id" type="string">
  Associated Stripe customer ID (if Stripe integration is enabled)
</ResponseField>

<ResponseField name="created_at" type="string">
  ISO 8601 timestamp when the customer was created
</ResponseField>

<ResponseField name="updated_at" type="string">
  ISO 8601 timestamp when the customer was last updated
</ResponseField>

<ResponseField name="status" type="string">
  Customer status: `active`, `inactive`, `suspended`
</ResponseField>

<ResponseField name="lifetime_value" type="number">
  Customer's lifetime value (computed from order history)
</ResponseField>

<ResponseField name="total_orders" type="integer">
  Total number of orders placed by this customer
</ResponseField>

<ResponseField name="tags" type="array">
  Array of customer tags
</ResponseField>

<ResponseField name="custom_fields" type="object">
  Custom field key-value pairs
</ResponseField>

<ResponseField name="preferences" type="object">
  Customer communication preferences
</ResponseField>

<RequestExample>
  ```bash Basic Customer theme={null}
  curl -X POST https://api.stateset.com/v1/customers \
    -H "Authorization: Bearer ${STATESET_API_KEY}" \
    -H "Content-Type: application/json" \
    -d '{
      "email": "john.doe@example.com",
      "first_name": "John",
      "last_name": "Doe",
      "phone": "+1-555-123-4567"
    }'
  ```

  ```bash Complete Customer Profile theme={null}
  curl -X POST https://api.stateset.com/v1/customers \
    -H "Authorization: Bearer ${STATESET_API_KEY}" \
    -H "Content-Type: application/json" \
    -H "Idempotency-Key: customer-creation-12345" \
    -d '{
      "email": "sarah.wilson@techcorp.com",
      "first_name": "Sarah",
      "last_name": "Wilson",
      "phone": "+1-555-987-6543",
      "date_of_birth": "1985-12-03",
      "address": {
        "street1": "123 Innovation Drive",
        "street2": "Suite 200",
        "city": "San Francisco",
        "state": "CA",
        "postal_code": "94105",
        "country": "US"
      },
      "marketing_consent": true,
      "customer_tier": "gold",
      "referral_source": "paid_search",
      "notes": "High-value enterprise customer",
      "tags": ["enterprise", "tech", "high-value"],
      "custom_fields": {
        "company_name": "Tech Corp",
        "job_title": "CTO",
        "industry": "Technology"
      },
      "preferences": {
        "email_notifications": true,
        "sms_notifications": false,
        "language": "en",
        "timezone": "America/Los_Angeles"
      }
    }'
  ```

  ```javascript Node.js SDK theme={null}
  import { StateSetClient } from 'stateset-node';

  const client = new StateSetClient({
    apiKey: process.env.STATESET_API_KEY
  });

  try {
    const customer = await client.customers.create({
      email: 'john.doe@example.com',
      first_name: 'John',
      last_name: 'Doe',
      phone: '+1-555-123-4567',
      address: {
        street1: '123 Main Street',
        city: 'New York',
        state: 'NY',
        postal_code: '10001',
        country: 'US'
      },
      marketing_consent: true,
      customer_tier: 'silver',
      tags: ['newsletter-subscriber']
    });
    
    console.log('Customer created:', customer.id);
    
    // Optionally, create a welcome email workflow
    await client.workflows.trigger({
      workflow_id: 'welcome_series',
      customer_id: customer.id
    });
    
  } catch (error) {
    if (error.code === 'DUPLICATE_EMAIL') {
      console.log('Customer already exists with this email');
    } else {
      console.error('Error creating customer:', error.message);
    }
  }
  ```

  ```python Python SDK theme={null}
  from stateset import StateSet
  import os

  client = StateSet(api_key=os.getenv('STATESET_API_KEY'))

  try:
      customer = client.customers.create({
          'email': 'jane.smith@example.com',
          'first_name': 'Jane',
          'last_name': 'Smith',
          'phone': '+1-555-234-5678',
          'address': {
              'street1': '456 Oak Avenue',
              'city': 'Los Angeles',
              'state': 'CA',
              'postal_code': '90210',
              'country': 'US'
          },
          'marketing_consent': False,
          'customer_tier': 'bronze',
          'referral_source': 'social_media',
          'custom_fields': {
              'how_did_you_hear': 'Instagram ad',
              'interests': 'sustainability'
          }
      })
      
      print(f'Customer created: {customer.id}')
      
      # Send welcome email
      client.emails.send({
          'template': 'welcome',
          'to': customer.email,
          'variables': {
              'first_name': customer.first_name
          }
      })
      
  except Exception as error:
      if hasattr(error, 'code') and error.code == 'DUPLICATE_EMAIL':
          print('Customer already exists')
      else:
          print(f'Error: {str(error)}')
  ```

  ```ruby Ruby SDK theme={null}
  require 'stateset'

  client = StateSet::Client.new(
    api_key: ENV['STATESET_API_KEY']
  )

  begin
    customer = client.customers.create({
      email: 'mike.johnson@example.com',
      first_name: 'Mike',
      last_name: 'Johnson',
      phone: '+1-555-345-6789',
      address: {
        street1: '789 Pine Street',
        city: 'Seattle',
        state: 'WA',
        postal_code: '98101',
        country: 'US'
      },
      customer_tier: 'platinum',
      tags: ['vip', 'longtime-customer']
    })
    
    puts "Customer created: #{customer.id}"
    
  rescue StateSet::DuplicateEmailError
    puts "Customer already exists with this email"
  rescue StateSet::Error => e
    puts "Error creating customer: #{e.message}"
  end
  ```

  ```go Go SDK theme={null}
  package main

  import (
      "context"
      "fmt"
      "log"
      "os"
      
      "github.com/stateset/stateset-go"
      "github.com/stateset/stateset-go/option"
  )

  func main() {
      client := stateset.NewClient(
          option.WithAPIKey(os.Getenv("STATESET_API_KEY")),
      )
      
      customer, err := client.Customers.Create(context.Background(), &stateset.CustomerCreateParams{
          Email:     "alex.brown@example.com",
          FirstName: "Alex",
          LastName:  "Brown",
          Phone:     "+1-555-456-7890",
          Address: &stateset.AddressParams{
              Street1:    "321 Elm Street",
              City:       "Austin",
              State:      "TX",
              PostalCode: "73301",
              Country:    "US",
          },
          MarketingConsent: stateset.Bool(true),
          CustomerTier:     stateset.String("gold"),
          Tags:            []string{"referral", "premium"},
      })
      
      if err != nil {
          var apiErr *stateset.Error
          if errors.As(err, &apiErr) && apiErr.Code == "DUPLICATE_EMAIL" {
              fmt.Println("Customer already exists")
              return
          }
          log.Fatal(err)
      }
      
      fmt.Printf("Customer created: %s\n", customer.ID)
  }
  ```

  ```php PHP SDK theme={null}
  <?php
  require_once 'vendor/autoload.php';

  use StateSet\StateSetClient;
  use StateSet\Exception\StateSetException;

  $client = new StateSetClient([
      'api_key' => $_ENV['STATESET_API_KEY']
  ]);

  try {
      $customer = $client->customers->create([
          'email' => 'lisa.davis@example.com',
          'first_name' => 'Lisa',
          'last_name' => 'Davis',
          'phone' => '+1-555-567-8901',
          'address' => [
              'street1' => '654 Maple Drive',
              'city' => 'Denver',
              'state' => 'CO',
              'postal_code' => '80202',
              'country' => 'US'
          ],
          'customer_tier' => 'silver',
          'marketing_consent' => true,
          'referral_source' => 'email'
      ]);
      
      echo "Customer created: " . $customer->id . "\n";
      
      // Send welcome SMS if phone provided
      if ($customer->phone) {
          $client->sms->send([
              'to' => $customer->phone,
              'message' => "Welcome to our store, {$customer->first_name}!"
          ]);
      }
      
  } catch (StateSetException $e) {
      if ($e->getCode() === 'DUPLICATE_EMAIL') {
          echo "Customer already exists\n";
      } else {
          echo "Error: " . $e->getMessage() . "\n";
      }
  }
  ?>
  ```

  ```java Java SDK theme={null}
  import com.stateset.StateSetClient;
  import com.stateset.models.Customer;
  import com.stateset.models.CustomerCreateParams;
  import com.stateset.models.Address;
  import com.stateset.exception.StateSetException;

  public class CreateCustomerExample {
      public static void main(String[] args) {
          StateSetClient client = StateSetClient.builder()
              .apiKey(System.getenv("STATESET_API_KEY"))
              .build();
              
          try {
              CustomerCreateParams params = CustomerCreateParams.builder()
                  .email("tom.wilson@example.com")
                  .firstName("Tom")
                  .lastName("Wilson")
                  .phone("+1-555-678-9012")
                  .address(Address.builder()
                      .street1("987 Oak Boulevard")
                      .city("Miami")
                      .state("FL")
                      .postalCode("33101")
                      .country("US")
                      .build())
                  .customerTier("gold")
                  .marketingConsent(true)
                  .addTag("newsletter")
                  .addTag("loyalty-program")
                  .build();
                  
              Customer customer = client.customers().create(params);
              System.out.println("Customer created: " + customer.getId());
              
          } catch (StateSetException e) {
              if ("DUPLICATE_EMAIL".equals(e.getCode())) {
                  System.out.println("Customer already exists");
              } else {
                  System.err.println("Error: " + e.getMessage());
              }
          }
      }
  }
  ```

  ```graphql GraphQL Mutation theme={null}
  mutation CreateCustomer($input: CustomerCreateInput!) {
    createCustomer(input: $input) {
      id
      email
      firstName
      lastName
      fullName
      phone
      address {
        street1
        street2
        city
        state
        postalCode
        country
      }
      customerTier
      marketingConsent
      status
      createdAt
      stripeCustomerId
      tags
      customFields
      preferences {
        emailNotifications
        smsNotifications
        language
        timezone
      }
    }
  }

  # Variables:
  {
    "input": {
      "email": "emily.chen@example.com",
      "firstName": "Emily",
      "lastName": "Chen",
      "phone": "+1-555-789-0123",
      "address": {
        "street1": "159 Innovation Way",
        "city": "Boston",
        "state": "MA",
        "postalCode": "02101",
        "country": "US"
      },
      "customerTier": "platinum",
      "marketingConsent": true,
      "tags": ["enterprise", "tech-executive"],
      "customFields": {
        "company": "Innovation Labs",
        "role": "VP Engineering"
      }
    }
  }
  ```
</RequestExample>

<ResponseExample>
  ```json Success Response (201 Created) theme={null}
  {
    "id": "cust_1NXWPnCo6bFb1KQto6C8OWvE",
    "email": "sarah.wilson@techcorp.com",
    "first_name": "Sarah",
    "last_name": "Wilson",
    "full_name": "Sarah Wilson",
    "phone": "+1-555-987-6543",
    "date_of_birth": "1985-12-03",
    "address": {
      "street1": "123 Innovation Drive",
      "street2": "Suite 200",
      "city": "San Francisco",
      "state": "CA",
      "postal_code": "94105",
      "country": "US"
    },
    "customer_tier": "gold",
    "marketing_consent": true,
    "referral_source": "paid_search",
    "stripe_customer_id": "cus_ABC123DEF456",
    "status": "active",
    "created_at": "2024-01-15T10:30:00Z",
    "updated_at": "2024-01-15T10:30:00Z",
    "lifetime_value": 0.00,
    "total_orders": 0,
    "tags": ["enterprise", "tech", "high-value"],
    "custom_fields": {
      "company_name": "Tech Corp",
      "job_title": "CTO",
      "industry": "Technology"
    },
    "preferences": {
      "email_notifications": true,
      "sms_notifications": false,
      "language": "en",
      "timezone": "America/Los_Angeles"
    }
  }
  ```

  ```json Error Response (400 Bad Request) theme={null}
  {
    "error": {
      "code": "VALIDATION_ERROR",
      "message": "Request validation failed",
      "errors": [
        {
          "field": "email",
          "message": "Invalid email format",
          "value": "invalid-email"
        },
        {
          "field": "first_name",
          "message": "First name is required",
          "value": null
        }
      ],
      "request_id": "req_1NXWPnCo6bFb1KQto6C8OWvE"
    }
  }
  ```

  ```json Error Response (409 Conflict) theme={null}
  {
    "error": {
      "code": "DUPLICATE_EMAIL",
      "message": "A customer with this email already exists",
      "details": {
        "email": "sarah.wilson@techcorp.com",
        "existing_customer_id": "cust_2OYZRpEq8dHd3MSvq8E0QYwG"
      },
      "request_id": "req_1NXWPnCo6bFb1KQto6C8OWvE"
    }
  }
  ```

  ```json Error Response (422 Unprocessable Entity) theme={null}
  {
    "error": {
      "code": "BUSINESS_RULE_VIOLATION", 
      "message": "Customer creation violates business rules",
      "errors": [
        {
          "rule": "age_restriction",
          "message": "Customer must be at least 13 years old",
          "field": "date_of_birth"
        }
      ],
      "request_id": "req_1NXWPnCo6bFb1KQto6C8OWvE"
    }
  }
  ```
</ResponseExample>

## Additional Features

### Idempotency

Use the `Idempotency-Key` header to safely retry customer creation requests:

```bash theme={null}
curl -X POST https://api.stateset.com/v1/customers \
  -H "Idempotency-Key: customer-signup-form-abc123" \
  -H "Authorization: Bearer sk_live_..." \
  -d '{"email": "customer@example.com", ...}'
```

### Stripe Integration

When Stripe integration is enabled:

* A Stripe customer is automatically created if `stripe_customer_id` is not provided
* Customer data is synced between StateSet and Stripe
* Payment methods can be attached to the Stripe customer

### Webhook Events

Creating a customer triggers these webhook events:

* `customer.created` - Fired when customer is successfully created
* `customer.stripe_synced` - Fired when Stripe customer is created (if integration enabled)

### Validation Rules

| Field           | Validation                                         |
| --------------- | -------------------------------------------------- |
| `email`         | Must be valid email format, unique across account  |
| `first_name`    | 1-50 characters, letters and spaces only           |
| `last_name`     | 1-50 characters, letters and spaces only           |
| `phone`         | Valid phone number format                          |
| `date_of_birth` | Valid date, customer must be at least 13 years old |
| `postal_code`   | Valid format for specified country                 |
| `country`       | Valid ISO 3166-1 alpha-2 country code              |

### Rate Limiting

Customer creation is subject to rate limits:

* **Standard:** 100 customers/minute
* **Enterprise:** 1000 customers/minute

Consider using batch import for large datasets.
