Documente
Documente codai Studio — construiești prezentări (PPTX), documente (DOCX) și foi de calcul (XLSX) dintr-un spec JSON, le previzualizezi ca PDF și PNG și transformi prezentările în MP4-uri narate.
Un document este un fișier Office construit dintr-un spec JSON: o prezentare (.pptx), un document (.docx) sau o foaie de calcul (.xlsx). Descrii conținutul, gateway-ul construiește fișierul sincron și îl stochează ca asset Studio (kind: "document"). Fișierele se deschid și rămân editabile în PowerPoint, Word, Excel, LibreOffice, Google Slides/Docs/Sheets și Keynote.
| Metodă | Cale | Rezultat |
|---|---|---|
POST | /v1/studio/documents | 200 — fișierul e construit; întoarce documentul și file.url semnat |
GET | /v1/studio/documents/{id} | Documentul, un file.url proaspăt, spec-ul stocat și latest_preview_id |
POST | /v1/studio/documents/{id}/previews | 202 — pune în coadă o previzualizare (PDF etichetat + PNG-uri pe pagini) |
GET | /v1/studio/previews/{id} | Starea previzualizării, plus PDF-ul și paginile după succeeded |
POST | /v1/studio/documents/{id}/video | 202 — transformă o prezentare într-o randare MP4 |
Modele și prețuri
| Model | Ce face | Preț |
|---|---|---|
codai-docs | Construirea fișierului PPTX / DOCX / XLSX | gratuit (cost_micro_usd: "0") |
codai-docs-preview | Previzualizare LibreOffice: PDF etichetat, câte un PNG pe pagină, foaie de contact | 0,002 $ pe pagină, minimum 0,01 $, taxat o singură dată |
O previzualizare se taxează la primul poll care vede rezultatul; previzualizările eșuate nu costă nimic. Video-urile din prezentări se taxează ca randări (vezi Prezentare → MP4).
Cererea
{
"model": "codai-docs",
"type": "deck",
"theme": "codai-light",
"title": "Rezultate T3",
"language": "ro-RO",
"filename": "rezultate-t3",
"preview": true,
"spec": {
"slides": [
{
"layout": "title",
"title": "Rezultate T3",
"subtitle": "Octombrie 2026",
"notes": "Bun venit."
},
{
"layout": "chart",
"title": "Venituri",
"chart": {
"chart_type": "column",
"alt": "Veniturile cresc de la 1,2 la 1,9 milioane lei",
"categories": ["Iul", "Aug", "Sep"],
"series": [{ "name": "Venituri", "values": [1.2, 1.5, 1.9] }]
}
}
]
}
}| Câmp | Implicit | Semnificație |
|---|---|---|
type | — | deck (PPTX), doc (DOCX) sau sheet (XLSX); obligatoriu. Alege schema lui spec. |
spec | — | Conținutul (obligatoriu); trebuie să corespundă cu type. Vezi Referința spec-ului. |
model | codai-docs | Singurul model de documente. |
theme | codai-light | codai-light, codai-dark sau corporate (vezi mai jos). |
title | primul titlu de slide / secțiune | Până la 200 de caractere; scris în proprietățile fișierului. |
language | ro-RO | Limba de corectură BCP-47 a textului; și limba implicită a narațiunii. |
filename | — | Numele de descărcare, fără extensie (până la 120 de caractere, curățat). |
based_on | — | Unul dintre documentele tale de același type; creează versiunea următoare (vezi Editarea). |
preview | false | Pune în coadă și o previzualizare, taxată ca POST …/previews. |
Răspunsul:
{
"id": "5a7b2c3d-0000-4000-8000-000000000020",
"object": "studio.document",
"type": "deck",
"theme": "codai-light",
"model": "codai-docs",
"title": "Rezultate T3",
"version": 1,
"based_on": null,
"warnings": [],
"cost_micro_usd": "0",
"file": {
"asset_id": "5a7b2c3d-…",
"kind": "document",
"url": "https://storage.googleapis.com/…",
"mime_type": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
"…": "…"
},
"preview": { "id": "6b8c3d4e-…", "object": "studio.preview", "status": "queued" }
}file.url este un URL semnat, valabil o oră; obții oricând unul proaspăt cu GET /v1/studio/documents/{id} sau GET /v1/assets/{id}. warnings enumeră observații nefatale, de exemplu o notă de subsol ignorată într-o prezentare.
Teme
| Temă | Font | Aspect |
|---|---|---|
codai-light | Manrope | culorile brandului codai pe fundal deschis |
codai-dark | Manrope | culorile brandului codai pe fundal închis |
corporate | Aptos (Office îl înlocuiește cu Calibri când Aptos lipsește) | stil de afaceri neutru |
Fonturile nu sunt incluse în fișiere: un calculator fără Manrope afișează un font de rezervă. Diacriticele românești (ș ț ă î â) se păstrează peste tot.
Referința spec-ului
Schemele complete sunt în referința API (DocumentCreateRequest, DeckSpec, DocSpec, SheetSpec). Câmpurile necunoscute sunt respinse.
Tipuri comune
- RichText — un șir (până la 10.000 de caractere) sau o listă de 1–200 de fragmente
{ text, bold?, italic?, underline?, code?, link?, footnote? }.linktrebuie să fie un URLhttps;footnotefuncționează doar în DOCX (ignorat cu un avertisment în prezentări). - Bullet — RichText sau
{ text, level }, cu un nivel de indentare 0–3. - Image —
{ asset_id, alt, caption? }.asset_ideste unul dintre asset-urile tale imagineready(generate sau încărcate);alteste obligatoriu. - Table —
{ columns (1–20), rows (≤ 500, celule string | number | null), header? (true), align?, caption? }. Un rând poate fi mai scurt decâtcolumns, niciodată mai lung. - Chart — vezi Grafice.
Prezentări (type: "deck")
{ aspect? ("16:9" | "4:3", implicit 16:9), footer?, slide_numbers? (true), slides: Slide[1..60] }. Fiecare slide alege un layout și poate avea notes (notele vorbitorului, până la 5.000 de caractere):
layout | Câmpuri |
|---|---|
title | title, subtitle? |
section | title, subtitle? |
bullets | title, bullets (1–12) |
two_column | title, left, right — fiecare coloană { heading?, text?, bullets?, image?, chart? } |
image | title?, image |
chart | title, chart |
table | title, table |
quote | quote, attribution? |
stats | title?, stats (1–4 de { value, label, delta? }) |
timeline | title, items (2–8 de { date, label, detail? }) |
closing | title, subtitle?, contact? |
Documente (type: "doc")
{ page_size? ("A4" | "Letter"), orientation? ("portrait" | "landscape"), header?, footer?, page_numbers? (true), toc? (false), blocks: Block[1..2000] }. toc: true inserează un cuprins construit din titluri.
type de bloc | Câmpuri |
|---|---|
heading | level (1–4), text |
paragraph | text (RichText), align? (left, center, right, justify) |
list | items (1–200 de puncte), ordered? |
table | table |
image | image |
chart | chart |
quote | text, attribution? |
page_break | — |
Foi de calcul (type: "sheet")
{ sheets: Sheet[1..20] }, cel mult 200.000 de celule în total. O foaie:
| Câmp | Implicit | Semnificație |
|---|---|---|
name | — | Unic, 1–31 de caractere, fără []:*?/\. |
columns | — | { header, width?, format? } pentru fiecare coloană. |
rows | — | Liste de celule. |
freeze_header | true | Îngheață rândul de antet. |
autofilter | true | Butoane de filtrare pe antet. |
totals | false | Adaugă un rând SUM pentru coloanele numerice. |
conditional | — | { range: "B2:B20", rule, value?, value2?, style? }; reguli gt, lt, eq, between (cer value, iar between și value2), color_scale, data_bar; stiluri good, bad, neutral. |
charts | — | { chart, anchor?: "H2" }. |
O celulă este un șir, un număr, un boolean, null, { "formula": "SUM(B2:B10)" } (fără = la început) sau { "date": "2026-10-10" } (dată sau dată-oră ISO). Formatele de coloană urmează convențiile ro-RO:
format | Format Excel |
|---|---|
ron | #,##0.00 "lei" |
eur | #,##0.00 "€" |
usd | "$"#,##0.00 |
percent | 0.0% |
date | dd.mm.yyyy |
datetime | dd.mm.yyyy hh:mm |
text, integer, number | după nume |
Grafice
{ chart_type, alt, title?, categories?, series?, stacked?, number_format?, vega_lite? }, cel mult 20 de grafice per document.
chart_typeestebar,column,line,area,pie,doughnut,scattersauvega.- Pentru toate tipurile în afară de
vega,categoriesșiseries(1–12 de{ name, values }) sunt obligatorii, iar fiecare serie are exact câte o valoare pentru fiecare categorie.number_formateste un format numeric Excel, de exemplu#,##0 "lei". vegaprimește un specvega_litedoar cu date în linie — oriceurl(încărcări de date, marcaje de imagine) este respins — de cel mult 500 kB.
Cum sunt desenate:
| PPTX | DOCX | XLSX | |
|---|---|---|---|
bar … scatter | grafic nativ, editabil | PNG Vega-Lite | PNG Vega-Lite + datele ca tabel alături |
vega | PNG Vega-Lite | PNG Vega-Lite | PNG Vega-Lite + datele ca tabel alături |
Un grafic care nu poate fi randat oprește cererea cu 400 chart_render_failed.
Accesibilitate
alteste obligatoriu la fiecare imagine și grafic; devine textul alternativ în fișier și în PDF.- PDF-urile de previzualizare sunt etichetate (tagged), iar ordinea de citire urmează ordinea din spec.
- Setează
languageca cititoarele de ecran și corectorul ortografic să folosească limba potrivită.
Editarea cu based_on
GET /v1/studio/documents/{id} întoarce spec-ul stocat. Îl modifici și îl trimiți înapoi cu based_on setat la id-ul documentului:
{ "type": "deck", "based_on": "5a7b2c3d-0000-4000-8000-000000000020", "spec": { "slides": [ … ] } }Rezultatul este un document nou, cu version = precedenta + 1 și based_on spre cel editat; fișierul vechi rămâne neschimbat. based_on trebuie să fie unul dintre documentele tale de același type, altfel 400 invalid_based_on.
Editare ca o creație
În loc să editezi spec-ul JSON, poți transforma un document într-o creație
editabilă: POST /v1/studio/documents/{id}/creative îl convertește (gratuit și idempotent — apelurile următoare întorc
aceeași creație) și îl leagă de document, care raportează apoi creative_id. O editezi prin operații sau în editorul
Studio, cu previzualizare live, iar POST /v1/studio/creatives/{id}/build generează o versiune nouă a acestui document
(version + 1).
Previzualizări
POST /v1/studio/documents/{id}/previews (sau preview: true la creare) convertește fișierul cu LibreOffice în:
- un PDF etichetat (
pdf, un asset cukind: "preview"); - câte un PNG pe pagină, lat de 1280 px, cel mult 60 de pagini (
pages); - o foaie de contact cu toate paginile într-o singură imagine (
contact_sheet_url).
Interoghează GET /v1/studio/previews/{id} până când status este succeeded sau failed:
{
"id": "6b8c3d4e-0000-4000-8000-000000000021",
"object": "studio.preview",
"document_id": "5a7b2c3d-0000-4000-8000-000000000020",
"model": "codai-docs-preview",
"status": "succeeded",
"error": null,
"page_count": 2,
"cost_micro_usd": "10000",
"pdf": {
"asset_id": "6b8c3d4e-…",
"kind": "preview",
"mime_type": "application/pdf",
"url": "https://storage.googleapis.com/…",
"…": "…"
},
"pages": [
{ "page": 1, "url": "https://storage.googleapis.com/…p001.png…", "width": 1280, "height": 720 }
],
"contact_sheet_url": "https://storage.googleapis.com/…contact.png…"
}Toate URL-urile sunt valabile o oră. Cel mult 3 previzualizări pot fi în coadă sau în lucru per utilizator în același timp (429 too_many_previews). Previzualizarea este ce ar trebui să verifice un agent ca să controleze aranjarea înainte să trimită fișierul mai departe.
Prezentare → MP4
POST /v1/studio/documents/{id}/video transformă o prezentare într-un video: gateway-ul pune în coadă o previzualizare de 1920×1080, apoi o randare (codai-render) care arată câte un slide pe pagină, cu tranziție fade sau fără.
{
"quality": "final",
"seconds_per_slide": 5,
"transition": "fade",
"music_asset_id": "3f2b8c1e-0000-4000-8000-000000000002",
"narrate": { "model": "codai-speech", "voice": "Achernar", "language": "ro-RO" }
}| Câmp | Implicit | Semnificație |
|---|---|---|
quality | final | final sau draft, ca la randări. |
seconds_per_slide | 5 | 2–20 s pe slide când nu există narațiune. |
transition | fade | fade sau none. |
music_asset_id | — | Unul dintre asset-urile tale audio ready, mixat sub slide-uri la −18 dB. |
narrate | — | { model? ("codai-speech" | "codai-speech-expressive"), voice?, language?, instructions? }. |
Cu narrate, sunt citite notes ale fiecărui slide (fără note: titlul, subtitlul și textul punctelor), iar un slide durează max(2 s, narațiunea + 0,6 s). Tot video-ul trebuie să încapă în 180 de secunde (400 video_too_long). Narațiunea nu este disponibilă pentru conturile cu rezidența datelor în UE (403 residency_unavailable).
Răspunsul 202 este o randare (object: "studio.render") plus preview_id, narration_cost_micro_usd, slides și duration_seconds; o interoghezi cu GET /v1/studio/renders/{id}. Prețuri:
- narațiunea — taxată imediat la prețul text-to-speech (
narration_cost_micro_usd, și în antetulx-codai-narration-cost-micro-usd); - previzualizarea —
codai-docs-preview, 0,002 $ pe pagină de slide (minimum 0,01 $); - randarea —
codai-renderpe secundă de ieșire (0,01 $ final / 0,005 $ draft), taxată la poll-ul randării.
Limite
| Limită | Valoare |
|---|---|
| Slide-uri per prezentare | 60 |
| Blocuri per document | 2.000 |
| Foi per foaie de calcul | 20 |
| Celule per foaie de calcul | 200.000 |
| Grafice per document | 20 |
| Mărimea fișierului generat | 50 MB |
| Pagini randate în previzualizare | 60 |
| Previzualizări active per utilizator | 3 |
| Durata video-ului din prezentare | 180 s |
Erori
| HTTP | code | Când |
|---|---|---|
| 400 | invalid_spec | Corpul nu respectă schema; primele probleme sunt în mesaj, lista completă în details. |
| 400 | invalid_based_on | based_on nu e unul dintre documentele tale de același type. |
| 400 | asset_not_found | O imagine (sau asset-ul muzical) e necunoscută, nu e a ta, nu e ready sau nu e imagine (audio, pentru muzică). |
| 400 | unsupported_image | Formatul imaginii nu poate fi inclus în fișier. |
| 400 | too_many_charts | Peste 20 de grafice într-un document. |
| 400 | chart_render_failed | Un grafic nu a putut fi randat. |
| 400 | not_a_deck | S-a cerut video pentru un doc sau sheet. |
| 400 | video_too_long | Video-ul prezentării ar dura peste 180 s. |
| 400 | bad_request | Corp invalid la previzualizare sau la video. |
| 403 | forbidden | Cheia nu are voie să folosească codai-docs, codai-docs-preview, codai-render sau modelul de narațiune. |
| 403 | residency_unavailable | S-a cerut narațiune pe un cont cu rezidența datelor în UE. |
| 402 / 429 | subscription_inactive / rate_limit_exceeded | Abonament inactiv sau plafon de cheltuieli atins. |
| 404 | not_found | Id necunoscut sau documentul ori previzualizarea altui utilizator. |
| 413 | document_too_large | Fișierul generat depășește 50 MB. |
| 429 | too_many_previews | Ai deja 3 previzualizări în coadă sau în lucru. |
| 429 | too_many_renders | Ai deja 3 randări în coadă sau în lucru. |
| 503 | documents_unavailable | Documentele sau previzualizările nu sunt configurate pe acest gateway. |
Exemple
curl
DOC=$(curl -s https://ai.codai.ro/v1/studio/documents \
-H "Authorization: Bearer $CODAI_API_KEY" -H "Content-Type: application/json" \
-d @deck.json)
curl -L -o rezultate-t3.pptx "$(echo "$DOC" | jq -r .file.url)"
PREVIEW=$(echo "$DOC" | jq -r .preview.id)
while :; do
P=$(curl -s "https://ai.codai.ro/v1/studio/previews/$PREVIEW" -H "Authorization: Bearer $CODAI_API_KEY")
S=$(echo "$P" | jq -r .status)
[ "$S" = succeeded ] || [ "$S" = failed ] && break
sleep 3
done
curl -L -o rezultate-t3.pdf "$(echo "$P" | jq -r .pdf.url)"
# Prezentare -> MP4 narat, apoi interoghezi /v1/studio/renders/{id}
curl -s "https://ai.codai.ro/v1/studio/documents/$(echo "$DOC" | jq -r .id)/video" \
-H "Authorization: Bearer $CODAI_API_KEY" -H "Content-Type: application/json" \
-d '{"narrate":{"model":"codai-speech","language":"ro-RO"}}'SDK TypeScript
import { Codai } from 'codai-sdk';
const client = new Codai({ apiKey: process.env.CODAI_API_KEY! });
const doc = await client.documents.create({
type: 'sheet',
theme: 'corporate',
filename: 'facturi-octombrie',
spec: {
sheets: [
{
name: 'Facturi',
columns: [
{ header: 'Client' },
{ header: 'Data', format: 'date' },
{ header: 'Total', format: 'ron' },
],
rows: [
['Alfa SRL', { date: '2026-10-01' }, 1250.5],
['Beta SA', { date: '2026-10-03' }, 980],
],
totals: true,
},
],
},
});
console.log(doc.file.url);
const queued = await client.documents.preview(doc.id);
const preview = await client.documents.retrievePreview(queued.id);
const again = await client.documents.retrieve(doc.id); // include spec-ul stocatPentru prezentări, client.documents.video(id, { narrate: { model: 'codai-speech' } }) întoarce randarea pusă în coadă; o interoghezi cu client.renders.retrieve(render.id).
SDK Python
import os
from codai import Codai
client = Codai(api_key=os.environ["CODAI_API_KEY"])
doc = client.documents.create({
"type": "doc",
"title": "Raport lunar",
"spec": {
"toc": True,
"blocks": [
{"type": "heading", "level": 1, "text": "Raport lunar"},
{"type": "paragraph", "text": [{"text": "Veniturile au crescut cu "}, {"text": "18%", "bold": True}, {"text": "."}]},
{"type": "table", "table": {"columns": ["Lună", "Venituri"], "rows": [["Septembrie", 1.5], ["Octombrie", 1.9]]}},
],
},
})
print(doc["file"]["url"])
queued = client.documents.preview(doc["id"])
preview = client.documents.retrieve_preview(queued["id"])
stored = client.documents.retrieve(doc["id"]) # include spec-ul stocatclient.documents.video(deck_id, {...}) pune în coadă un video din prezentare; îl interoghezi cu client.renders.retrieve(render["id"]).
Randări
Randări codai Studio — transformi o compoziție HyperFrames HTML (cu asset-urile tale Studio) într-un MP4, apoi interoghezi până când e gata.
Creații
Documente creative editabile în codai Studio — creezi un video, o imagine sau o prezentare ca JSON, le editezi prin operații, păstrezi fiecare versiune și le randezi în MP4.