Skip to content
Website

Connect Contacts to your own systems ​

Typing contacts in, or uploading a spreadsheet, are only two ways to fill Contacts. Most businesses already have a website form, a CRM, a booking or billing system. Voxido can take new people from those systems automatically, and your agents can send details back to them.

Find it: Sidebar → Integrations → Custom API (Inbound and Outbound), and Sidebar → Agents → open an agent → TriggersWho can set it up: Owners and Admins. Your developer, or Copilot, can do the technical part.

Every way a contact gets into Voxido ​

WayGood forHow Voxido spots someone it already hasWorkspace the contact lands in
Add contactOne person at a timeSame phone in the same workspace is refusedThe workspace you're in
Import (CSV or Excel)A list you already haveSame phone in that workspace. You choose Skip, Fill empty fields or Update.The workspace you import into
A call or WhatsApp messagePeople who reach you firstTheir phone number. New numbers become contacts.The workspace of the number or agent
Inbound APIYour website form, CRM or booking system sends each new or changed personEmail, then phone (you choose)The workspace you pick on the API, or your default workspace
Webhook trigger on an agentYour system says "contact this person now"contact_id, phone or email. Creates the contact if it's new.The agent's workspace
Hotel PMS (eZee)Guests from bookingsThe booking, then phone or emailThe PMS's workspace
Copilot"Add Priya Sharma, +91 90000 12345, interested in a consultation"No check, so search first—

Agents also keep contacts up to date on their own. During a conversation they can update fields and move the contact to the right stage, and after a call they fill in empty fields from what the customer said.

Pick your path ​

Your situationUseWhy
"Leads fill in a form on our website and someone retypes them."Inbound APIThe contact appears in seconds, with your fields filled in. Nobody types.
"When an order ships, our system should WhatsApp the customer."Webhook triggerIt creates the contact if needed and starts the agent right away.
"We have 2,000 old customers in Excel."ImportOne upload, with duplicate checks.
"During a chat, the agent should save the lead in our CRM or check our booking system."Outbound API (or an app such as HubSpot)The agent calls your system as part of the conversation.
"Every stage change should update our CRM automatically."Not available yetVoxido doesn't send automatic webhooks when a contact changes. See Send details out for what works today.

Bring contacts in with an Inbound API ​

An Inbound API is a private web address plus a key. Your system sends a person's details to it, and Voxido creates the contact, or updates it if it already exists. You decide which of your system's fields go into which contact field. That's called mapping.

  1. Go to Integrations → Custom API → Inbound and click New inbound API.
  2. Type a Name, such as Website enquiry form. If you have more than one workspace, pick the Property (workspace) new contacts should land in.
  3. Click Create endpoint. You'll see: "Endpoint created" and the Endpoint URL.
  4. Click Generate key and copy it now. It's shown once. You'll see: the key. Your system sends it in the X-API-Key header.
  5. Paste an example of what your system sends into Sample payload (see the sample below), or click Capture from a live request and send one real request. You'll see: "N source fields detected."
  6. Under Field Mappings, match each source field to a contact field and pick a Transform where needed. Tick Required for fields that must be there.
  7. Set Match existing contact by: Auto (email, then phone), Email or Phone.
  8. In the Test console, click Dry run (writes nothing), then Send test (creates a real contact).
  9. Click Save changes. Give your developer the URL and the key, or copy the ready-made cURL example.

Inbound API panel

Use the key from the Inbound API panel

Keys made in Settings → API keys don't work on Inbound APIs. Click Generate key on the Inbound API itself.

Sample: a website enquiry form ​

This is what a typical form sends. Paste it into Sample payload:

json
{
  "full_name": "Priya Sharma",
  "mobile": "+919000012345",
  "email": "Priya.Sharma@mail.example",
  "service": "Consultation",
  "preferred_date": "2026-10-24",
  "message": "Can I come in on Saturday morning?"
}

Map it like this:

Source fieldContact fieldTransformRequired
full_nameNameTrim whitespace
mobilePhonePhone → E.164✓
emailEmailLowercase
serviceyour custom field Service
preferred_dateyour custom field Appointment date
messageNotes

Tips:

  • Send dates as YYYY-MM-DD. The Date → ISO 8601 transform only tidies spaces; it doesn't rewrite other date formats.
  • Use Phone → E.164 so 90000 12345 and +91 90000 12345 are seen as the same person.
  • A request with no email and no phone is skipped: there's nothing to match on.

Send it from your server:

bash
curl -X POST "https://api.voxido.ai/api/v1/inbound/YOUR_ENDPOINT_ID" \
  -H "Content-Type: application/json" \
  -H "X-API-Key: $VOXIDO_INBOUND_KEY" \
  -d '{"full_name":"Priya Sharma","mobile":"+919000012345","email":"priya.sharma@mail.example","service":"Consultation","preferred_date":"2026-10-24"}'
js
// Run this on your server, never in the browser: the key must stay secret.
const res = await fetch("https://api.voxido.ai/api/v1/inbound/YOUR_ENDPOINT_ID", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "X-API-Key": process.env.VOXIDO_INBOUND_KEY,
  },
  body: JSON.stringify({
    full_name: form.name,
    mobile: form.phone,
    email: form.email,
    service: form.service,
    preferred_date: form.date, // "2026-10-24"
  }),
});
console.log(res.status, await res.json());
python
import os, requests

r = requests.post(
    "https://api.voxido.ai/api/v1/inbound/YOUR_ENDPOINT_ID",
    headers={"X-API-Key": os.environ["VOXIDO_INBOUND_KEY"]},
    json={
        "full_name": "Priya Sharma",
        "mobile": "+919000012345",
        "email": "priya.sharma@mail.example",
        "service": "Consultation",
        "preferred_date": "2026-10-24",
    },
    timeout=10,
)
print(r.status_code, r.json())

You'll get back:

json
{ "status": "ok", "contact_id": "8b1d…", "result": "created", "goal_fired": false, "assignee": null }

result is created, updated or skipped. Every status code is listed in REST API and authentication.

Sample: from a tool, without code ​

Zapier, Make, Pabbly and n8n can all send this request. Add a Webhook or HTTP request step after your trigger (a new form entry, a new CRM deal…):

SettingValue
MethodPOST
URLYour Endpoint URL
HeadersX-API-Key = your key, Content-Type = application/json
BodyJSON with your fields, as in the sample above

If a form builder can only send a webhook without custom headers, send it to Zapier, Make or n8n first, and let that step add the X-API-Key header.

Let Copilot set it up ​

Copilot can create, change and test Inbound APIs for you. You approve each change. Open Ask Copilot and paste something like:

Create an inbound API called "Website enquiry form" in this workspace. Our form sends: {"full_name":"Priya Sharma","mobile":"+919000012345","email":"priya@mail.example","service":"Consultation","preferred_date":"2026-10-24"}. Map full_name to Name, mobile to Phone with E.164 (required), email to Email in lowercase, service to the Service field and preferred_date to Appointment date. Match existing contacts by phone. Then do a dry run.

Then open the Inbound API, click Generate key yourself, and send one real test.

Make an agent act when your system says so (webhook trigger) ​

Use this when your system should start a conversation now: "booking confirmed, send the details", "order shipped, tell the customer".

  1. Open an agent → Triggers → Add trigger → When an external system notifies us.
  2. Copy the Webhook URL. Click Generate next to Signing secret and copy it.
  3. From your system, send a POST to the URL with the contact's phone (or email, or contact_id) and anything the agent should know:
json
{
  "phone": "+919000012345",
  "trigger_source": "order_shipped",
  "context": { "order_id": "BW-1042", "items": "2 × water filter", "eta": "Friday" }
}
  1. Sign it: the X-Voxido-Signature header is the HMAC-SHA256 (lowercase hex) of the exact body, using the signing secret. Don't send the secret itself.

If no contact has that phone or email, Voxido creates one in the agent's workspace. The agent must be Active to act. Code samples in Python and Node.js: Webhook triggers: payload and HMAC signing. Step-by-step: Webhook triggers and signing secrets.

Inbound APIWebhook trigger
Creates or updates the contactYes, with your field mappingCreates it if missing. Doesn't map fields.
Starts an agentOnly if you pick a goal under After updateYes, straight away
AuthenticationX-API-Key headerX-Voxido-Signature (HMAC of the body)
Best forKeeping Contacts in step with your form or CRM"Do something for this person now"

Send details out to your systems ​

Voxido doesn't push automatic updates (webhooks) to your systems when a contact is created or changes stage. Today, details go out in these ways:

WayWhen it runsWorks on
Outbound API exposed to the agentWhen the agent decides to call it during a conversation, for example after it has the customer's name and needText chats (WhatsApp and others). Not voice calls yet.
An app from the Apps catalog, such as HubSpotWhen the agent uses that app's action during a conversationCalls and chats
ExportWhen you download a CSVAny time

Sample: "Save lead to our CRM" (outbound) ​

Let the WhatsApp agent save every qualified lead in your CRM.

  1. Go to Integrations → Custom API → Outbound → New outbound API.
  2. On Auth, create the connection: Base URL https://crm.brightway.example, Auth type API key, Header name X-API-Key. Click Create & test connection.
  3. Name it Save lead to CRM, method POST, path /api/leads.
  4. On Headers, add Content-Type = application/json. On Body, choose Raw template:
json
{
  "name": "{{contact.name}}",
  "phone": "{{contact.phone}}",
  "email": "{{contact.email}}",
  "service": "{{contact.custom_fields.service}}",
  "summary": "{{args.summary}}",
  "source": "voxido-whatsapp"
}
  1. On Response, add the output field lead_id.
  2. On Agent, switch on Expose to agents. Description: "Use once you know the customer's name, phone and the service they want. Saves the lead in our CRM and returns its ID." Add a parameter summary (string, required): "One line on what the customer wants".
  3. Click Test, then Save. Then open the agent → Skills → From your apps → System → Voxido, switch the API on, and Save.

Agent tab of an outbound API

Your CRM receives a normal JSON POST and should answer within 30 seconds. A minimal receiver:

js
app.post("/api/leads", express.json(), async (req, res) => {
  if (req.get("X-API-Key") !== process.env.CRM_KEY_FOR_VOXIDO) return res.sendStatus(401);
  const lead = await db.leads.upsert({ phone: req.body.phone }, req.body);
  res.json({ lead_id: lead.id, status: "saved" });
});
python
@app.post("/api/leads")
def save_lead():
    if request.headers.get("X-API-Key") != os.environ["CRM_KEY_FOR_VOXIDO"]:
        return {"error": "unauthorized"}, 401
    lead = upsert_lead(phone=request.json["phone"], data=request.json)
    return {"lead_id": lead.id, "status": "saved"}

Copilot can build this too. Click Set up with Copilot → Paste cURL or API docs…, paste your CRM's API docs or an example request, and click Send to Copilot. Check the result, then test it.

More options (routing rules, variables, limits): Custom API.

Common problems ​

The inbound request returns 401. Use a key from Generate key on the Inbound API, sent in X-API-Key. Keys from Settings → API keys don't work here.

The answer says "result": "skipped". The request had no email and no phone, so there was nothing to match. Map at least one of them.

The same person shows up twice. The phone came in two formats. Add the Phone → E.164 transform and set Match existing contact by to Phone.

422 "Missing required mapping fields". Your system didn't send a field you marked Required. The response lists which ones.

The webhook trigger returns 401.X-Voxido-Signature must be the HMAC of the exact body, not the secret itself.

The agent never saved the lead to our CRM. Check that Expose to agents is on, the API is switched on in the agent's Skills, and the conversation was a text chat. Voice calls don't use outbound APIs yet.