End-to-end examples
A few complete "from key to result" scenarios. All assume the API key in an environment variable:
export GEO_KEY="geo_your_key" # panel → API Keys
1. First request — visibility summary
curl -s -H "X-API-Key: $GEO_KEY" \
"https://geoplatform.pl/v1/visibility/summary?days=30"
You'll get SoV, sentiment and position per platform for the last 30 days — the same numbers you see on the dashboard.
2. Daily SoV trend into a spreadsheet
curl -s -H "X-API-Key: $GEO_KEY" \
"https://geoplatform.pl/v1/visibility/timeseries?days=90" \
| python3 -c "
import csv, json, sys
rows = json.load(sys.stdin)['data']
w = csv.DictWriter(sys.stdout, fieldnames=rows[0].keys()); w.writeheader(); w.writerows(rows)
" > sov_trend.csv
3. The whole product catalog (cursor pagination)
CURSOR=""
while :; do
RESP=$(curl -s -H "X-API-Key: $GEO_KEY" \
"https://geoplatform.pl/v1/products?limit=100&cursor=$CURSOR")
echo "$RESP" | python3 -c "import sys,json; [print(p['name']) for p in json.load(sys.stdin)['data']]"
CURSOR=$(echo "$RESP" | python3 -c "import sys,json; print(json.load(sys.stdin)['meta'].get('next_cursor') or '')")
[ -z "$CURSOR" ] && break
done
The cursor is opaque — pass it back unchanged; the loop ends when next_cursor is empty.
4. Order ingest (attribution)
Requires the orders:write scope. The upsert is idempotent by external_id — send the
same order again (e.g. with status returned) to update it:
curl -s -X POST -H "X-API-Key: $GEO_KEY" -H "Content-Type: application/json" \
https://geoplatform.pl/v1/orders -d '{
"external_id": "ORD-2026-1234",
"ordered_at": "2026-07-22T10:15:00Z",
"status": "paid",
"total_value": 349.99,
"currency": "PLN",
"utm_source": "chatgpt.com",
"items": [
{"product_external_id": "SKU-001", "name": "Trail shoes X", "quantity": 1,
"unit_price": 349.99, "total_price": 349.99}
]
}'
A product_external_id matching your catalog identifiers ties the order to per-SKU revenue.
For historical dumps use POST /v1/orders/batch (up to 500 orders; failed ones land in
errors with their index, the rest go through).
5. A webhook receiver with signature verification
A minimal receiver (FastAPI) that accepts an event and verifies X-GEO-Signature — format
details in Webhooks:
import hashlib, hmac, os
from fastapi import FastAPI, Header, HTTPException, Request
app = FastAPI()
SECRET = os.environ["GEO_WEBHOOK_SECRET"]
@app.post("/geo-webhook")
async def geo_webhook(request: Request, x_geo_signature: str = Header("")):
body = await request.body() # raw bytes — before parsing!
expected = "sha256=" + hmac.new(SECRET.encode(), body, hashlib.sha256).hexdigest()
if not hmac.compare_digest(expected, x_geo_signature):
raise HTTPException(status_code=401)
event = await request.json()
# queue it and respond fast (10 s limit)
print(event["event"], event["data"])
return {"ok": True}
Good practices
- Watch the
X-RateLimit-*headers and back off on429(overview). - For bulk dumps use Data export or BigQuery Sync — the API is for live reads and automation.