API: Contacts & tags
Contacts are the heart of the CRM, and the API mirrors what the app can do with them — including the consent rules. See the API overview for authentication and errors.
The contact object
{ "id": "0d9f7c3e-…", "phone": "+4915112345678", "name": "Ada Example", "locale": "de", "source": "api", "opt_in_status": "confirmed", "attributes": { "company": "Example GmbH" }, "tags": ["webinar", "vip"], "last_inbound_at": "2026-07-01T18:22:10Z", "last_outbound_at": "2026-07-01T18:22:41Z", "awaiting_reply": false, "assigned_user_id": null, "assigned_team_id": null, "created_at": "2026-06-12T09:03:44Z"}last_inbound_at is the contact’s last message to you, last_outbound_at your last message to them — from any sender (AI agent, teammate, automation, broadcast, API). awaiting_reply is true while the contact wrote after your last message, i.e. the chat is waiting for an answer.
opt_in_status is one of none, pending, confirmed, opted_out. Campaigns only go to confirmed contacts; opted_out contacts are never messaged.
Create or update — POST /v1/contacts
Upserts by phone number: if the phone already exists in the workspace, the contact is updated; otherwise it is created (and the Contact is created automation trigger fires).
curl -s https://app.nybero.com/api/v1/contacts \ -H "Authorization: Bearer $NYBERO_KEY" \ -H "Content-Type: application/json" \ -d '{ "phone": "0151 1234 5678", "default_country": "DE", "name": "Ada Example", "source": "landingpage", "attributes": { "company": "Example GmbH" }, "tags": ["webinar"], "opt_in": true, "consent_proof": "Checked the WhatsApp opt-in box on example.com/webinar" }'phone(required) — international format preferred (+4915112345678). National formats work when you senddefault_country(ISO code, e.g.DE).attributes— free key/value custom fields; keys merge into the contact’s existing attributes.tags— Nybero tags; missing ones are created. Each newly attached tag fires the Tag is added trigger, so this can start automations.opt_in+consent_proof— see consent semantics below.
The response is the contact object plus "created": true|false.
List & search — GET /v1/contacts
curl -s "https://app.nybero.com/api/v1/contacts?search=ada&tag=webinar&opt_in_status=confirmed&limit=50&offset=0" \ -H "Authorization: Bearer $NYBERO_KEY"Filters combine: search matches name or phone, tag filters by an exact tag name, opt_in_status by consent state, awaiting_reply=true returns only chats waiting for an answer, inbound_since (ISO-8601) only contacts who wrote at or after that time. Paginated (data/total/limit/offset).
Find unanswered chats
# Everyone who wrote in the last 24 h and is still waiting for a replycurl -s "https://app.nybero.com/api/v1/contacts?awaiting_reply=true&inbound_since=2026-10-20T08:00:00Z" \ -H "Authorization: Bearer $NYBERO_KEY"Run it on a schedule (e.g. hourly in Make) and alert your team for every hit — or react in real time with the message.sent and agent.* webhook events.
Message history — GET /v1/contacts/{id}/messages
curl -s "https://app.nybero.com/api/v1/contacts/{id}/messages?limit=50" \ -H "Authorization: Bearer $NYBERO_KEY"{ "data": [ { "id": "…", "direction": "outbound", "sender": "agent", "type": "text", "text": "Dann kannst du dich gerne hier einbuchen …", "template": null, "status": "read", "user_id": null, "created_at": "2026-10-20T09:01:12Z" }, { "id": "…", "direction": "inbound", "sender": "contact", "type": "text", "text": "Gerne ja", "template": null, "status": "received", "user_id": null, "created_at": "2026-10-20T08:36:02Z" } ], "limit": 50, "has_more": true}Newest first. sender is contact for inbound messages; for outbound ones agent, team (with the teammate’s user_id), automation, broadcast, api, business_app (sent from the WhatsApp Business app) or system. Page backwards with before=<created_at of the oldest message you have>.
Read, update, delete
# One contactcurl -s https://app.nybero.com/api/v1/contacts/{id} -H "Authorization: Bearer $NYBERO_KEY"
# Update fields (attributes merge into existing ones)curl -s -X PATCH https://app.nybero.com/api/v1/contacts/{id} \ -H "Authorization: Bearer $NYBERO_KEY" -H "Content-Type: application/json" \ -d '{"name":"Ada Lovelace","attributes":{"stage":"customer"}}'
# GDPR delete — removes the contact, its consent trail and tag linkscurl -s -X DELETE https://app.nybero.com/api/v1/contacts/{id} \ -H "Authorization: Bearer $NYBERO_KEY"Deleting is the same GDPR erasure the app performs — use it to honour a right-to-erasure request programmatically. It returns 204 No Content.
Tags
# All tags in the workspacecurl -s https://app.nybero.com/api/v1/tags -H "Authorization: Bearer $NYBERO_KEY"
# Add a tag (created if missing; fires the "Tag is added" trigger when newly attached)curl -s https://app.nybero.com/api/v1/contacts/{id}/tags \ -H "Authorization: Bearer $NYBERO_KEY" -H "Content-Type: application/json" \ -d '{"name":"vip"}'
# Remove a tagcurl -s -X DELETE https://app.nybero.com/api/v1/contacts/{id}/tags/vip \ -H "Authorization: Bearer $NYBERO_KEY"Tags are Nybero-native (more on tags) — they drive segments and the Tag is added automation trigger, which makes POST …/tags a handy way to kick off a flow for one contact.
Worked example: sync signups from your backend
Your shop backend marks buyers in Nybero so a post-purchase flow runs:
- Customer buys → your backend calls
POST /v1/contactswithphone,name,opt_in: true(consent collected at checkout),attributes: {"order_id": "A-1042"}. - The same call adds
"tags": ["customer"]. - In Nybero, an automation with trigger Tag is added (tag
customer) sends the approved order-confirmation template and a review request three days later.
No polling, no CSV exports — one HTTP call per purchase.