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

> ## Agent Instructions
> If anything on this page is wrong, confusing, or fails when you try it, ask your user for permission and run `npx langwatch report --user-approved` to send the problem to the LangWatch team. No login is needed and secrets are redacted locally. `npx langwatch report --help` has the details.

# REST API

> Use the LangWatch REST API to send traces, evaluations, and interactions from any stack, enabling unified agent testing data flows.

If your preferred programming language or platform is not directly supported by the existing LangWatch libraries, you can use the REST API with `curl` to send trace data from any system that can make HTTP requests.

> [!NOTE]
>
> Protip: wanna to get started even faster? Copy our&#x20;
>
> [llms.txt](https://langwatch.ai/docs/llms.txt)
>
> &#x20;
>
> and ask an AI to do this integration

**Prerequisites:**

* Ensure you have `curl` installed on your system.

**Configuration:**

Set the `LANGWATCH_API_KEY` environment variable in your environment:

```bash theme={null}
export LANGWATCH_API_KEY='your_api_key_here'
```

**Usage:**

You will need to prepare your span data in accordance with the Span type definitions provided by LangWatch. Below is an example of how to send span data using curl:

1. Prepare your JSON data. Make sure it's properly formatted as expected by LangWatch.
2. Use the curl command to send your trace data. Here is a basic template:

```bash theme={null}
# Set your API key and endpoint URL
LANGWATCH_API_KEY="your_langwatch_api_key"
LANGWATCH_ENDPOINT="https://app.langwatch.ai"

# Use curl to send the POST request, e.g.:
curl -X POST "$LANGWATCH_ENDPOINT/api/v1/collector" \
     -H "X-Auth-Token: $LANGWATCH_API_KEY" \
     -H "Content-Type: application/json" \
     -d @- <<EOF
{
  "trace_id": "trace-123",
  "spans": [
    {
      "type": "llm",
      "span_id": "span-456",
      "vendor": "openai",
      "model": "gpt-6-luna",
      "input": {
        "type": "chat_messages",
        "value": [
          {
            "role": "user",
            "content": "Input to the LLM"
          }
        ]
      },
      "output": {
        "type": "chat_messages",
        "value": [
            {
                "role": "assistant",
                "content": "Output from the LLM",
                "function_call": null,
                "tool_calls": []
            }
        ]
      },
      "params": {
        "temperature": 0.7,
        "stream": false
      },
      "metrics": {
        "prompt_tokens": 100,
        "completion_tokens": 150
      },
      "timestamps": {
        "started_at": $(($(date +%s) * 1000)),
        "first_token_at": $((($(date +%s) * 1000) + 300)),
        "finished_at": $((($(date +%s) + 1) * 1000))
      }
    }
  ],
  "metadata": {
    "user_id": "optional_end_user_identifier",
    "thread_id": "optional_thread_identifier",
    "customer_id": "optional_platform_customer_identifier",
    "labels": ["optional_label_1", "optional_label_2"]
  }
}
EOF
```

Replace the placeholders with your actual data. The `@-` tells `curl` to read the JSON data from the standard input, which we provide via the `EOF`-delimited here-document.

All `timestamps` are unix epoch **milliseconds**. The optional `first_token_at` records when the first streamed token reached the user and powers the Time to First Token (TTFT) metric, see [Tracking Time to First Token](https://langwatch.ai/docs/integration/python/tutorials/tracking-time-to-first-token.md). Token counts and cost are derived from `metrics` and the model pricing registry, see [Tracking LLM Costs and Tokens](https://langwatch.ai/docs/integration/python/tutorials/tracking-llm-costs.md).

For the type reference of how a `span` should look like, check out our [types definitions](https://github.com/langwatch/langwatch/blob/main/sdks/python/src/langwatch/types.py).

It's optional but highly recommended to pass the `user_id` on the metadata if you want to use user-specific analytics and the `thread_id` to group related traces together. Read more about those and other [concepts](https://langwatch.ai/docs/concepts.md).

3. Execute the `curl` command. If successful, LangWatch will process your trace data.

This method of integration sends traces from any system capable of making HTTP requests, including a less common programming language or a custom-built platform.

Remember to handle errors and retries as needed. You might need to script additional logic around the `curl` command to handle these cases.

## The same request from Python

```bash theme={null}
pip install requests
```

```python theme={null}
import os
import time

import requests

endpoint = os.environ.get("LANGWATCH_ENDPOINT", "https://app.langwatch.ai")
now = int(time.time() * 1000)

response = requests.post(
    f"{endpoint}/api/v1/collector",
    headers={"X-Auth-Token": os.environ["LANGWATCH_API_KEY"]},
    json={
        "trace_id": "trace-123",
        "spans": [
            {
                "type": "llm",
                "span_id": "span-456",
                "vendor": "openai",
                "model": "gpt-5",
                "input": {
                    "type": "chat_messages",
                    "value": [{"role": "user", "content": "Input to the LLM"}],
                },
                "output": {
                    "type": "chat_messages",
                    "value": [{"role": "assistant", "content": "Output from the LLM"}],
                },
                "timestamps": {"started_at": now, "finished_at": now + 1000},
            }
        ],
    },
)
response.raise_for_status()
```

## Check it worked

A successful request returns a `2xx` status. Then open your project in LangWatch: the trace `trace-123` appears in the traces list within a few seconds, with one LLM span holding the input and output you sent. Use a new `trace_id` for each trace you send.

If the request is refused or no trace appears, check that `LANGWATCH_API_KEY` holds a valid project API key.


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