Atune Docs
Guides

Use Atune with Segment

Route Segment track, identify, and group messages into Atune without changing your downstream understanding model.

Twilio Segment

Atune is native-first. Use the SDK when you can install it directly.

If Segment is already your event source of truth, send Segment messages to Atune instead. Segment is an ingress adapter. After mapping, events and identity updates enter the same Atune ingest core as native capture.

Endpoint

Send single messages or batch envelopes to:

Segment endpoint
https://test.useatune.com/api/v1/segment

Use your workspace API key as a Bearer token.

Connect from Segment

Until Atune is listed in Segment's catalog, use Segment's generic Webhooks (Actions) destination. It forwards the raw Segment message, which is what this endpoint accepts. The same steps, with your real endpoint and key filled in, are on the Install page in the Atune app.

  1. In Segment, open Connections → Destinations → Add destination and pick Webhooks (Actions). Connect it to the source that carries your product events.
  2. Add a mapping with the Send action. Set the trigger to Event Type is Track, Identify or Group. Atune rejects page, screen, and alias calls.
  3. Set URL to {{ATUNE_URL}}/api/v1/segment and Method to POST.
  4. Under Headers, add Authorization with the value Bearer <YOUR_API_KEY>, using your key from Settings → API key.
  5. Leave Data as the default (the entire event). Batching is optional: Atune accepts single messages, { batch: [...] } envelopes, and the bare arrays this destination sends when batching is on. If you turn batching on, set Batch Size to 500 or lower (see Batch limits).
  6. Save and enable the destination, then send one track call and check it on the Install page or in Settings → Events, filtered to Segment.

You do not need to add a group id to your calls. Atune scores accounts, and it works out the account for each message (see Messages without an account).

Track

track creates an Atune event. When the message names an account, Atune uses this precedence:

  1. top-level accountId
  2. context.groupId
  3. context.traits.accountId (or account_id)
  4. context.traits.companyId (or company_id)
  5. properties.accountId (or account_id)
  6. properties.companyId (or company_id)
  7. properties.groupId (or group_id)
  8. context.traits.company.id or properties.company.id (Segment's reserved company object)

identify reads the same fields from its traits, so an identify with traits.company.id places the user in that account.

IDs can be strings or numbers. 14042 and "14042" name the same account.

If none of those fields exist, the event goes to the user's current account (see below). A track with neither a userId nor an account field is rejected.

Send a Segment track
curl -X POST https://test.useatune.com/api/v1/segment \-H "Authorization: Bearer <YOUR_API_KEY>" \-H "Content-Type: application/json" \-d '{  "type": "track",  "messageId": "seg-msg-001",  "event": "Invoice Sent",  "userId": "user_123",  "properties": {    "accountId": "acme",    "amount": 1200  }}'

Sign in to find your API key in Settings.

Repeated track deliveries with the same messageId are idempotent per workspace.

Identify

identify can attach name and email to a user. It is treated as personal data and requires the workspace DPA to be accepted. The account is optional. Without one, the traits are applied to every account the user belongs to.

Send a Segment identify
curl -X POST https://test.useatune.com/api/v1/segment \-H "Authorization: Bearer <YOUR_API_KEY>" \-H "Content-Type: application/json" \-d '{  "type": "identify",  "userId": "user_123",  "traits": {    "name": "Kari Nordmann",    "email": "kari@acme.example"  }}'

Sign in to find your API key in Settings.

Messages without an account

Segment's usual flow is identify first, then group, and track calls without a group id. Atune accepts this flow as it is. A message without an account is resolved from its userId:

  • The user belongs to one or more accounts. identify traits are applied to every account the user belongs to. track events go to the account the user was most recently grouped into, so the last group call wins. This covers users who belong to several accounts.
  • The user belongs to no account yet. identify creates no account. Atune keeps the user's name and email and applies them when a group call or a track with a group id places the user in an account. A track without any account becomes an account of one, with the userId as account ID, named after the user. This is how B2C products without accounts work in Atune.

A user who later joins an account. Segment's mobile SDKs (analytics-swift, analytics-kotlin) do not add context.groupId to track calls. Mobile apps often call group only at login. A user's first mobile events can then reach Atune before their group call and land on an account of one. When that user is later placed in a real account, Atune moves those events to the account and removes the account of one. You do not need to change your instrumentation. An account of one that reported a paid subscription (accountStage: paying or an MRR) is a B2C customer and stays as it is. Until then, such a person is listed under Users without a company, not as an account.

To send an event to a specific account instead, set context.groupId on that track call.

Group

group attaches company identity to an account. groupId becomes the Atune account ID. traits.company or traits.name becomes the account display name.

Send a Segment group
curl -X POST https://test.useatune.com/api/v1/segment \-H "Authorization: Bearer <YOUR_API_KEY>" \-H "Content-Type: application/json" \-d '{  "type": "group",  "groupId": "acme",  "userId": "user_123",  "traits": {    "name": "Acme AS",    "plan": "Pro",    "seats": 12  }}'

Sign in to find your API key in Settings.

Plan and lifecycle

Atune reads the account's plan, seats, stage, trial end and MRR from group and identify traits. Send them on either call, or on both.

FieldTraits Atune readsValue
Planplan, accountPlan, or company.planThe plan name in your product, for example Pro. At most 100 characters.
Seatsseats or accountSeatsA positive whole number.
StageaccountStage or stagetrial or paying, in any letter case.
Trial endtrialEndsAtAn ISO 8601 date.
MRRmrr or accountMrrWhat the account pays per month, in major units (49.5 = 49.50). 0 is kept.
Currencycurrency or accountCurrencyISO 4217 code for MRR, for example NOK.

Atune keeps a history of these values, so a paying account that lowers its MRR or seats shows up as Downgraded in the Inbox. See Trial, paying and subscription value.

On identify, the values go to the account the message resolves to. That is the account named in the message, or the user's current account if none is named (see Messages without an account). Invalid values are ignored, and the message is still accepted.

Batch

Segment-style batch envelopes are supported, and so are bare arrays of messages (what Webhooks (Actions) sends with batching on). If sentAt is present, Atune uses it as the timestamp fallback for track messages that do not include timestamp.

Send a Segment batch
curl -X POST https://test.useatune.com/api/v1/segment \-H "Authorization: Bearer <YOUR_API_KEY>" \-H "Content-Type: application/json" \-d '{  "sentAt": "2026-07-26T10:00:00.000Z",  "batch": [    {      "type": "track",      "messageId": "seg-msg-002",      "event": "Report Generated",      "properties": { "accountId": "acme" }    },    {      "type": "group",      "groupId": "acme",      "traits": { "name": "Acme AS" }    }  ]}'

Sign in to find your API key in Settings.

An invalid message does not reject the batch. Atune stores the valid messages and lists the invalid ones in rejected, each with its index and error. The response is 200, so Segment does not retry the whole batch. A batch with no valid messages returns 400.

If a batch contains identify or group, the whole batch requires the workspace DPA. This prevents partial identity writes.

Batch limits

LimitValueOver the limit
Batch request body512 KB413, nothing stored
Messages per batch1000413, nothing stored
One message, alone or inside a batch16 KBAlone: 413. Inside a batch: listed in rejected, the rest is stored
Messages per workspace2,000 events per 10 seconds by default, and separately 2,000 identify/group writes (accounts and users touched)429 with Retry-After: 10, nothing from the request is stored

Every message in a batch counts toward the rate limit. A full batch of 1000 fits, but Segment can send several batches at once, so with batching on in Webhooks (Actions) set Batch Size to 500 or lower. That leaves room for parallel batches and your other traffic in the same 10 seconds. Segment retries a 429 but not a 413.

Known limitation: the limit is soft under parallel bursts. Each request checks the count and then stores, so requests that arrive at the same moment can all pass. In a test with 10 parallel batches, 8× the limit was stored. The limit throttles sustained traffic; it does not cap a single parallel burst.

When you get 429

The response says what happened and what to do:

{
  "error": "Rate limit exceeded",
  "detail": "This workspace may send at most 2000 messages per 10 seconds for events, and separately 2000 identify/group writes (counted as accounts and users touched), and every message in a batch counts. Nothing from this request was stored. Retry after 10 seconds, or send smaller batches (Segment: Batch Size 500 or lower).",
  "limit": 2000,
  "windowSeconds": 10
}
  • Nothing from the request was stored, so resending it creates no duplicates. Segment does this on its own.
  • Wait for Retry-After seconds before sending again.
  • If you hit the limit regularly, lower Batch Size first. If your normal volume needs a higher limit, contact us. The limit is set per workspace.
  • Atune counts every refused message per workspace, so we can see when a workspace keeps hitting its limit.

On this page