# Identity verification

> Personalize chat for signed-in customers by attaching a stable end-user id, syncing them as contacts, and keeping API keys server-side.

When a customer is signed in to your store, you can tie their Bookbag conversations to a stable identity. That lets you group a person's chats, look up their history, and enrich the agent's context with what you already know about them.

## Attach an end-user id

The simplest form of identity is the `userId` you pass on [API v2 chat](/docs/api/v2/chat). It is your own stable identifier for the customer (for example your database user id). Bookbag stores it on the conversation so you can list everything that person has asked.

| Field | Where | Rules |
| --- | --- | --- |
| userId | chat request body | Must match `^[a-zA-Z0-9._-]{1,128}$`. Use a stable id, not an email if it might change. |

```javascript
await fetch(`https://app.bookbag.ai/api/v2/agents/123/chat`, {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.BOOKBAG_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    message: "Where is my last order?",
    userId: "user_8821",
    stream: false,
  }),
});
```

> **KEEP IDENTITY ON THE SERVER:** Because `userId` is supplied by the caller, treat it as trusted only when it comes from your authenticated backend. Do not let the browser pick an arbitrary `userId` for another user, and never ship your API key to the client — proxy chat requests through your server, where you already know who is signed in.

## Enrich with contacts

To give the agent durable facts about a customer — plan, lifetime value, account status — sync them as a [contact](/docs/api/v1/contacts-create). Use the same stable id as the contact's `external_id` so the records line up:

```bash
curl https://app.bookbag.ai/api/v1/chatbots/123/contacts \
  -H "Authorization: Bearer $BOOKBAG_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "users": [ { "external_id": "user_8821", "email": "sam@acme.com", "custom_attributes": { "plan": "pro" } } ] }'
```

Define the [custom attributes](/docs/api/v1/custom-attributes) you want to store first, then attach values per contact. See the [Contacts](/docs/contacts/overview) section for the full model.

## A recommended flow

1. **Authenticate on your side** — Identify the signed-in customer with your own session/auth — Bookbag does not authenticate end users for you.
2. **Sync the contact** — Upsert the customer as a contact keyed by a stable `external_id` whenever their profile changes.
3. **Proxy chat with the userId** — Send chat requests from your backend, passing the same id as `userId`, so conversations attach to the right person.
4. **Read history when needed** — Use the per-user conversations endpoint to show a customer their past chats or to give agents context.

> **INFO:** The website [embed](/docs/developers/javascript-embed) is anonymous by design and needs no key. When you need verified identity and personalization, drive chat through the [API](/docs/developers/api-integration) from your authenticated backend.

- [Chat (v2)](/docs/api/v2/chat) — The userId parameter and conversation continuation.
- [Create contacts (v1)](/docs/api/v1/contacts-create) — Sync customers as contacts.
- [Authentication](/docs/api/authentication) — Keep keys server-side and scoped.
