Abrova
☰ Docs menu · Logs REST API

Logs REST API

Send logs over HTTPS from any application, language or tool, one at a time or in batches.

RESTHTTPSLast updated: 27 Oct 2026

Send logs over HTTPS from any application, language or framework. Every request needs a project credential in the x-api-key header: the server secret (ab_srv_...) when you send from a server, or the app key (ab_live_...) when you send from an app.

Which key?

The app key ships inside mobile and web apps, so treat it as public. On your own servers use the server secret from an environment variable and keep it out of client code. Both keys are accepted on the two log endpoints below, whatever the project's settings. See Server secret & server routes.

Costs from your wallet.

Logs are free up to 1 GB a month; above that they cost 15,000 Toman per GB from your wallet. Logs are kept for 30 days. See Pricing.

Send one log#

POSThttps://trace.abrova.ir/api/logs/ingest
OptionTypeRequiredDescription
messagestringYesThe log line (up to 10,000 characters are kept)
levelstringNofatal, error, warn, info, debug or trace (default: info)
sourceIdstringNoIdentifier for the log source (for example "api-server"). Default: "<platform>-default", or "unknown-default"
sourceNamestringNoHuman-readable source name
timestampstringNoISO 8601 timestamp (default: the time it was received)
metadataobjectNoAdditional key-value pairs
platformstringNoPlatform tag shown in the Logs view
environmentstringNoEnvironment (default: production)
releasestringNoRelease version
userIdstringNoUser the log belongs to
bash
curl -X POST https://trace.abrova.ir/api/logs/ingest \
  -H "x-api-key: $ABROVA_TRACE_SERVER_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "sourceId": "api-server",
    "sourceName": "API Server",
    "level": "info",
    "message": "User login successful",
    "metadata": {
      "userId": "user_123",
      "ip": "192.168.1.1"
    }
  }'

Response (201): {"status": "created", "id": 12345}

Send a batch#

POSThttps://trace.abrova.ir/api/logs/ingest/batch

More efficient for high-volume logging: send many entries in one request as a JSON array under logs. sourceId is required here; each entry in logs takes the same fields as a single log (except sourceId / sourceName). Up to 1,000 entries are stored from one request; send more as several batches.

bash
curl -X POST https://trace.abrova.ir/api/logs/ingest/batch \
  -H "x-api-key: $ABROVA_TRACE_SERVER_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "sourceId": "api-server",
    "logs": [
      { "level": "info", "message": "Request received: GET /api/users" },
      { "level": "debug", "message": "Querying database..." },
      { "level": "info", "message": "Response sent: 200 OK (45ms)" }
    ]
  }'

Response (201): {"status": "created", "count": 3, "projectId": "..."}

Code examples#

Node.js

javascript
const ABROVA_TRACE_SERVER_SECRET = process.env.ABROVA_TRACE_SERVER_SECRET; // ab_srv_...
const ABROVA_TRACE_URL = 'https://trace.abrova.ir';

async function sendLog(sourceId, level, message, metadata = {}) {
await fetch(`${ABROVA_TRACE_URL}/api/logs/ingest`, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'x-api-key': ABROVA_TRACE_SERVER_SECRET,
  },
  body: JSON.stringify({ sourceId, level, message, metadata }),
});
}

// Usage
sendLog('api-server', 'info', 'Server started on port 3000');
sendLog('api-server', 'error', 'Database connection failed', {
error: 'ECONNREFUSED',
});

For Node.js apps, the Node.js SDK batches and retries for you.

Python

python
import os
import requests

ABROVA_TRACE_SERVER_SECRET = os.environ.get('ABROVA_TRACE_SERVER_SECRET')  # ab_srv_...
ABROVA_TRACE_URL = 'https://trace.abrova.ir'

def send_log(source_id, level, message, metadata=None):
    requests.post(
        f'{ABROVA_TRACE_URL}/api/logs/ingest',
        json={
            'sourceId': source_id,
            'level': level,
            'message': message,
            'metadata': metadata or {},
        },
        headers={'x-api-key': ABROVA_TRACE_SERVER_SECRET},
        timeout=5,
    )

# Usage
send_log('worker', 'info', 'Job started')
send_log('worker', 'error', 'Job failed', {'job_id': '123'})

Go

go
package main

import (
    "bytes"
    "encoding/json"
    "net/http"
    "os"
)

func sendLog(sourceId, level, message string, metadata map[string]interface{}) error {
    body, _ := json.Marshal(map[string]interface{}{
        "sourceId": sourceId,
        "level":    level,
        "message":  message,
        "metadata": metadata,
    })

    req, _ := http.NewRequest("POST",
        "https://trace.abrova.ir/api/logs/ingest",
        bytes.NewBuffer(body))
    req.Header.Set("Content-Type", "application/json")
    req.Header.Set("x-api-key", os.Getenv("ABROVA_TRACE_SERVER_SECRET"))

    _, err := http.DefaultClient.Do(req)
    return err
}

PHP

For Laravel apps, use the Laravel SDK log channel. For plain PHP:

php
$ch = curl_init('https://trace.abrova.ir/api/logs/ingest');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Content-Type: application/json',
        'x-api-key: ' . getenv('ABROVA_TRACE_SERVER_SECRET'),
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'sourceId' => 'shop-backend',
        'level' => 'error',
        'message' => 'payment callback timeout order=ORD-8812',
    ]),
]);
curl_exec($ch);
curl_close($ch);

Response codes#

  • 201 — Created
  • 400 — Invalid request body (missing message; for a batch, empty logs or missing sourceId)
  • 401 — Missing or invalid key, or Abrova Trace is not enabled for the project
  • 429 — Too many requests. There are generous limits per key and per client address; a client that exceeds them gets 429 with a Retry-After header (seconds). Send batches instead of single logs, and wait before retrying.
  • 500 — Server error — retry later.
Was this page helpful?
Report a problem