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

# Track custom events

> Define business events and send customer activity to YCloud.

## What it is

Custom Events represent activity from your application, website, store, or
backend system. Define the event schema once, then send occurrences that can be
used by YCloud customer workflows.

## Before you begin

* Choose a stable event name that will not change with display copy.
* Identify the contact associated with each event.
* Define the event properties and their data types.
* Decide which system timestamp represents when the activity occurred.

## How it works

1. Create an event definition.
2. Add or update property definitions as the schema evolves.
3. Send event occurrences using the exact definition name.
4. Associate each occurrence with a contact ID, phone number, or Meta username.
5. Monitor rejected events and schema mismatches.

Event definitions are contracts. Changing a label or description is safer than
changing the meaning of an existing name or property.

## Request

### Create an event definition

`POST /event/definitions`

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl --request POST https://api.ycloud.com/v2/event/definitions \
  --header "X-API-Key: $YCLOUD_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "name": "order_completed",
    "label": "Order completed",
    "description": "A customer completed an order.",
    "objectType": "CONTACT",
    "properties": [
      {
        "name": "order_value",
        "label": "Order value",
        "type": "NUMBER"
      }
    ]
  }'
```

### Choose a contact identifier

For an event defined with `objectType: CONTACT`, provide one of these identifiers:

| Field | How YCloud identifies the contact |
| - | - |
| `objectId` | Uses the numeric ID of an existing contact in your account. If the contact does not exist, the request fails. |
| `contactPhoneNumber` | Looks up an E.164 phone number in your account and creates a contact if no match exists. |
| `contactUsername` | Matches the saved Meta username of an existing contact in your account. If no match exists, the request fails without creating a contact. |

Only one identifier is used for each event. If you provide multiple identifiers,
a numeric `objectId` takes precedence, followed by a non-blank
`contactPhoneNumber`, then `contactUsername`. If a numeric contact ID is not
found, YCloud rejects the request without trying the phone number or username.

Use the Meta username saved on the contact, without the leading `@`.
`contactUsername` is a top-level request field, separate from `properties`.
You do not need to add it to the event's property definitions.

### Send an event by phone number

`POST /event/events`

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl --request POST https://api.ycloud.com/v2/event/events \
  --header "X-API-Key: $YCLOUD_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "eventName": "order_completed",
    "occurTime": "2026-07-16T12:00:00.000Z",
    "contactPhoneNumber": "+16315551111",
    "properties": {
      "order_value": 99.9
    }
  }'
```

### Send an event by username

If you know the contact's Meta username, you can send the same event without a
phone number or contact ID. In this example, `customer_demo` must already be
saved on a contact in your account.

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl --request POST https://api.ycloud.com/v2/event/events \
  --header "X-API-Key: $YCLOUD_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "eventName": "order_completed",
    "occurTime": "2026-07-16T12:00:00.000Z",
    "contactUsername": "customer_demo",
    "properties": {
      "order_value": 99.9
    }
  }'
```

## Response

Creating a definition returns the saved definition.

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "name": "order_completed",
  "label": "Order completed",
  "objectType": "CONTACT",
  "properties": [
    {
      "name": "order_value",
      "label": "Order value",
      "type": "NUMBER"
    }
  ]
}
```

A successfully accepted event occurrence returns HTTP `200` with an empty JSON
object.

```http theme={"theme":{"light":"github-light","dark":"github-dark"}}
HTTP/1.1 200 OK
Content-Type: application/json

{}
```

## Schema evolution

* Add new optional properties when possible.
* Do not reuse an existing property name for a different meaning.
* Validate types before sending events.
* Keep event names and property names stable across environments.
* Version the event name when a breaking semantic change is unavoidable.

## Limits and troubleshooting

* The event definition must exist before an occurrence is sent.
* Property names and values must match the definition.
* Use RFC 3339 for `occurTime`.
* Ensure the contact identifier resolves to the intended customer in your account.
* For `contactUsername`, check that the contact already exists and that the
  username matches the saved value without a leading `@`.
* Omit identifiers you do not want YCloud to use. A supplied phone number takes
  precedence over a username.
* A `200` response confirms acceptance, not that a downstream automation
  completed.

<CardGroup cols={2}>
  <Card title="Create event definition" icon="list-check" href="/api-reference/custom-events/create-an-event-definition">
    Inspect definition and property schemas.
  </Card>

  <Card title="Send an event" icon="bolt" href="/api-reference/custom-events/send-an-event">
    Inspect the occurrence request contract.
  </Card>
</CardGroup>


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