# SIExpo licensed Content API v1

API: https://siexpo.bg/api/v1
Documentation: https://siexpo.bg/api/docs
Publisher offer: https://siexpo.bg/api/media
OpenAPI: https://siexpo.bg/api/openapi.json
Contact: support@falcosoft.bg

Public reading stays free. The media API subscription costs EUR 250 per month.
Republication access is arranged with FalcoSoft ITS and activated manually after
payment. A client-specific, expiring Bearer key provides read-only
access to the agreed BG/EN versions. Keep the key on your server, never in URLs,
browser JavaScript or a public repository. Only a hash is stored by SIExpo.

GET /api/v1/articles?after=0&limit=25&lang=both
Authorization: Bearer <YOUR_KEY>

The response contains items, next_after, through and has_more. Use the same through
while following a batch's pages. After has_more=false, save next_after and omit
through on the next poll. The cursor is a change sequence, not an article ID or
timestamp. Upsert by (article id, language), replace corrections and disclosures,
and remove imported versions for deleted=true. A repeated batch is safe to apply.
When a single-language response omits that translation, remove the old imported
version; with lang=both, replace the set of translations returned for each item.
New stories, edits, translations, exclusions and withdrawals are captured together
with publication. The first request backfills the currently available archive.

Use lang=bg, en or both (default); the key's entitlement applies. limit is 1–50,
default 25, and limits scanned change events, so a page may contain fewer items.
Polling every 15–30 minutes is usually enough. An empty successful feed is normal.
Persist the cursor only after the page has been successfully imported. Do not
advance it after an error or before processing removals. A client can request
GET /api/v1/articles/{id}, /api/v1/categories and /api/v1/account as well.

Each article contains full body_markdown and safely rendered body_html per language,
title, excerpt, author, original URL, publication/update timestamps, category,
sources, AI disclosure and its own R2 image. Images are included only when they are
SIExpo-generated editorial illustrations; they are not documentary photographs.
Preserve attribution to SIExpo, the original article link, source links and AI
disclosures. The customer's specific republication rights follow the agreed
licence; this API does not license external source texts, photographs or video.

Use HTTPS. Authenticated requests count toward the daily allowance even when a
parameter is invalid. Daily quotas reset at midnight Europe/Sofia; minute quotas
use calendar minutes. 401: invalid/revoked key; 403: inactive, expired, disallowed IP
or language; 404: unavailable article; 429: exhausted quota (Retry-After seconds);
503: retry later. GET and HEAD only. Responses are no-store. No visitor analytics,
admin data or credentials are returned. IP allowlists are optional; a recorded
website is a licensing identity, not a network restriction on its own.

Client example: https://siexpo.bg/api/client.py
Set SIEXPO_API_KEY privately in the environment. The example downloads the JSON
article feed into a local directory and saves its cursor atomically. Connect its
upsert/removal actions to your CMS; it does not publish to a third-party CMS by
itself. Re-running it updates the same IDs instead of duplicating articles.
