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", "created_at": "2026-06-12T09:03:44Z"}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. Paginated (data/total/limit/offset).
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.