Telemetry
Browse docs
SDKsUpdated July 27, 2026Reviewed by the Telemetry product team2 min read

Use this doc with your coding agent

Copy a Telemetry prompt and ask Claude Code, Codex, or Cursor to instrument the workflow covered here.

On this page
  1. Send an event
  2. Run a SQL query
  3. Production checklist

PHP

Use PHP's cURL extension to call the Telemetry HTTP API from server-side application code.

Send an event

<?php

$apiKey = getenv("TELEMETRY_API_KEY");

$payload = [
    "table" => "api_requests",
    "data" => [
        "route_template" => "/api/projects/:id",
        "method" => "GET",
        "status_code" => 200,
        "latency_ms" => 184,
    ],
];

$request = curl_init("https://api.telemetry.sh/log");
curl_setopt_array($request, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        "Authorization: " . $apiKey,
        "Content-Type: application/json",
    ],
    CURLOPT_POSTFIELDS => json_encode($payload, JSON_THROW_ON_ERROR),
]);

$body = curl_exec($request);
$status = curl_getinfo($request, CURLINFO_HTTP_CODE);

if ($body === false || $status < 200 || $status >= 300) {
    throw new RuntimeException("Telemetry log failed with HTTP " . $status);
}

curl_close($request);

Telemetry adds timestamp_utc to every row. Keep the API key in a server-side environment variable and send categorized error context rather than raw request bodies, credentials, or private customer content.

Run a SQL query

Use a read-scoped key when the process only queries data.

<?php

$sql = <<<'SQL'
SELECT
  route_template,
  COUNT(*) AS requests,
  ROUND(AVG(latency_ms), 0) AS avg_latency_ms
FROM api_requests
WHERE timestamp_utc >= now() - INTERVAL '24 hours'
GROUP BY route_template
ORDER BY requests DESC;
SQL;

$request = curl_init("https://api.telemetry.sh/query");
curl_setopt_array($request, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        "Authorization: " . $apiKey,
        "Content-Type: application/json",
    ],
    CURLOPT_POSTFIELDS => json_encode(["query" => $sql], JSON_THROW_ON_ERROR),
]);

$body = curl_exec($request);
$status = curl_getinfo($request, CURLINFO_HTTP_CODE);

if ($body === false || $status < 200 || $status >= 300) {
    throw new RuntimeException("Telemetry query failed with HTTP " . $status);
}

$results = json_decode($body, true, flags: JSON_THROW_ON_ERROR);
curl_close($request);

Production checklist

Set cURL connection and request timeouts, handle non-2xx responses without printing the API key, and retry only transient failures with backoff. Keep event names and field types stable as the table evolves. Exercise success, failure, retry, and timeout branches with synthetic events before creating an operational alert.

See the Log API, Query API, and SQL recipe library for more examples.