NewInstance Documentation
View as Markdown

OpenTelemetry, Prometheus & Tracing

OpenTelemetry, Prometheus remote-write, Jaeger trace queries, and RUM web-vitals ingest for BugWatch.

Scope required for all write endpoints: ingest:write

Key facts:

  • OTLP/HTTP (/v1/logs, /v1/traces, /v1/metrics) accept both application/json and application/x-protobuf. The OpenTelemetry Collector sends protobuf by default; the requests in this folder use JSON for readability.
  • An OTLP/gRPC receiver is also available on port 4317 (logs, traces and metrics services); pass the same credential as gRPC metadata (x-api-key or authorization: Bearer ...).
  • The BugWatch JS and PHP SDKs export their own spans (withSpan/startSpan) to POST /v1/traces natively, so you do not need an OTel SDK or collector for BugWatch tracing.
  • POST /api/v1/prom/write accepts Snappy-compressed Prometheus protobuf, which is always sent by the Prometheus remote-write adapter or the bugwatch-otel-collector. This folder documents the endpoint but does not include a fake binary body.
  • Prometheus query endpoints (/query, /query_range, /label/__name__/values) are fully runnable; /query and /query_range also accept POST with form-encoded parameters, which is what Grafana's Prometheus data source sends by default.
  • Jaeger GET endpoints (/jaeger/api/services, /jaeger/api/traces, /jaeger/api/traces/{traceId}) are fully runnable.
  • RUM (/api/v1/rum) accepts x-bugwatch-session (browser) or x-api-key (server).

Auth header: x-api-key: {{apiKey}} or Authorization: Bearer {{apiKey}}

OTLP/HTTP – ingest logs (JSON)

POST/v1/logs

Sends OpenTelemetry logs to BugWatch over OTLP/HTTP.

Scope: ingest:write

Send application/json, as in this example, or application/x-protobuf with a protobuf ExportLogsServiceRequest, which is what the OTel Collector sends. A fully accepted batch answers with an empty {} object.

Authorization

x-api-keyAPI key · headerrequired

Request body

application/json
{
  "resourceLogs": [
    {
      "resource": {
        "attributes": [
          {
            "key": "service.name",
            "value": {
              "stringValue": "my-service"
            }
          }
        ]
      },
      "scopeLogs": [
        {
          "logRecords": [
            {
              "timeUnixNano": "{{nowNano}}",
              "severityNumber": 9,
              "severityText": "INFO",
              "body": {
                "stringValue": "User signed in"
              },
              "attributes": [
                {
                  "key": "user.id",
                  "value": {
                    "stringValue": "usr_123"
                  }
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}

Responses

200All accepted
401Invalid or missing API key
429Rate limited
curl -X POST 'https://api.newinstance.cloud/v1/logs' \
  -H 'x-api-key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  --data-raw '{
  "resourceLogs": [
    {
      "resource": {
        "attributes": [
          {
            "key": "service.name",
            "value": {
              "stringValue": "my-service"
            }
          }
        ]
      },
      "scopeLogs": [
        {
          "logRecords": [
            {
              "timeUnixNano": "{{nowNano}}",
              "severityNumber": 9,
              "severityText": "INFO",
              "body": {
                "stringValue": "User signed in"
              },
              "attributes": [
                {
                  "key": "user.id",
                  "value": {
                    "stringValue": "usr_123"
                  }
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}'
Response
null

OTLP/HTTP – ingest traces (JSON)

POST/v1/traces

Sends OpenTelemetry traces to BugWatch over OTLP/HTTP.

Scope: ingest:write

Send application/json, as in this example, or application/x-protobuf with a protobuf ExportTraceServiceRequest, which is what the OTel Collector sends. A fully accepted batch answers with an empty {} object.

Authorization

x-api-keyAPI key · headerrequired

Request body

application/json
{
  "resourceSpans": [
    {
      "resource": {
        "attributes": [
          {
            "key": "service.name",
            "value": {
              "stringValue": "my-service"
            }
          }
        ]
      },
      "scopeSpans": [
        {
          "spans": [
            {
              "traceId": "4bf92f3577b34da6a3ce929d0e0e4736",
              "spanId": "00f067aa0ba902b7",
              "name": "HTTP GET /api/users",
              "kind": 2,
              "startTimeUnixNano": "{{nowNano}}",
              "endTimeUnixNano": "{{nowNano}}",
              "status": {
                "code": 1
              },
              "attributes": [
                {
                  "key": "http.method",
                  "value": {
                    "stringValue": "GET"
                  }
                },
                {
                  "key": "http.status_code",
                  "value": {
                    "intValue": 200
                  }
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}

Responses

200All accepted
401Invalid or missing API key
429Rate limited
curl -X POST 'https://api.newinstance.cloud/v1/traces' \
  -H 'x-api-key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  --data-raw '{
  "resourceSpans": [
    {
      "resource": {
        "attributes": [
          {
            "key": "service.name",
            "value": {
              "stringValue": "my-service"
            }
          }
        ]
      },
      "scopeSpans": [
        {
          "spans": [
            {
              "traceId": "4bf92f3577b34da6a3ce929d0e0e4736",
              "spanId": "00f067aa0ba902b7",
              "name": "HTTP GET /api/users",
              "kind": 2,
              "startTimeUnixNano": "{{nowNano}}",
              "endTimeUnixNano": "{{nowNano}}",
              "status": {
                "code": 1
              },
              "attributes": [
                {
                  "key": "http.method",
                  "value": {
                    "stringValue": "GET"
                  }
                },
                {
                  "key": "http.status_code",
                  "value": {
                    "intValue": 200
                  }
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}'
Response
null

OTLP/HTTP – ingest metrics (JSON)

POST/v1/metrics

Sends OpenTelemetry metrics to BugWatch over OTLP/HTTP.

Scope: ingest:write

Send application/json, as in this example, or application/x-protobuf with a protobuf ExportMetricsServiceRequest, which is what the OTel Collector sends. A fully accepted batch answers with an empty {} object.

Authorization

x-api-keyAPI key · headerrequired

Request body

application/json
{
  "resourceMetrics": [
    {
      "resource": {
        "attributes": [
          {
            "key": "service.name",
            "value": {
              "stringValue": "my-service"
            }
          }
        ]
      },
      "scopeMetrics": [
        {
          "metrics": [
            {
              "name": "http.server.request.duration",
              "unit": "ms",
              "gauge": {
                "dataPoints": [
                  {
                    "timeUnixNano": "{{nowNano}}",
                    "asDouble": 123.4,
                    "attributes": [
                      {
                        "key": "http.method",
                        "value": {
                          "stringValue": "GET"
                        }
                      }
                    ]
                  }
                ]
              }
            }
          ]
        }
      ]
    }
  ]
}

Responses

200All accepted
401Invalid or missing API key
429Rate limited
curl -X POST 'https://api.newinstance.cloud/v1/metrics' \
  -H 'x-api-key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  --data-raw '{
  "resourceMetrics": [
    {
      "resource": {
        "attributes": [
          {
            "key": "service.name",
            "value": {
              "stringValue": "my-service"
            }
          }
        ]
      },
      "scopeMetrics": [
        {
          "metrics": [
            {
              "name": "http.server.request.duration",
              "unit": "ms",
              "gauge": {
                "dataPoints": [
                  {
                    "timeUnixNano": "{{nowNano}}",
                    "asDouble": 123.4,
                    "attributes": [
                      {
                        "key": "http.method",
                        "value": {
                          "stringValue": "GET"
                        }
                      }
                    ]
                  }
                ]
              }
            }
          ]
        }
      ]
    }
  ]
}'
Response
null

Prometheus remote-write (DOCUMENTATION ONLY)

POST/api/v1/prom/write

Receives Prometheus remote-write samples.

Scope: ingest:write

To use Prometheus remote-write with BugWatch:

  1. Deploy the bugwatch-otel-collector (or configure Prometheus remote_write).
  2. Set the remote-write URL to {{baseUrl}}/api/v1/prom/write.
  3. Add the header x-api-key: sk_live_KEYID:secret.

Authorization

x-api-keyAPI key · headerrequired

Headers

X-Prometheus-Remote-Write-Version

Request body

text/plain
<<< BINARY SNAPPY-COMPRESSED PROTOBUF - sent by Prometheus/collector, not a manual JSON request >>>

Responses

204Samples accepted
400Malformed protobuf
401Invalid or missing API key
429Rate limited
curl -X POST 'https://api.newinstance.cloud/api/v1/prom/write' \
  -H 'x-api-key: YOUR_API_KEY' \
  -H 'Content-Type: text/plain' \
  --data-raw '<<< BINARY SNAPPY-COMPRESSED PROTOBUF - sent by Prometheus/collector, not a manual JSON request >>>'
Response
null

Prometheus query (instant)

GET/api/v1/prom/query

Returns the latest value of each matching metric series at one point in time, using a PromQL-compatible selector.

Scope: ingest:write (the key you write with is accepted for queries)

The same query also works as a POST with form-encoded parameters, which is what Grafana's Prometheus data source sends.

Authorization

x-api-keyAPI key · headerrequired

Parameters

queryquery · stringdefault:

Required. Metric name or label selector, such as http_requests_total or {service="api-gateway"}.

timequery · stringdefault:

Optional. Evaluation time in Unix seconds (decimals allowed). Defaults to now.

Responses

200Instant vector
401Invalid or missing API key
curl -X GET 'https://api.newinstance.cloud/api/v1/prom/query?query=http_requests_total&time=1767225600' \
  -H 'x-api-key: YOUR_API_KEY'
Response
{
  "status": "success",
  "data": {
    "resultType": "vector",
    "result": [
      {
        "metric": {
          "__name__": "http_requests_total",
          "service": "api"
        },
        "value": [
          1767225600,
          "42"
        ]
      }
    ]
  }
}

Prometheus query_range (over time)

GET/api/v1/prom/query_range

Returns every stored point of each matching metric series over a time range.

Scope: ingest:write

The same query also works as a POST with form-encoded parameters, which is what Grafana's Prometheus data source sends.

Authorization

x-api-keyAPI key · headerrequired

Parameters

queryquery · stringdefault:

Required. Metric name or label selector, such as http_requests_total or {service="api-gateway"}.

startquery · stringdefault:

Range start in Unix seconds (decimals allowed). Defaults to 0, the oldest stored point.

endquery · stringdefault:

Range end in Unix seconds (decimals allowed). Defaults to now.

Responses

200Matrix result
401Invalid or missing API key
curl -X GET 'https://api.newinstance.cloud/api/v1/prom/query_range?query=http_requests_total&start=1767222000&end=1767225600' \
  -H 'x-api-key: YOUR_API_KEY'
Response
{
  "status": "success",
  "data": {
    "resultType": "matrix",
    "result": [
      {
        "metric": {
          "__name__": "http_requests_total"
        },
        "values": [
          [
            1767222000,
            "38"
          ],
          [
            1767225600,
            "42"
          ]
        ]
      }
    ]
  }
}

Prometheus label __name__ values (list metric names)

GET/api/v1/prom/label/__name__/values

Lists every distinct metric name stored for the project and environment your key is scoped to.

Scope: ingest:write

Authorization

x-api-keyAPI key · headerrequired

Responses

200Metric names
401Invalid or missing API key
curl -X GET 'https://api.newinstance.cloud/api/v1/prom/label/__name__/values' \
  -H 'x-api-key: YOUR_API_KEY'
Response
{
  "status": "success",
  "data": [
    "http_requests_total",
    "rum.lcp",
    "rum.cls",
    "rum.inp"
  ]
}

Jaeger – list service names

GET/jaeger/api/services

Lists the distinct service names that have sent traces to this BugWatch project.

Scope: ingest:write (the same API key)

Authorization

x-api-keyAPI key · headerrequired

Responses

200Services
401Invalid or missing API key
curl -X GET 'https://api.newinstance.cloud/jaeger/api/services' \
  -H 'x-api-key: YOUR_API_KEY'
Response
{
  "data": [
    "api-gateway",
    "payment-service",
    "user-service"
  ],
  "total": 3,
  "limit": 3,
  "offset": 0,
  "errors": null
}

Jaeger – list traces

GET/jaeger/api/traces

Lists recent distributed traces for the project and environment your key is scoped to, newest first, each with its spans in the Jaeger format.

Scope: ingest:write

Authorization

x-api-keyAPI key · headerrequired

Parameters

limitquery · stringdefault:

Optional. Maximum number of traces, up to 100. Defaults to 20.

lookbackquery · stringdefault:

Optional. How far back to look: 1h, 24h, 7d or 30d. Defaults to 1h; any other value is treated as 1h.

Responses

200Traces list
401Invalid or missing API key
curl -X GET 'https://api.newinstance.cloud/jaeger/api/traces?limit=20&lookback=1h' \
  -H 'x-api-key: YOUR_API_KEY'
Response
{
  "data": [],
  "total": 0,
  "limit": 20,
  "offset": 0,
  "errors": null
}

Jaeger – get one trace

GET/jaeger/api/traces/{traceId}

Returns every span of one trace in the Jaeger format.

Scope: ingest:write

traceId in the path is the 32-character hex trace identifier, as sent in traceparent or returned by Jaeger – list traces. A trace id with no stored spans answers 200 with an empty data list, not 404.

Authorization

x-api-keyAPI key · headerrequired

Parameters

traceIdpath · stringrequireddefault:

Responses

200Trace
401Invalid or missing API key
curl -X GET 'https://api.newinstance.cloud/jaeger/api/traces/{traceId}' \
  -H 'x-api-key: YOUR_API_KEY'
Response
{
  "data": [
    {
      "traceID": "4bf92f3577b34da6a3ce929d0e0e4736",
      "spans": []
    }
  ],
  "total": 1,
  "limit": 1,
  "offset": 0,
  "errors": null
}

RUM – ingest web-vitals

POST/api/v1/rum

Ingests Real User Monitoring (RUM) web-vitals metrics (LCP, CLS, INP, FID, TTFB).

Authenticate with x-bugwatch-session from a browser, or with x-api-key from a server or while testing.

Scope (for x-api-key): ingest:write

Request body: three shapes are accepted.

  1. Wrapped array:
{ "vitals": [{ "name": "LCP", "value": 1250.5, "url": "https://example.com/", "rating": "good" }] }
  1. Bare array:
[{ "name": "CLS", "value": 0.05, "rating": "good" }, { "name": "INP", "value": 180, "rating": "needs-improvement" }]
  1. Single vital object:
{ "name": "TTFB", "value": 320, "url": "https://example.com/checkout", "rating": "needs-improvement" }

Vital field schema:

FieldTypeNotes
namestring (required)LCP, CLS, INP, FID, TTFB
valuenumber (required)Metric value in ms (or unitless for CLS)
urlstring (optional)Page URL
ratingstring (optional)good, needs-improvement or poor
idstring (optional)Client-side unique id

Vitals are stored as rum.<name_lower> metric points (for example rum.lcp, rum.cls). A browser call from an origin outside the project's allowed origins is refused with 401, the same as a bad session token.

Authorization

x-api-keyAPI key · headerrequired

Request body

application/json
{
  "vitals": [
    {
      "name": "LCP",
      "value": 1250.5,
      "url": "https://example.com/",
      "rating": "good"
    },
    {
      "name": "CLS",
      "value": 0.05,
      "url": "https://example.com/",
      "rating": "good"
    },
    {
      "name": "INP",
      "value": 180,
      "url": "https://example.com/",
      "rating": "needs-improvement"
    }
  ]
}

Responses

202Vitals ingested
400Malformed JSON
401Invalid or missing API key
429Rate limited
curl -X POST 'https://api.newinstance.cloud/api/v1/rum' \
  -H 'x-api-key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  --data-raw '{
  "vitals": [
    {
      "name": "LCP",
      "value": 1250.5,
      "url": "https://example.com/",
      "rating": "good"
    },
    {
      "name": "CLS",
      "value": 0.05,
      "url": "https://example.com/",
      "rating": "good"
    },
    {
      "name": "INP",
      "value": 180,
      "url": "https://example.com/",
      "rating": "needs-improvement"
    }
  ]
}'
Response
{
  "ingested": 3
}