Pentru dezvoltatori și agenți AI
Integrare prin API
Tot ce face un client din contul EkoPress se poate face și programatic, din propriul CMS, script sau agent AI: alegi publicația din catalog, trimiți articolul, urmărești fiecare pas al verificării, răspunzi la notele redacției, corectezi articolul și aprobi publicarea. Fiecare acțiune sensibilă lasă urme: notă în istoricul articolului și email către titularul contului.
Autentificare
Cheia se generează din Cont → Setări → Chei API și se afișează o singură dată. Se trimite la fiecare cerere, în header:
Authorization: Bearer eko_live_...
Baza: https://ekopress.ro · Toate răspunsurile sunt JSON. Cheile se pot revoca oricând din cont.
Folosirea API-ului se supune acelorași termeni și condiții ca
folosirea platformei — cheia acționează în numele contului tău de client, iar comenzile create prin ea
sunt comenzi în toată regula.
1 · Catalogul de publicații
GET /api/v1/sites
Întoarce publicațiile disponibile: domain, priceLei, category,
lang, dr și, unde există, wpCategories — categoriile WordPress
reale ale site-ului ([{ id, name }]), dintre care poți alege una la comandă.
Domeniul de aici este cel care se trimite la comandă.
2 · Crearea unei comenzi
Pasul A — imaginea reprezentativă (obligatorie la articolele scrise de tine).
Se urcă separat, ca multipart/form-data, fără cheie API:
POST /api/briefs/upload-image
Câmpuri: file (PNG/JPEG/GIF/WebP, max 5 MB) + draftId (orice string unic, ex. un UUID)
Răspuns: { "url": "https://..." } Pasul B — comanda:
POST /api/v1/orders
{
"items": [{
"siteDomain": "exemplu-din-catalog.ro",
"targetUrl": "https://site-ul-tau.ro",
"anchorText": "textul ancorei",
"source": "eu", // "eu" = articolul tău · "redactie" = îl scrie echipa
"articleHtml": "<h1>Titlul</h1><p>...</p>", // obligatoriu la "eu"; trebuie să conțină linkul promovat
"featuredImageUrl": "https://...", // URL-ul de la Pasul A
"featuredImageAlt": "descrierea imaginii",
"confirmImageRights": true, // OBLIGATORIU la orice imagine: declari că deții drepturile de utilizare
"featuredImageCredit": { "name": "Ana Pop", "url": "https://www.pexels.com/@ana" },
// opțional: sursa pozei, afișată sub ea (vezi mai jos)
"authorName": "Nume Prenume", // opțional — semnătura articolului (vezi mai jos)
"authorBio": "Câteva rânduri despre autor",
"authorLinkedinUrl": "https://linkedin.com/in/...",
"isMini": false, // true = articol mini (plafon 350 de cuvinte)
"wpCategoryId": 12 // opțional — categoria WP în care se publică (id din wpCategories,
}], // GET /api/v1/sites); absent SAU id necunoscut pentru site =
// se publică în categoria default a site-ului, fără eroare
"contact": { "name": "...", "email": "...", "phone": "07..." }
}
Răspuns 201: { "orderId": "...", "clientOrderRef": "...", "status": "pending" | "paid" } Ce trebuie să știi despre articleHtml:
- Titlul articolului este textul primului heading din
articleHtml(de regulă<h1>). Nu există un câmp separat de titlu. La publicare, acel heading este scos din text, ca titlul să apară o singură dată în pagină; orice alt<h1>din text devine<h2>. Nu pune linkul promovat sau o imagine în heading-ul de titlu: un heading care le conține rămâne în text, iar titlul apare atunci de două ori. - Introducerea (rezumatul articolului) este primul paragraf
<p>. - Adresa articolului se formează din titlu, de către site-ul pe care se publică. Un titlu scurt dă o adresă scurtă.
- Linkuri: cel mult 2 linkuri în tot articolul, cu tot cu linkul promovat, care este obligatoriu. Linkurile către rețele sociale și Wikipedia nu intră la numărătoare.
- HTML permis:
p, br, strong, b, em, i, u, s, sub, sup, blockquote, a, ul, ol, li, h1-h6, img, figure, figcaption, table, thead, tbody, tr, th, td. Atributele se păstrează doar pea(href,title) și peimg(src,alt,width,height,title). Tot restul se șterge la primire, inclusivid,class,styleși scripturile, deci un cuprins cu salt la secțiuni nu funcționează.
Sursa pozei (opțional): cu featuredImageCredit trimiți numele autorului
sau al băncii de imagini, iar sub poză apare „Foto: Ana Pop". Câmpul url e opțional și
devine link doar pentru Pexels, Unsplash și Pixabay („Foto: Ana Pop / Pexels"); la orice altă sursă
apare doar numele. Fără featuredImageCredit, poza se publică fără legendă.
Comenzile cu plată: când totalul e mai mare ca zero, contact.name,
contact.email și contact.phone sunt obligatorii, iar datele de facturare se
iau din contul tău. Dacă nu ai plasat încă nicio comandă din site, plasează una acolo și completează
datele de facturare; comenzile următoare prin API le moștenesc. Deocamdată asta funcționează pentru
facturarea pe persoană fizică. Pentru factură pe firmă, comenzile cu plată se plasează din site.
Reguli impuse de server: linkul promovat trebuie să existe în text · imagine + text ALT +
confirmImageRights obligatorii · cel mult 2 linkuri per articol · la "redactie"
se trimite editorialBrief.topic în loc de articleHtml. Prețul se calculează
server-side, din catalog — cel din payload se ignoră. O comandă neplătită așteaptă plata în contul web;
când totalul e zero (campanii), intră direct în verificare. Cât ține o campanie cu plafon, un cont
poate lua cel mult un anumit număr de articole gratuite pe zi și pe săptămână; o comandă care nu
încape e refuzată întreagă, cu 429 (vezi codurile de eroare, mai jos).
Semnătura articolului (opțional): dacă authorName e completat, articolul
publicat afișează „De <nume>" sub imaginea principală și o casetă „Despre autor" la final (cu bio
și link LinkedIn, dacă le trimiți). Fără authorName = fără semnătură; bio și LinkedIn se
ignoră singure. Excepție: la articolele de content creator ("isCreator": true), fără
authorName semnează numele contului tău.
Contactul comenzii: dacă nu trimiți contact (sau îi lipsesc numele ori
emailul), golurile se completează din contul tău, ca să apară comanda pe numele tău și să primești
emailurile despre ea. Ce trimiți tu nu se suprascrie. Categoria
(wpCategoryId) se poate alege și la articolele de content creator.
3 · Statusul comenzii — și cum îl urmărești
GET /api/v1/orders/{ref} // ref = orderId sau clientOrderRef
Răspuns: {
"orderId": "...", "clientOrderRef": "...", "status": "paid", "totalLei": 0,
"items": [{
"itemId": "...", // folosit la toate acțiunile pe articol
"siteDomain": "...", "articleTitle": "...",
"status": "asteapta_aprobare_client",
"editTurn": "client", // la cine e „pixul" — vezi mai jos
"publishedUrl": null, // completat după publicare
"notes": [{ "author": "admin", "note": "...", "createdAt": "..." }]
}]
} Modelul recomandat de urmărire este sondarea (polling): interoghează statusul la 1–5 minute cât timp ai comenzi active. Limita este de 120 de interogări / 10 minute — generoasă pentru sondare, dar nu interoga în buclă strânsă. Notificările push (webhook) sunt în plan; până atunci, sondarea este singura sursă de adevăr pentru mașina ta, iar emailurile țin la curent omul.
Statusurile unui articol, în ordinea fluxului:
redactare— comanda nu e încă plătită;de_scris— plătită; articolul urmează să fie scris de echipa editorială;de_verificat— are text; e în verificare la echipa editorială;asteapta_aprobare_client— echipa a trimis varianta finală; se aprobă din contul web sau prin API;de_corectat— ai cerut modificări, le face echipa;corectura_client— ai cerut modificări și le faci tu; până le predai înapoi, articolul poate fi modificat prinPATCH /api/v1/order-items/{itemId};in_coada_publicare— aprobat, urmează publicarea;publicat— live;publishedUrlconține linkul articolului;esuat— publicarea a eșuat; echipa reia manual;respins— respins de echipă; ai dreptul la un text nou pe aceeași publicație.
Schimbare din 24.08.2026: statusul corectura_ai a fost înlocuit de patru stări
distincte (de_scris, de_verificat, de_corectat,
corectura_client), iar aprobat_client a fost retras — aprobarea trece direct în
in_coada_publicare. Motivul: vechiul status însemna patru lucruri diferite, așa că din el nu
se putea afla dacă articolul e la noi sau la tine. Dacă integrarea ta compară statusuri, tratează orice
valoare necunoscută ca „în lucru", nu ca eroare.
Articolul întreg — când vrei să-i arăți omului exact ce aprobă (text, poză, semnătură), nu doar titlul:
GET /api/v1/order-items/{itemId}
Răspuns: articleTitle, articleIntro, articleHtml, featuredImageUrl + Alt,
featuredImageCredit, authorName/Bio/LinkedinUrl, status, editTurn, publishedUrl, notes 4 · „Pixul" (editTurn): cine poate salva
Articolul e un dosar aflat mereu la o singură parte: editTurn: "echipa" înseamnă că e pe
masa echipei (tu doar citești), editTurn: "client" înseamnă că e la tine (poți edita).
Pixul se predă doar prin acțiuni explicite — nu poți edita „printre" corecturile echipei, iar echipa
nu salvează peste modificările tale.
5 · Dialogul cu echipa și corecturile
Când articolul e la aprobare și vrei o schimbare (sau răspunzi unei note a echipei, ex. „schimbă poza"):
POST /api/v1/order-items/{itemId}/request-changes
{ "note": "ce vrei schimbat", "modificEu": true | false } "modificEu": false(implicit) — „schimbați voi": echipa face modificarea; pixul rămâne la ea;"modificEu": true— „modific eu": primești pixul și editezi chiar tu, apoi îl predai înapoi.
Fiecare cerere consumă din cota de corecturi incluse a articolului, indiferent de canal (API sau cont web).
Editarea, cu pixul la tine — update parțial, trimiți doar ce schimbi:
PATCH /api/v1/order-items/{itemId}
{ "featuredImageUrl": "...", "featuredImageAlt": "...", // împreună, plus:
"confirmImageRights": true, // obligatoriu la imagine nouă
"featuredImageCredit": { "name": "...", "url": "..." }, // opțional: sursa pozei NOI; fără el,
// creditul pozei vechi se șterge
"articleTitle": "...", "articleIntro": "...", "articleHtml": "...",
"authorName": "...", "authorBio": "...", "authorLinkedinUrl": "..." } // authorName: null șterge semnătura Predarea înapoi, când ai terminat:
POST /api/v1/order-items/{itemId}/return-to-team
{ "note": "mesaj opțional pentru echipă" }
Exemplu cap-coadă, „schimbă poza": urci poza nouă (Pasul A) → request-changes cu
"modificEu": true → PATCH cu featuredImageUrl +
featuredImageAlt → return-to-team. Echipa verifică și retrimite spre aprobare.
6 · Aprobarea publicării
Când articolul e la asteapta_aprobare_client, îl poți aproba și prin API — echivalentul
butonului „Aprobă" din cont:
POST /api/v1/order-items/{itemId}/approve
{
"scheduledAt": "2026-08-09T10:00:00Z", // opțional — fără el, publicarea pornește imediat
"human_review": { "name": "Prenume Nume" } // numele persoanei care a CITIT articolul în întregime
} Aprobarea prin API e obligatorie contractual, exact ca cea din cont — cheia acționează în numele tău. De aceea lasă două urme automate: o notă în istoricul articolului („aprobat prin API") și un email-chitanță către titularul contului. Dacă primești chitanța fără să recunoști acțiunea, revocă imediat cheia din cont.
human_review — lectura umană la articolele generate cu AI. Regulamentul
european privind inteligența artificială (art. 50) cere ca textul generat de AI publicat fără control
editorial uman să fie marcat ca atare. De aceea, la un articol generat cu AI: dacă trimiți
human_review cu numele persoanei care a citit articolul în întregime, articolul se publică
fără nicio mențiune (lectura umană se înregistrează); dacă NU îl trimiți — aprobarea funcționează în
continuare, dar articolul se publică cu mențiunea vizibilă „Conținut generat cu inteligență
artificială" (răspunsul conține atunci "aiLabel": true). La articolele scrise de om,
câmpul e ignorat.
Asumarea conținutului la crearea comenzii
Textele trimise prin cheia API sunt textele tale, la fel ca cele scrise în cont. Poți declara explicit persoana care le-a citit, la fiecare articol din comandă:
"human_review": { "name": "Prenume Nume" } Câmpul e opțional — comenzile existente funcționează neschimbat. E însă recomandat: declarația se înregistrează permanent, împreună cu amprenta textului trimis, și e proba care te apără dacă cineva contestă ulterior conținutul publicat. Răspunderea pentru conținut îți revine oricum, prin Termeni, indiferent de canalul folosit.
Răspunderi asumate prin folosirea API-ului
- Imaginile: confirmarea drepturilor e explicită și obligatorie —
"confirmImageRights": truela fiecare imagine trimisă (echivalentul bifei din checkout); fără ea, cererea e respinsă; - Acțiunile cheii: tot ce face cheia ta (comenzi, corecturi, aprobare) e considerat făcut de tine; păstrează cheia secretă și revoc-o la orice suspiciune;
- Conținutul: aceleași reguli editoriale și legale ca la comenzile din cont (marcaj „Publicitate", rel=sponsored, fără conținut interzis de termeni).
Erori
401— cheia lipsește, e greșită sau revocată;400— payload invalid; mesajul spune exact ce lipsește;404— comanda/articolul nu există sau nu aparține cheii tale;409— acțiune nepermisă în starea curentă (ex. editare fără pix); mesajul spune ce să faci în loc;429— prea multe cereri; încetinește ritmul. Tot429, cucode: "campaign_limit", când o comandă nu mai încape în plafonul de articole gratuite al campaniei: răspunsul spune câte mai încap acum (remaining), când revine loc (resetAt) și câte poate avea cel mult o comandă (maxPerOrder). Header-ulRetry-Aftervine doar când nu mai încape nimic, iar prețul nu se schimbă niciodată.503, cucode: "campaign_limit_unavailable": plafonul de articole gratuite al campaniei nu s-a putut verifica, iar comanda nu a fost acceptată. Eroarea e trecătoare: retrimite comanda după câteva secunde.
Ce nu se poate prin API — intenționat
- Scrierea cu AI (sursa „eko") — doar în checkout, unde are limitele ei;
- Conținutul sensibil — exclusiv prin fluxul dedicat de pe site.
Notă pentru agenții AI care construiesc integrarea: această pagină este sursa completă și
actuală a API-ului public. Fluxul minim al unei integrări: catalog → upload imagine → comandă → sondare
status la 1–5 min → reacție la note (request-changes / PATCH / return-to-team) → la
asteapta_aprobare_client, citește articolul întreg
(GET /api/v1/order-items/{itemId}), arată-i-l omului tău în conversație
(titlu, intro, imagine, semnătură, notele echipei) și cere-i confirmarea explicită —
abia apoi /approve (chitanța pleacă automat pe email către titular) →
publishedUrl din status e livrarea finală. Nu aproba niciodată fără confirmarea omului.
La întrebarea de aprobare, oferă-i omului TOATE opțiunile momentului, nu doar „da/nu":
(1) publicare acum sau programată — scheduledAt există fix pentru asta; întreabă
„acum sau la o anumită oră?"; (2) semnătura articolului — dacă authorName e gol,
întreabă explicit „îl semnezi cu numele tău?" ÎNAINTE de aprobare (după publicare nu se mai poate din
API); (3) cere modificări / nu încă. Aprobarea e ireversibilă — tot ce se putea decide înainte
de ea trebuie pus pe masă atunci.