Skip to content

API reference

The Insights API is currently in beta. The API surface may change as development continues.

These endpoints are part of the Gram OpenAPI specification, available at app.getgram.ai/openapi.yaml.

All requests require authentication headers:

HeaderDescription
Gram-KeyAPI key with Consumer or Producer scope
Gram-ProjectProject identifier (slug)
Terminal window
curl -X POST "https://app.getgram.ai/rpc/telemetry.searchLogs" \
-H "Content-Type: application/json" \
-H "Gram-Key: <your-api-key>" \
-H "Gram-Project: <your-project-slug>" \
-d '{"limit": 50}'

Terminal window
POST https://app.getgram.ai/rpc/telemetry.searchLogs

Search and list telemetry logs that match a search filter.

FieldTypeDescription
limitnumberNumber of items to return (1-1000, default: 50)
sortstringSort order: asc or desc (default: desc)
cursorstringCursor for pagination
filterobjectFilter criteria (see below)
FieldTypeDescription
fromstringStart time in ISO 8601 format
tostringEnd time in ISO 8601 format
deployment_idstringFilter by deployment ID (UUID)
function_idstringFilter by function ID (UUID)
gram_urnstringFilter by single Gram URN
gram_urnsstring[]Filter by multiple Gram URNs
trace_idstringFilter by trace ID (32 hex characters)
severity_textstringFilter by severity: DEBUG, INFO, WARN, ERROR, FATAL
http_status_codenumberFilter by HTTP status code
http_routestringFilter by HTTP route
http_methodstringFilter by HTTP method: GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS
service_namestringFilter by service name
gram_chat_idstringFilter by chat session ID
user_idstringFilter by user ID
external_user_idstringFilter by external user ID
{
"logs": [
{
"id": "uuid",
"time_unix_nano": 1734605400000000000,
"observed_time_unix_nano": 1734605400000000000,
"severity_text": "INFO",
"body": "GET /api/users -> 200 (45.23ms)",
"trace_id": "abc123def456789012345678901234ab",
"span_id": "1234567890abcdef",
"attributes": {
"http.server.url": "https://api.example.com",
"http.route": "/api/users",
"http.request.method": "GET",
"http.response.status_code": 200,
"http.duration_ms": 45.23
},
"resource_attributes": {
"service.name": "gram-server",
"gram.project.id": "project-uuid",
"gram.deployment.id": "deployment-uuid",
"gram.tool.urn": "urn:gram:tool:example"
},
"service": {
"name": "gram-server",
"version": "1.0.0"
}
}
],
"next_cursor": "cursor-string",
"enabled": true
}
FieldDescription
idUnique identifier for the log entry
time_unix_nanoWhen the event occurred (Unix nanoseconds)
observed_time_unix_nanoWhen the event was observed (Unix nanoseconds)
severity_textLog severity level
bodyThe primary log message
trace_idW3C trace ID for distributed tracing
span_idW3C span ID
attributesLog-level structured data
resource_attributesMetadata about who/where generated the log
serviceService name and version
Terminal window
curl -X POST "https://app.getgram.ai/rpc/telemetry.searchLogs" \
-H "Content-Type: application/json" \
-H "Gram-Key: <your-api-key>" \
-H "Gram-Project: <your-project-slug>" \
-d '{
"limit": 100,
"filter": {
"user_id": "user-123"
}
}'

Example: Filter by time range and severity

Section titled “Example: Filter by time range and severity”
Terminal window
curl -X POST "https://app.getgram.ai/rpc/telemetry.searchLogs" \
-H "Content-Type: application/json" \
-H "Gram-Key: <your-api-key>" \
-H "Gram-Project: <your-project-slug>" \
-d '{
"filter": {
"from": "2025-12-01T00:00:00Z",
"to": "2025-12-15T23:59:59Z",
"severity_text": "ERROR"
}
}'

Terminal window
POST https://app.getgram.ai/rpc/telemetry.searchToolCalls

Search and list tool call summaries grouped by trace ID. This endpoint aggregates logs into tool call summaries for a high-level view.

FieldTypeDescription
limitnumberNumber of items to return (1-1000, default: 50)
sortstringSort order: asc or desc (default: desc)
cursorstringCursor for pagination
filterobjectFilter criteria (see below)
FieldTypeDescription
fromstringStart time in ISO 8601 format
tostringEnd time in ISO 8601 format
deployment_idstringFilter by deployment ID (UUID)
function_idstringFilter by function ID (UUID)
gram_urnstringFilter by Gram URN
{
"tool_calls": [
{
"trace_id": "abc123def456789012345678901234ab",
"start_time_unix_nano": 1734605400000000000,
"log_count": 5,
"http_status_code": 200,
"gram_urn": "urn:gram:tool:example"
}
],
"next_cursor": "cursor-string",
"enabled": true
}
FieldDescription
trace_idTrace ID grouping related logs
start_time_unix_nanoEarliest log timestamp (Unix nanoseconds)
log_countTotal number of logs in this tool call
http_status_codeHTTP status code (if applicable)
gram_urnGram URN for this tool call

Terminal window
POST https://app.getgram.ai/rpc/telemetry.getProjectMetricsSummary

Get aggregated metrics for an entire project within a time range.

FieldTypeRequiredDescription
fromstringYesStart time in ISO 8601 format
tostringYesEnd time in ISO 8601 format
{
"metrics": {
"first_seen_unix_nano": "1734519000000000000",
"last_seen_unix_nano": "1734605400000000000",
"total_input_tokens": 125000,
"total_output_tokens": 87500,
"total_tokens": 212500,
"avg_tokens_per_request": 425.0,
"total_chat_requests": 500,
"avg_chat_duration_ms": 2340.5,
"finish_reason_stop": 350,
"finish_reason_tool_calls": 150,
"total_tool_calls": 1250,
"tool_call_success": 1200,
"tool_call_failure": 50,
"avg_tool_duration_ms": 145.2,
"total_chats": 500,
"distinct_models": 3,
"distinct_providers": 2,
"models": [
{"name": "gpt-4", "count": 300},
{"name": "claude-3-sonnet", "count": 150}
],
"tools": [
{
"urn": "urn:gram:tool:search",
"count": 500,
"success_count": 485,
"failure_count": 15
}
]
},
"enabled": true
}
FieldDescription
first_seen_unix_nanoEarliest activity timestamp (Unix nanoseconds, as string)
last_seen_unix_nanoLatest activity timestamp (Unix nanoseconds, as string)
FieldDescription
total_input_tokensSum of input tokens consumed
total_output_tokensSum of output tokens consumed
total_tokensTotal tokens (input + output)
avg_tokens_per_requestAverage tokens per chat request
FieldDescription
total_chat_requestsTotal number of chat requests
avg_chat_duration_msAverage chat request duration (milliseconds)
finish_reason_stopRequests that completed naturally
finish_reason_tool_callsRequests that resulted in tool calls
FieldDescription
total_tool_callsTotal number of tool calls
tool_call_successSuccessful tool calls (2xx status)
tool_call_failureFailed tool calls (4xx/5xx status)
avg_tool_duration_msAverage tool call duration (milliseconds)
FieldDescription
total_chatsNumber of unique chat sessions
distinct_modelsNumber of distinct LLM models used
distinct_providersNumber of distinct providers used
FieldDescription
modelsArray of {name, count} objects
toolsArray of {urn, count, success_count, failure_count} objects
Terminal window
curl -X POST "https://app.getgram.ai/rpc/telemetry.getProjectMetricsSummary" \
-H "Content-Type: application/json" \
-H "Gram-Key: <your-api-key>" \
-H "Gram-Project: <your-project-slug>" \
-d '{
"from": "2025-12-01T00:00:00Z",
"to": "2025-12-31T23:59:59Z"
}'

Terminal window
POST https://app.getgram.ai/rpc/telemetry.getUserMetricsSummary

Get aggregated metrics for a specific user within a time range.

FieldTypeRequiredDescription
fromstringYesStart time in ISO 8601 format
tostringYesEnd time in ISO 8601 format
user_idstringNoUser ID (mutually exclusive with external_user_id)
external_user_idstringNoExternal user ID (mutually exclusive with user_id)

Provide either user_id or external_user_id, not both. If neither is provided, returns metrics for all users.

The response structure is identical to the project metrics summary.

Terminal window
curl -X POST "https://app.getgram.ai/rpc/telemetry.getUserMetricsSummary" \
-H "Content-Type: application/json" \
-H "Gram-Key: <your-api-key>" \
-H "Gram-Project: <your-project-slug>" \
-d '{
"from": "2025-12-01T00:00:00Z",
"to": "2025-12-31T23:59:59Z",
"user_id": "user-123"
}'

All search endpoints use cursor-based pagination:

  1. Set limit to control page size (maximum 1000)
  2. Use sort for ordering (desc for newest first, asc for oldest first)
  3. Check next_cursor in the response for more results
  4. Pass the next_cursor value as cursor in the next request

The cursor is an opaque string encoding the position in the result set. Always use the cursor from the previous response rather than constructing one manually.

Terminal window
# First request
curl -X POST "https://app.getgram.ai/rpc/telemetry.searchLogs" \
-H "Content-Type: application/json" \
-H "Gram-Key: <your-api-key>" \
-H "Gram-Project: <your-project-slug>" \
-d '{"limit": 50}'
# Next page (use next_cursor from previous response)
curl -X POST "https://app.getgram.ai/rpc/telemetry.searchLogs" \
-H "Content-Type: application/json" \
-H "Gram-Key: <your-api-key>" \
-H "Gram-Project: <your-project-slug>" \
-d '{"limit": 50, "cursor": "previous-cursor-value"}'

The API returns standard HTTP status codes:

StatusDescription
200Success
400Bad request (invalid parameters)
401Unauthorized (missing or invalid credentials)
403Forbidden (insufficient permissions)
500Internal server error