Logs quickstart
By the end of this guide you’ll have ingested a few logs, queried them via the API, and pinned a saved view in the dashboard.
1. Send a log
Section titled “1. Send a log”curl -X POST https://logs.siteqwality.com/v1/ingest \ -H "Authorization: Bearer $SITEQWALITY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "timestamp": "'$(date -u +%Y-%m-%dT%H:%M:%SZ)'", "level": "error", "message": "Failed to charge card", "source": "billing-api", "env": "prod", "host": "api-demo-1", "tags": { "endpoint": "/api/charge" }, "metadata": { "user_id": "usr_abc123", "amount_cents": 9900, "stripe_error": "card_declined" } }'202 Accepted. The log appears in ClickHouse within ~10 seconds.
2. Send a few more
Section titled “2. Send a few more”for i in {1..20}; do LEVEL="info" [ $((i % 5)) -eq 0 ] && LEVEL="error" curl -X POST https://logs.siteqwality.com/v1/ingest \ -H "Authorization: Bearer $SITEQWALITY_API_KEY" \ -H "Content-Type: application/json" \ -d "{ \"timestamp\": \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\", \"level\": \"$LEVEL\", \"message\": \"Order $i processed\", \"source\": \"billing-api\", \"env\": \"prod\", \"tags\": { \"endpoint\": \"/api/orders\" } }" > /dev/null sleep 2doneThat’s 20 logs over 40 seconds, with 4 errors mixed in.
3. Query
Section titled “3. Query”Logs → Explorer. Filter source = billing-api, level = error. The matching logs render in a table with the message and metadata expanded.
START=$(date -u -v-1H +%Y-%m-%dT%H:%M:%SZ)END=$(date -u +%Y-%m-%dT%H:%M:%SZ)
curl -G https://api.siteqwality.com/logs/query \ -H "Authorization: Bearer $SITEQWALITY_API_KEY" \ --data-urlencode "source=billing-api" \ --data-urlencode "level=error" \ --data-urlencode "start_time=$START" \ --data-urlencode "end_time=$END" \ --data-urlencode "limit=50"Returns {logs: [...], total: N}.
4. Save the search
Section titled “4. Save the search”In the dashboard’s Logs Explorer, after applying your filters click Save view, name it Billing errors — prod. It now appears in the Saved views sidebar; share with your team by toggling Shared.
Or via the API:
curl -X POST https://api.siteqwality.com/log_saved_views \ -H "Authorization: Bearer $SITEQWALITY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Billing errors — prod", "description": "All errors from billing-api in prod", "is_shared": true, "filters": { "source": "billing-api", "env": "prod", "level": "error" } }'5. Wire your real app
Section titled “5. Wire your real app”Most logging libraries can ship to a HTTP sink. Two common patterns:
Direct ship from your app (small services):
import logging, requests, json, os
class SqHandler(logging.Handler): def emit(self, record): requests.post( "https://logs.siteqwality.com/v1/ingest", headers={"Authorization": f"Bearer {os.environ['SITEQWALITY_API_KEY']}"}, json={ "timestamp": record.created, "level": record.levelname.lower(), "message": record.getMessage(), "source": "my-app", }, timeout=2, )Ship via your existing log pipeline (Vector, Fluent Bit, Filebeat) — point it at https://logs.siteqwality.com/v1/ingest with the API key in the Authorization header.
For high-volume apps, batch via NDJSON: stick to Content-Type: application/x-ndjson and submit one JSON object per line, up to ~1MB per request.