Delivery API

Suprafața publică, fără autentificare, care servește conținutul tău publicat. Totul e indexat după cheia publică a site-ului tău (pk_…) și funcționează doar pentru site-uri verificate. GET și HEAD sunt suportate peste tot.

Originea de bază: https://api.dailysmith.com.

Pagini randate

GET /v1/render/{publicKey}/{path}

{path} e calea așa cum apare pe site-ul tău — ex. /blog pentru index, /blog/my-post-slug pentru un articol. baas rezolvă ce blog deține calea după calea lui de bază, deci proxy, SDK și prerender folosesc toate aceeași schemă de URL-uri.

Parametru querySens
format=fragmentFragment JSON pentru SDK, în loc de o pagină HTML completă
page=NPaginare index (10 articole per pagină)

O pagină randată e servită întotdeauna în limba blogului ei — aici nu există parametru locale. Un blog are o singură limbă, așa că singurul lucru pe care l-ar putea produce altă valoare e o pagină goală care declară o limbă în care nu are nimic, și asta nu merită dată unui crawler. Dacă publici într-o a doua limbă, fă un al doilea blog. Listarea structurată de mai jos acceptă locale, pentru că acolo un răspuns gol explicit la „aveți ediție în germană?" chiar folosește.

Paginile complete sunt documente HTML complete, cu titlu, meta descriere, taguri Open Graph și Twitter card (inclusiv og:image, când articolul are o imagine reprezentativă), URL canonical, JSON-LD, un stil implicit lizibil și paleta ta de temă inline.

Fragmentele (format=fragment) returnează:

{
  "html": "<article class=\"baas-post\">…</article>",
  "kind": "post",
  "title": "Titlul articolului",
  "description": "Meta descriere",
  "canonical": "https://example.com/blog/my-post-slug",
  "json_ld": "{…}",
  "locale": "en",
  "og_locale": "en_US",
  "css": "/* paleta de temă a blogului, doar când una e setată */",
  "css_href": "/v1/sdk/md2.css",
  "hero_image_url": "https://api.dailysmith.com/v1/media/01a01789-959f-78f7-a5d0-78fc208903f6",
  "hero_image_alt": "Ilustrație abstractă pentru Titlul articolului",
  "hero_image_width": 1376,
  "hero_image_height": 768
}

locale e limba blogului ca tag simplu — pune-o pe elementul în care inserezi fragmentul, altfel articolul e anunțat de cititorul de ecran în limba pe care o declară pagina ta. og_locale e aceeași limbă în forma limbă_TERITORIU pe care o cere Open Graph; setează-l ca <meta property="og:locale">, altfel cardul de distribuire e presupus en_US. SDK-ul nostru pune întotdeauna lang pe fragmentul pe care îl inserează, iar og:locale îl setează și pe el, dacă nu ai renunțat la gestionarea head-ului.

Cele patru câmpuri hero_image_* sunt omise complet pentru un articol fără imagine reprezentativă, adică fiecare articol scris înainte să le activezi. Imaginea e și deja în interiorul html-ului, ca <img class="baas-hero"> — un singur motor de randare servește fiecare mod de livrare, deci o obții gratis doar prin inserarea fragmentului. Câmpurile separate există ca să poți construi un card social sau o miniatură de listare fără să parsezi marcajul; propriul nostru SDK le citește ca să seteze og:image și le curăță din nou când navighează către un articol care nu are una. Imaginea e servită de la https://api.dailysmith.com/v1/media/{id} — permanentă, imuabilă și publică după id, deci nu are nevoie de nicio cheie și poate fi pusă în cache pentru totdeauna.

css și css_href sunt omise amândouă când nu se aplică, nu trimise goale: css poartă doar paleta de temă a blogului — niciodată foaia de stil a componentelor — deci lipsește când nu există o temă activă; css_href indică spre foaia de stil comună, cacheable, de mai jos, și e prezent doar când conținutul chiar folosește componente MD2. Paginile complete le inline-uiesc pe amândouă, în loc să le lege. Pentru index (kind: "index"), description și json_ld sunt mereu șiruri goale, nu omise.

Listări structurate

GET /v1/delivery/{publicKey}/blogs
GET /v1/delivery/{publicKey}/posts?base_path=/blog&locale=en&page=1

blogs listează blogurile site-ului (nume, cale de bază, locale implicit). posts listează articolele publicate pentru un blog — slug, titlu, rezumat, cale pe site, dată de publicare, minute de citire — paginat (răspunsul poartă și page și total_pages) — utile ca să-ți construiești propriul UI de index sau să alimentezi alte sisteme.

Fluxuri

GET /v1/delivery/{publicKey}/sitemap.xml
GET /v1/delivery/{publicKey}/rss.xml

Sitemap-ul acoperă indexurile de blog și fiecare articol publicat, cu date de ultima modificare; RSS-ul poartă cele mai recente 50 de articole. Referențiază sitemap-ul din robots.txt-ul tău:

Sitemap: https://api.dailysmith.com/v1/delivery/pk_YOUR_KEY/sitemap.xml

Scriptul SDK

GET /v1/sdk/blog.js
GET /v1/sdk/md2.css

JS SDK-ul și foaia de stil pentru conținut bogat MD2 spre care indică css_href-ul unui fragment — ambele servite cu headere de cache pe termen lung.

Erori

Fiecare eroare e problem+json (RFC 9457):

{ "type": "about:blank", "title": "Not found", "status": 404, "detail": "…" }
UndeStatusdetailSens
Orice endpoint404unknown or unverified site keyCheia nu există, sau site-ul nu a trecut de verificare — indistincte intenționat, ca o cheie să nu poată fi folosită ca să sondezi ce site-uri există.
/v1/render/{publicKey}/{path}404no blog is mounted at this pathNiciun blog nu are calea de bază potrivită cu {path}.
/v1/render/{publicKey}/{path}404no such postCalea a rezolvat un blog, dar slug-ul nu.
/v1/delivery/{publicKey}/posts404no blog at that base pathParametrul query base_path nu se potrivește cu niciun blog.
/v1/sdk/md2.css503stylesheet temporarily unavailableSidecar-ul de randare e inaccesibil — reîncearcă.

Nimic pe această suprafață nu returnează vreodată 402 sau 422 — erorile de cotă și de validare se aplică doar API-ului autentificat de conținut.

Semantica de cache

  • Fiecare răspuns poartă un ETag puternic (un hash al conținutului) și respectă If-None-Match cu 304 Not Modified.
  • Cache-Control: public, max-age=60, s-maxage=300, stale-while-revalidate=600 — prietenos cu CDN-urile și cu cache-ul tău de edge; schimbările de conținut (un articol nou, o temă editată) schimbă ETag-ul.
  • CORS e complet deschis (Access-Control-Allow-Origin: *): conținutul e public prin definiție, ceea ce îi permite SDK-ului să-l preia de pe domeniul tău.
enro