> ## Documentation Index
> Fetch the complete documentation index at: https://docs.usefrictionless.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Send context from your server

> Create contacts and send events with the REST API.

Base URL `https://api.usefrictionless.com/api/v1`. Send JSON with your API key in the `Authorization` header. Every endpoint is in the [API reference](/api-reference/introduction), where you can try it.

## Create or update a contact

`PUT /contacts/:userId`. Only the fields you send change. Set an attribute to `null` to remove it.

```bash theme={null}
curl -X PUT https://api.usefrictionless.com/api/v1/contacts/user_42 \
  -H "Authorization: Bearer $FRICTIONLESS_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Ada Obi",
    "email": "ada@example.com",
    "phone": "+2348012345678",
    "attributes": { "plan": "Business", "kycVerified": true, "walletBalance": 45000 }
  }'
```

Returns the contact, and `linkedChats`: how many chats it's now linked to.

## Send an event

`POST /events`. Say who it happened to with:

* `userId`: best. Saved even before they ever chat, and creates the contact if needed.
* `phone`: for someone already chatting on WhatsApp.
* or both.

`amount` and `reference` in `properties` get their own rows on the card.

```bash theme={null}
curl -X POST https://api.usefrictionless.com/api/v1/events \
  -H "Authorization: Bearer $FRICTIONLESS_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "user_42",
    "event": "Transfer failed",
    "properties": { "amount": "NGN 45,000", "reference": "TRX_0001", "reason": "Insufficient funds" },
    "level": "problem"
  }'
```

`level` is optional. `"problem"` puts the event at the top of the agent's panel in red, `"info"` keeps it in the list. Leave it out and Frictionless decides from the name: words like *failed*, *declined* or *rejected* make it a problem.

Returns `201` with the event's `id` and `postedToConversations`: how many active chats received a card. `occurredAt` (ISO 8601) is optional and defaults to now.

## In Node.js

```js theme={null}
async function sendEvent(userId, event, properties) {
  const res = await fetch("https://api.usefrictionless.com/api/v1/events", {
    method: "POST",
    headers: {
      Authorization: "Bearer " + process.env.FRICTIONLESS_SECRET_KEY,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ userId, event, properties }),
  });
  if (!res.ok) {
    const { error } = await res.json();
    throw new Error(error.code + ": " + error.message);
  }
  return res.json();
}

await sendEvent("user_42", "Transfer failed", { amount: "NGN 45,000", reference: "TRX_0001" });
```

## Read or delete a contact

* `GET /contacts/:userId` returns the contact and its latest 20 events, which helps when checking an integration.
* `DELETE /contacts/:userId` removes the contact and its events, for example when a user deletes their account with you. Chats and messages stay.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.