Logs REST API
Send logs over HTTPS from any application, language or tool, one at a time or in batches.
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.
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.
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#
| Option | Type | Required | Description |
|---|---|---|---|
| message | string | Yes | The log line (up to 10,000 characters are kept) |
| level | string | No | fatal, error, warn, info, debug or trace (default: info) |
| sourceId | string | No | Identifier for the log source (for example "api-server"). Default: "<platform>-default", or "unknown-default" |
| sourceName | string | No | Human-readable source name |
| timestamp | string | No | ISO 8601 timestamp (default: the time it was received) |
| metadata | object | No | Additional key-value pairs |
| platform | string | No | Platform tag shown in the Logs view |
| environment | string | No | Environment (default: production) |
| release | string | No | Release version |
| userId | string | No | User the log belongs to |
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#
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.
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
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
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
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:
$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, emptylogsor missingsourceId) - 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
429with aRetry-Afterheader (seconds). Send batches instead of single logs, and wait before retrying. - 500 — Server error — retry later.