# Sending data from Segment

Source: https://kirora.io/docs/api/segment

Point Segment's libraries or a Segment webhook destination at Kirora, and see how each call maps to Kirora data.

If your team already sends data through Segment, Kirora takes it in Segment's own
format: point a Segment library at Kirora, or add Kirora as a webhook destination in
your Segment workspace. Nothing in your tracking calls changes.

## Point a Segment library at Kirora

Segment's server libraries send to whatever host you give them. Use a Kirora API key
with the `contacts:write` and `events:write` scopes as the write key, and
`https://api.kirora.io/segment` as the host:

```js
import { Analytics } from '@segment/analytics-node';

const analytics = new Analytics({
  writeKey: process.env.KIRORA_API_KEY,
  host: 'https://api.kirora.io/segment',
});

analytics.identify({ userId: 'customer-881', traits: { email: 'ada@example.com' } });
analytics.track({ userId: 'customer-881', event: 'Order Completed', properties: { total: 125.5 } });
```

```python
import os
import segment.analytics as analytics

analytics.write_key = os.environ["KIRORA_API_KEY"]
analytics.host = "https://api.kirora.io/segment"
```

Other Segment libraries take the address in different forms. Use the form your library
expects:

| Library | Setting |
| --- | --- |
| Python | `analytics.host = "https://api.kirora.io/segment"` |
| Go | `Endpoint: "https://api.kirora.io/segment"` |
| PHP | `"host" => "api.kirora.io/segment"` |
| Ruby | `host: "api.kirora.io", path: "/segment/v1/import"` |
| Java | `setUploadURL("https://api.kirora.io/segment/v1/import")` |

The libraries post to `/segment/v1/batch` (Ruby and Java to `/segment/v1/import`),
with the key as Basic auth's user name. Kirora also accepts the call types
(`/segment/v1/identify`, `track`, `page`, `screen`) and a trailing slash. Segment's
browser and mobile SDKs also load settings from Segment's CDN, so use Kirora's web SDK in
the browser instead.

## Requirements

- **Scopes**: the key needs `contacts:write` and `events:write`.
- **Plan**: every `/segment/v1` call needs the integrations feature (Starter and above).
  On Free, each call is refused with 403 `PLAN_FEATURE_UNAVAILABLE`. Track, page and
  screen calls count against the plan's monthly event allowance.
- **Key kind**: an `agent` key is refused with 403, because it cannot write contacts or
  track events. See [Agents](https://kirora.io/docs/api/agents).

## From your Segment workspace

Add a **Webhooks (Actions)** destination with the URL
`https://api.kirora.io/segment/v1/webhook` and a header
`Authorization: Bearer <your Kirora API key>`. Send the raw Segment event as the body,
one at a time or batched (an array of events). A **destination function** can `fetch` the same URL.

## How calls become Kirora data

| Segment call | In Kirora |
| --- | --- |
| `identify` | Creates or updates the contact: `userId` is its `externalId`, else the `email` trait finds it. `email`, `firstName`/`first_name`, `lastName`/`last_name`, `phone` and `name` fill the contact's fields; other traits become attributes, a nested object one level flat (`address.city` → `address_city`), a key's spaces and symbols as `_`, the first 50 kept. |
| `track` | An event of that name with its `properties`, on the contact, created when new. An email in `context.traits` finds a contact you imported by email, rather than making a second one. |
| `page` | A `Page Viewed` event; `name` and `category` join its properties. |
| `screen` | A `Screen Viewed` event, the same way. |
| `group`, `alias` | Skipped. |

- **Consent** is never read from traits: a contact Segment creates has no marketing
  consent until your app records it through the contacts API or a form.
- **Anonymous calls**, with an `anonymousId` and no `userId` or `email` trait, are
  skipped: Kirora keeps no anonymous profiles.
- **Retries** record once: each call's `messageId` is its idempotency key.
- **Times**: `timestamp` is when it happened. An event more than 72 hours old starts no journey (as in
  [e-commerce events](https://kirora.io/docs/api/ecommerce-events)).
- **Limits**: 32 KB a call, 500 KB and 500 calls a request. Each call counts as one
  request against the events rate limit.

The response is `200` with what became of each call, by its place in the request:

```json
{
  "data": {
    "accepted": 3,
    "skipped": [{ "index": 3, "reason": "anonymous" }],
    "refused": [{ "index": 5, "code": "VALIDATION_ERROR", "message": "Invalid batch entry" }]
  }
}
```

A wrong key is `401`, a body that is not JSON `400`, and one over 500 KB `413`. A
temporary failure on Kirora's side is a `5xx` for the whole request, which the libraries
retry; retried calls are not recorded twice.

## Next steps

- [Events](https://kirora.io/docs/api/events): how tracked events are named and stored
- [IDs and identity](https://kirora.io/docs/api/identifiers): how a Segment user becomes a contact
- [Limits](https://kirora.io/docs/api/limits): request sizes and rates