POST
/
api
/
public
/
customer
/
upsert
/
info
Upsert user information
curl --request POST \
  --url https://api.vambe.me/api/public/customer/upsert/info \
  --header 'Content-Type: application/json' \
  --header 'x-api-key: <x-api-key>' \
  --data '{
  "channel_phone_number": "<string>",
  "channel": "whatsapp",
  "contact_phone_number": "<string>",
  "meta_data": {}
}'

Overview

Create or update a customer contact with intelligent AI-powered data processing. This endpoint automatically creates the contact if it doesn’t exist, or updates it if it does, along with optional metadata, stage assignment, and agent assignment - all in a single request. The AI automatically processes and structures any unstructured data you provide in the metadata, making it perfect for importing customer data from external sources.

Use Cases

  • CRM Data Import: Bulk import customer data from external CRM systems
  • Form Submissions: Create customers from web form submissions with flexible data
  • E-commerce Integration: Sync customer data from your e-commerce platform
  • Lead Capture: Capture leads with any structure of data
  • Customer Onboarding: Create customer profiles during signup flows
  • Data Migration: Migrate customer data from legacy systems

Authentication

This endpoint requires authentication using an API key. Include your API key in the request header:
x-api-key: your_api_key_here

Request Body

FieldTypeRequiredDescription
channel_phone_numberstringYesYour WhatsApp channel phone number (the sender)
channelstringYesChannel type: β€œwhatsapp” or β€œweb-whatsapp”
contact_phone_numberstringNoCustomer’s phone number (can also be in meta_data)
contact_namestringNoCustomer’s full name
contact_emailstringNoCustomer’s email address
stageIdstringNoPipeline stage UUID to assign the customer to
agentIdstringNoTeam member UUID to assign as responsible agent
meta_dataobjectNoAny additional customer data (AI will structure it)

Response Structure

Returns the created or updated AI contact object:
FieldTypeDescription
idstring (UUID)Unique identifier for the contact
namestringContact’s name
phonestringContact’s phone number
emailstringContact’s email
platformstringChannel platform (whatsapp, web-whatsapp)
client_idstring (UUID)Your organization ID
ai_customer_idstring (UUID)Associated customer profile ID
created_atstring (ISO)Contact creation timestamp
default_stage_idstring (UUID)Current pipeline stage (if assigned)

Example Request

curl --request POST \
  'https://api.vambe.ai/api/public/customer/upsert/info' \
  --header 'Content-Type: application/json' \
  --header 'x-api-key: your_api_key_here' \
  --data-raw '{
    "channel_phone_number": "+56987654321",
    "channel": "whatsapp",
    "contact_phone_number": "+56912345678",
    "contact_name": "Maria Rodriguez",
    "contact_email": "maria.rodriguez@example.com",
    "stageId": "550e8400-e29b-41d4-a716-446655440000",
    "agentId": "228d7a0d-9072-4ca8-939b-959b75cc606a",
    "meta_data": {
      "company": "Acme Corp",
      "position": "CEO",
      "industry": "Technology",
      "employees": "50-100",
      "revenue": "$1M-$5M",
      "source": "LinkedIn Campaign",
      "interests": "AI, Automation, CRM",
      "budget": "High",
      "timeline": "Q4 2024"
    }
  }'

Example Response

{
  "id": "df980fc8-b6db-4820-bf22-2969482d106d",
  "name": "Maria Rodriguez",
  "phone": "+56912345678",
  "email": "maria.rodriguez@example.com",
  "platform": "whatsapp",
  "client_id": "550e8400-e29b-41d4-a716-446655440000",
  "ai_customer_id": "660e8400-e29b-41d4-a716-446655440001",
  "created_at": "2024-09-30T10:00:00.000Z",
  "default_stage_id": "550e8400-e29b-41d4-a716-446655440000",
  "blocked": false,
  "chat_status": "UNATTENDED",
  "is_chat_read": false
}

Common Use Cases

1. Import CRM Data with Flexible Structure

const importCRMCustomer = async (crmData) => {
  const response = await fetch(
    'https://api.vambe.ai/api/public/customer/upsert/info',
    {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'x-api-key': 'your_api_key_here',
      },
      body: JSON.stringify({
        channel_phone_number: '+56987654321', // Your WhatsApp number
        channel: 'whatsapp',
        contact_name: crmData.full_name,
        contact_phone_number: crmData.phone,
        contact_email: crmData.email,
        stageId: 'your_initial_stage_id',
        meta_data: {
          // AI will automatically structure all this data
          company: crmData.company_name,
          position: crmData.job_title,
          industry: crmData.industry_sector,
          companySize: crmData.number_of_employees,
          annualRevenue: crmData.yearly_revenue,
          website: crmData.company_website,
          linkedin: crmData.linkedin_url,
          leadScore: crmData.qualification_score,
          source: crmData.lead_source,
          notes: crmData.internal_notes,
          customField1: crmData.custom_data_1,
          customField2: crmData.custom_data_2,
          // ... any other fields from your CRM
        },
      }),
    },
  );

  const contact = await response.json();
  console.log(`Imported customer: ${contact.name} (${contact.id})`);
  return contact;
};

2. Process Form Submission

const processContactForm = async (formData) => {
  const response = await fetch(
    'https://api.vambe.ai/api/public/customer/upsert/info',
    {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'x-api-key': 'your_api_key_here',
      },
      body: JSON.stringify({
        channel_phone_number: process.env.WHATSAPP_PHONE,
        channel: 'whatsapp',
        contact_name: formData.name,
        contact_phone_number: formData.phone,
        contact_email: formData.email,
        stageId: 'your_leads_stage_id',
        agentId: formData.assignToAgent || null,
        meta_data: {
          formType: 'Contact Form',
          submittedAt: new Date().toISOString(),
          subject: formData.subject,
          message: formData.message,
          source: formData.utm_source,
          campaign: formData.utm_campaign,
          // AI will extract and structure relevant info
        },
      }),
    },
  );

  return await response.json();
};

3. E-commerce Customer Sync

const syncEcommerceCustomer = async (order) => {
  const response = await fetch(
    'https://api.vambe.ai/api/public/customer/upsert/info',
    {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'x-api-key': 'your_api_key_here',
      },
      body: JSON.stringify({
        channel_phone_number: '+56987654321',
        channel: 'whatsapp',
        contact_name: `${order.customer.first_name} ${order.customer.last_name}`,
        contact_phone_number: order.customer.phone,
        contact_email: order.customer.email,
        stageId: 'your_customers_stage_id',
        meta_data: {
          orderId: order.id,
          orderNumber: order.order_number,
          orderTotal: order.total_price,
          currency: order.currency,
          itemsCount: order.line_items.length,
          products: order.line_items.map((item) => item.title).join(', '),
          shippingAddress: JSON.stringify(order.shipping_address),
          billingAddress: JSON.stringify(order.billing_address),
          customerSince: order.customer.created_at,
          totalOrders: order.customer.orders_count,
          lifetimeValue: order.customer.total_spent,
          tags: order.customer.tags,
        },
      }),
    },
  );

  return await response.json();
};

4. Bulk Customer Import

const bulkImportCustomers = async (customers) => {
  const results = [];

  for (const customer of customers) {
    try {
      const response = await fetch(
        'https://api.vambe.ai/api/public/customer/upsert/info',
        {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
            'x-api-key': 'your_api_key_here',
          },
          body: JSON.stringify({
            channel_phone_number: process.env.WHATSAPP_PHONE,
            channel: 'whatsapp',
            contact_name: customer.name,
            contact_phone_number: customer.phone,
            contact_email: customer.email,
            meta_data: customer.additionalData,
          }),
        },
      );

      const result = await response.json();
      results.push({ phone: customer.phone, success: true, id: result.id });
    } catch (error) {
      results.push({
        phone: customer.phone,
        success: false,
        error: error.message,
      });
    }

    // Add delay to avoid rate limiting
    await new Promise((resolve) => setTimeout(resolve, 200));
  }

  console.log(
    `Imported ${results.filter((r) => r.success).length} of ${customers.length} customers`,
  );

  return results;
};

5. Upsert with Flexible Phone Number

// Phone number can be in contact_phone_number OR in meta_data
const createCustomerFlexible = async (data) => {
  const response = await fetch(
    'https://api.vambe.ai/api/public/customer/upsert/info',
    {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'x-api-key': 'your_api_key_here',
      },
      body: JSON.stringify({
        channel_phone_number: '+56987654321',
        channel: 'whatsapp',
        contact_name: data.name,
        // Phone can be here OR in meta_data as "phone_number"
        meta_data: {
          phone_number: data.phone, // AI will detect this as the phone
          email: data.email,
          company: data.company,
          // ... other fields
        },
      }),
    },
  );

  return await response.json();
};

Key Features

πŸ€– AI-Powered Data Processing

The endpoint uses AI to:
  • Extract structured data from unstructured metadata
  • Match fields to your custom field definitions
  • Convert data types automatically
  • Handle flexible formats for phone numbers, dates, etc.

πŸ”„ Upsert Behavior

  • If contact exists (by phone number): Updates the contact information
  • If contact doesn’t exist: Creates a new contact
  • Idempotent: Safe to call multiple times with same data

πŸ“Š Automatic Processing

All in one request:
  1. βœ… Create/update contact
  2. βœ… Assign to pipeline stage
  3. βœ… Assign to agent
  4. βœ… Process and save metadata

Phone Number Flexibility

The contact_phone_number field is optional because the AI can extract it from meta_data: Option 1 - Explicit phone number:
{
  "contact_phone_number": "+56912345678",
  "meta_data": { ... }
}
Option 2 - Phone in metadata:
{
  "meta_data": {
    "phone_number": "+56912345678"
    // ... other fields
  }
}
Both work! The AI will find and use the phone number.

Channel Types

ChannelDescriptionUse When
whatsappWhatsApp Business APIUsing official WhatsApp API
web-whatsappWhatsApp Web (QR Code)Using WhatsApp Web connection

Error Responses

Status CodeDescription
400Bad Request - Missing required fields
401Unauthorized - Invalid or missing API key
404Not Found - Channel phone number not found
500Internal Server Error - Something went wrong

Important Notes

  • Channel Phone Number: Must be a WhatsApp number/channel you own and have configured
  • Phone Format: Automatically cleaned (spaces, dashes, etc. are removed)
  • Upsert Logic: Contact identified by phone number - updates if exists, creates if not
  • AI Processing: Metadata is processed asynchronously with AI
  • Immediate Response: Returns contact immediately, metadata processing continues in background

Best Practices

1. Use Consistent Field Names

// Good: Consistent, clear field names
const goodMetadata = {
  company: 'Acme Corp',
  position: 'CEO',
  leadScore: 95,
  industry: 'Technology',
};

// Avoid: Inconsistent, unclear
const badMetadata = {
  Company: 'Acme Corp', // Inconsistent capitalization
  job: 'CEO', // Different from "position" elsewhere
  score: 95, // Unclear what kind of score
  sector: 'Technology', // Different from "industry"
};

2. Include Source Information

meta_data: {
  source: 'LinkedIn Campaign',
  importedAt: new Date().toISOString(),
  importedBy: 'CRM Sync Script',
  externalId: 'crm_12345',
  // ... other fields
}

3. Validate Data Before Sending

const validateAndUpsert = async (customerData) => {
  // Validate required fields
  if (!customerData.phone || !customerData.name) {
    throw new Error('Phone and name are required');
  }

  // Clean phone number
  const cleanPhone = customerData.phone.replace(/[^\d+]/g, '');

  // Ensure valid email
  const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
  const validEmail = emailRegex.test(customerData.email)
    ? customerData.email
    : null;

  return await fetch('https://api.vambe.ai/api/public/customer/upsert/info', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-api-key': 'your_api_key_here',
    },
    body: JSON.stringify({
      channel_phone_number: process.env.WHATSAPP_PHONE,
      channel: 'whatsapp',
      contact_phone_number: cleanPhone,
      contact_name: customerData.name,
      contact_email: validEmail,
      meta_data: customerData.additionalData,
    }),
  }).then((r) => r.json());
};

Migration from Deprecated Endpoint

If you’re migrating from the deprecated POST /api/public/whatsapp/message/note/send endpoint: Old:
POST /api/public/whatsapp/message/note/send
{
  "to_phone": "+56912345678",
  "from_phone": "your_phone",
  "note": "Internal note",
  "contact_name": "John Doe",
  "meta_data": { ... }
}
New (This endpoint):
POST /api/public/customer/upsert/info
{
  "channel_phone_number": "your_phone",
  "channel": "whatsapp",
  "contact_phone_number": "+56912345678",
  "contact_name": "John Doe",
  "meta_data": {
    "internal_note": "Internal note",
    ...
  }
}
The new endpoint provides better structure and automatic AI processing of all metadata!

Headers

x-api-key
string
required

API key needed to authorize the request

Body

application/json
channel_phone_number
string
required

The phone number of the channel you want associate with the user

Minimum length: 1
channel
enum<string>
required

Channel you want associate with the user

Available options:
whatsapp,
web-whatsapp
contact_phone_number
string
required

Phone number you want associate with the user

meta_data
object
required
stageId
string

Stage ID you want associate with the user

agentId
string

Agent ID you want associate with the user

contact_email
string

Email you want associate with the user

contact_name
string

Name you want associate with the user

Response

Message sent successfully.