Skip to Content

API reference

Authentication

All requests require authentication headers:

HeaderDescription
Gram-KeyAPI key with Consumer or Producer scope
Gram-ProjectProject identifier (slug)
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}'

Search logs

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

Search and list telemetry logs that match a search filter.

Request body

FieldTypeDescription
limitnumberNumber of items to return (1-1000, default: 50)
sortstringSort order: asc or desc (default: desc)
cursorstringCursor for pagination
filterobjectFilter criteria (see below)

Filter parameters

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

Response

{ "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 }

Log record fields

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

Example: Filter by user

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

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" } }'

Search tool calls

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.

Request body

FieldTypeDescription
limitnumberNumber of items to return (1-1000, default: 50)
sortstringSort order: asc or desc (default: desc)
cursorstringCursor for pagination
filterobjectFilter criteria (see below)

Filter parameters

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

Response

{ "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 }

Tool call summary fields

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

Get project metrics summary

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

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

Request body

FieldTypeRequiredDescription
fromstringYesStart time in ISO 8601 format
tostringYesEnd time in ISO 8601 format

Response

{ "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 }

Metrics fields

Timestamps

FieldDescription
first_seen_unix_nanoEarliest activity timestamp (Unix nanoseconds, as string)
last_seen_unix_nanoLatest activity timestamp (Unix nanoseconds, as string)

Token usage

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

Chat requests

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

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)

Cardinality

FieldDescription
total_chatsNumber of unique chat sessions
distinct_modelsNumber of distinct LLM models used
distinct_providersNumber of distinct providers used

Breakdowns

FieldDescription
modelsArray of {name, count} objects
toolsArray of {urn, count, success_count, failure_count} objects

Example

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" }'

Get user metrics summary

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

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

Request body

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)

Response

The response structure is identical to the project metrics summary.

Example

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" }'

Pagination

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

Example: Paginated query

# 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"}'

Error handling

The API returns standard HTTP status codes:

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

Last updated on