Skip to main content
POST
/
contact
curl --request POST \
  --url https://api.flowiq.live/contact \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '
{
  "name": "John Doe",
  "phone_number": "+27123456789",
  "email": "john@example.com",
  "tags": "customer,premium,vip"
}
'
{
"success": true,
"message": "Contact created successfully",
"contact": {
"id": "123e4567-e89b-12d3-a456-426614174000",
"full_name": "John Doe",
"whatsapp_id": "27123456789",
"phone_number": "+27123456789",
"email": "john@example.com",
"tags": [
"customer",
"premium",
"vip"
],
"organization_id": "org-uuid-here",
"created_at": "2025-12-11T10:30:00Z"
}
}
This endpoint creates a new contact with WhatsApp number verification. The phone number must be registered on WhatsApp.

Overview

Create a new contact in your FlowIQ organization. The API automatically:
  • Verifies the phone number is registered on WhatsApp
  • Normalizes phone numbers for consistent storage
  • Checks for duplicate contacts
  • Parses and stores contact tags

Authentication

All requests require a Bearer token with API key format (fiq_...) in the Authorization header:
Authorization: Bearer fiq_YOUR_API_KEY
Only API keys with the fiq_ prefix are accepted. The API key must belong to the organization specified in tenantId.

Basic Usage

Create a Contact

curl -X POST "https://api.flowiq.live/contact?tenantId=YOUR_TENANT_ID" \
  -H "Authorization: Bearer fiq_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "John Doe",
    "phone_number": "+27123456789",
    "email": "john@example.com",
    "tags": "customer,premium,vip"
  }'

Minimal Request (Phone Only)

curl -X POST "https://api.flowiq.live/contact?tenantId=YOUR_TENANT_ID" \
  -H "Authorization: Bearer fiq_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "phone_number": "+27123456789"
  }'

Request Parameters

Query Parameters

ParameterTypeRequiredDescription
tenantIdstringYesYour organization’s tenant identifier (slug)

Request Body

FieldTypeRequiredDescription
phone_numberstringYesPhone number with country code (e.g., +27123456789)
namestringNoContact’s full name
emailstringNoContact’s email address
tagsstringNoComma-separated tags (e.g., “customer,premium,vip”)
Phone numbers are automatically cleaned and normalized. Both +27 12 345 6789 and 27123456789 will be stored consistently.

Response Examples

Success Response (201)

{
  "success": true,
  "message": "Contact created successfully",
  "contact": {
    "id": "123e4567-e89b-12d3-a456-426614174000",
    "full_name": "John Doe",
    "whatsapp_id": "27123456789",
    "phone_number": "+27123456789",
    "email": "john@example.com",
    "tags": ["customer", "premium", "vip"],
    "organization_id": "org-uuid-here",
    "created_at": "2025-12-11T10:30:00Z"
  }
}

Error: Contact Already Exists (409)

{
  "error": "Contact already exists",
  "message": "A contact with this phone number already exists",
  "existing_contact": {
    "id": "existing-uuid",
    "full_name": "John Doe",
    "whatsapp_id": "27123456789"
  }
}

Error: Invalid WhatsApp Number (400)

{
  "error": "Invalid WhatsApp number",
  "message": "The provided phone number is not registered on WhatsApp"
}

Error: Missing Phone Number (400)

{
  "error": "Missing required field",
  "message": "phone_number is required"
}

Error: Invalid API Key (401)

{
  "error": "Invalid API key",
  "message": "API key has been revoked"
}

Error: Tenant Mismatch (401)

{
  "error": "API key mismatch",
  "message": "API key does not belong to the specified tenant"
}

Phone Number Validation

The API performs several validation steps:
  1. Format Check: Removes special characters, keeps only digits
  2. Length Check: Must be at least 10 digits (including country code)
  3. WhatsApp Verification: Verifies the number is registered on WhatsApp using FlowMod’s verification service
  4. Duplicate Check: Ensures no existing contact has the same WhatsApp ID in your organization
If the phone number is not registered on WhatsApp, the contact creation will fail with a 400 error.

Tag Management

Tags can be provided as a comma-separated string and are automatically:
  • Split into individual tags
  • Trimmed of whitespace
  • Stored as a JSON array
  • Empty tags are filtered out
Example:
{
  "tags": "customer, premium, vip, "
}
Stored as:
{
  "tags": ["customer", "premium", "vip"]
}

Contact Properties

When a contact is created, the following properties are automatically set:
PropertyDefault ValueDescription
bot_statustrueBot is enabled for this contact
archivedfalseContact is not archived
has_unread_messagesfalseNo unread messages initially
allow_broadcasttrueContact can receive broadcasts
active_statusfalseContact is not currently active
blockedfalseContact is not blocked
source.type"api"Contact was created via API

Error Codes

Status CodeErrorDescription
201SuccessContact created successfully
400Bad RequestMissing required fields or invalid phone number
401UnauthorizedInvalid or expired API key
404Not FoundOrganization with specified tenantId not found
409ConflictContact with this phone number already exists
500Internal Server ErrorServer-side error occurred

Best Practices

Phone Number Format

Always include the country code (e.g., +27 for South Africa, +1 for USA/Canada). The API handles formatting automatically.

Duplicate Detection

Check the 409 error response to get details about the existing contact before attempting to update or create a new one.

Tags Organization

Use consistent tag naming (e.g., lowercase, no spaces) for easier filtering and organization.

Error Handling

Always handle WhatsApp verification failures gracefully - inform users that the number must be registered on WhatsApp.

Integration Example

async function createContact(tenantId, apiKey, contactData) {
  try {
    const response = await fetch(
      `https://api.flowiq.live/contact?tenantId=${tenantId}`,
      {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${apiKey}`,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(contactData)
      }
    );

    const data = await response.json();

    if (!response.ok) {
      // Handle specific error cases
      if (response.status === 409) {
        console.log('Contact already exists:', data.existing_contact);
      } else if (response.status === 400) {
        console.error('Invalid data:', data.message);
      }
      throw new Error(data.message);
    }

    return data.contact;
  } catch (error) {
    console.error('Failed to create contact:', error);
    throw error;
  }
}

// Usage
const newContact = await createContact(
  'your-tenant-id',
  'fiq_your_api_key',
  {
    name: 'Jane Smith',
    phone_number: '+27987654321',
    email: 'jane@example.com',
    tags: 'lead,website'
  }
);

Authorizations

Authorization
string
header
required

Bearer token for authentication. Format: Bearer YOUR_BEARER_TOKEN

Query Parameters

tenantId
string
required

Organization tenant identifier (slug)

Body

application/json
phone_number
string
required

Phone number with country code (required)

Example:

"+27123456789"

name
string

Contact's full name

Example:

"John Doe"

email
string<email>

Contact's email address

Example:

"john@example.com"

tags
string

Comma-separated tags

Example:

"customer,premium,vip"

Response

Contact created successfully

success
boolean
required

Whether the request was successful

Example:

true

message
string
required

Success message

Example:

"Contact created successfully"

contact
object
required