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

# Send traces via OpenTelemetry (OTLP)

> Push your traces to Glassray directly with an OpenTelemetry exporter - the alternative to connecting Langfuse, LangSmith, or PostHog.

If you already instrument with OpenTelemetry, you can push traces straight to Glassray instead of [connecting a provider](/traces). Point your existing OTel exporter at Glassray's OTLP endpoint with a Bearer key - no separate Glassray SDK.

<Note>
  Not on OpenTelemetry? The [`@glassray/tracing` SDK](/sdk-quickstart) is the zero-dependency drop-in path - same endpoint, no OTel setup. And if you *are* pointing an existing OTel exporter here, read [Bring your own OTel](/sdk-byo-otel) first: the ingest expects each trace's spans in a single request.
</Note>

## Endpoint

```http theme={null}
POST https://app.glassray.ai/api/public/otel/v1/traces
```

* **Format:** OTLP/HTTP **JSON** - the standard `ExportTraceServiceRequest` shape, `{ "resourceSpans": [ ... ] }`.
* **`Content-Type: application/json`** is required.
* **`Content-Encoding: gzip`** is supported (and decoded transparently).

## Authentication

Send an API key as a Bearer token. The key must carry the **`traces:write`** permission.

```http theme={null}
Authorization: Bearer <your-api-key>
```

<Info>
  Create the endpoint and key under **Settings → Sources** - add an OTLP source and Glassray reveals a `traces:write` key (once) alongside ready-to-paste exporter snippets.
</Info>

## Exporter configuration

For any OTel-instrumented app, set the standard environment variables. Point `OTEL_EXPORTER_OTLP_ENDPOINT` at the **base** path - the OTel exporter appends `/v1/traces` itself.

```bash theme={null}
export OTEL_EXPORTER_OTLP_ENDPOINT="https://app.glassray.ai/api/public/otel"
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer <your-api-key>"
```

If you configure an exporter explicitly in code, use the full traces URL (`https://app.glassray.ai/api/public/otel/v1/traces`) with the same `Authorization` header.

<Tip>
  This works with any OTel-compatible GenAI instrumentation - OpenLIT, OpenLLMetry, Arize OpenInference, or a self-hosted OpenTelemetry Collector. Point it at the endpoint with the Bearer header and swap Glassray in alongside your other backends.
</Tip>

## Behavior

<CardGroup cols={2}>
  <Card title="Success" icon="circle-check">
    A `200` with an empty `{}` body acknowledges the batch.
  </Card>

  <Card title="Idempotent" icon="rotate">
    Re-sending the same spans is a no-op - traces are keyed by source and id, so retries are safe.
  </Card>
</CardGroup>

### Size limits

* Payloads larger than **32 MB** are rejected with `413`.
* A single trace whose stored document exceeds **16 MiB** is skipped (not stored) rather than failing the whole batch.

### Error codes

| Code  | Meaning                                                                                               |
| ----- | ----------------------------------------------------------------------------------------------------- |
| `400` | Malformed JSON, or an invalid gzip payload.                                                           |
| `401` | Missing or invalid API key.                                                                           |
| `403` | The key lacks `traces:write`, the source is disabled, or ingestion is suspended for the organization. |
| `413` | Payload too large (over 32 MB).                                                                       |
| `415` | Unsupported `Content-Type` (use `application/json`) or `Content-Encoding` (only `gzip`).              |
| `503` | Ingestion is temporarily unavailable - retry; idempotency makes retries safe.                         |

<Note>
  Once traces are flowing, Glassray classifies them into [flows](/flows) and starts looking for [deviations](/deviations) - exactly as it does for pulled traces.
</Note>
