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.