AI Agent & Developer Prompt
Status: Public documentation and system prompt. Last updated: 2026-06-21T12:58:39-07:00
The plain-text prompt at
/gpdf-agent-prompt.txtis the compact import target for AI coding assistants that generate JSON RenderDocumentRequestpayloads. This page explains the same rules for humans.
Source of truth
- Machine-readable contract:
/openapi.json. - Human API contract:
/docs/api-reference/. - Plain-text AI prompt:
/gpdf-agent-prompt.txt. - The renderer accepts structured JSON only. It does not parse HTML, CSS, browser DOM, screenshots, or web layout instructions.
- This prompt covers JSON Render only. Template Render and E-Invoice Render have separate API docs and should not be mixed into ordinary JSON Render examples.
- Do not claim that a PDF was rendered, tested, or visually verified unless a real render API call or render tool was used.
No HTML/CSS/Flexbox mental model
Generate gPdf JSON directly from the document goal. Do not first design an HTML, CSS, DOM, Flexbox, Grid, or SVG document and then translate it.
- gPdf is not an HTML/CSS renderer. A
DocumentRequestmust contain only public gPdf JSON fields. - Do not output HTML/CSS/Flexbox structures or style strings.
- Use the current gPdf JSON fields directly: container children live in
elements; visual styles usefill,stroke, andcorner_radius; local child layout useslayout.children; tables userowsandcolumns. - Use gPdf primitives directly:
containerfor grouped visual regions,container.layout.children.mode = "linear"for one-dimensional local layout,tablefor tabular rows and columns, sibling table + container body elements for table-followed-by totals/notes/signatures,pathwithview_boxanddfor native vector outlines, andheader/footer/layersfor repeated page sections. table.rowsandtable.columnsare valid table fields.
Required output shape
AI agents should return a root DocumentRequest JSON object unless the user explicitly asks for HTTP code, curl, SDK code, or a test run.
pagesis required and must be a non-empty array.- Use page
sizeor customwidthplusheight, never both. - Coordinates and lengths use millimeters.
font_sizeuses points. - Layout, positioning, and flow fields live under
layout:layout.left,layout.top,layout.right,layout.bottom,layout.anchor,layout.flow,layout.gap_after,layout.z_index, andlayout.children. Put positioning and flow controls inlayoutfor positioned elements. - Geometry-only subobjects keep their own coordinate names, such as line endpoints, circle centers, polygon points, and
path.view_box; do not copy those geometry names onto positioned text/table/container elements. - The origin is top-left. When
settings.layout.page_marginorpages[].layout.page_marginis set, body coordinates are relative to the content box:layout.left: 0starts at the effective left margin,layout.right: 0starts from the effective right margin, andlayout.top: 0starts at the effective top margin. Negative bodylayout.leftmay enter the left margin but must not pass the physical page edge. - Top-level
headerandfooterelements use the same horizontal margin origin as body content for explicitlayout.left/layout.rightandcontent_left/content_rightanchors. With page margins, their horizontal content width ispage_width - left_margin - right_margin:layout.left: 0aligns to the content-box left edge, andlayout.right: 0places the element’s right edge on the content-box right edge. Useanchor.reference: "page_left"or"page_right"only when you intentionally need physical page-edge alignment. Theirlayout.topvalues are local to the header/footer region. Layers remain physical page coordinates. - For ordinary business documents, prefer
settings.layout.page_marginof15mmon all sides unless the user requests labels, edge-to-edge backgrounds, or a tighter print format. - Common content boxes with
15mmmargins: A4 =180mm x 267mm, Letter =185.9mm x 249.4mm, Legal =185.9mm x 325.6mm. Do not reuse A4 widths such as180mmfor Letter layouts; compute content width aspage_width - left_margin - right_margin. - Keep ordinary visible content away from the physical paper edge. If no page margin is configured, keep top-level body/header/footer text, tables, barcodes, and business graphics at least
5mmfrom each physical page edge.layout.left: 0andlayout.top: 0are acceptable inside a configured content box, inside a padded container content box, or for intentional full-bleed layers/backgrounds/watermarks. - For header/footer divider rules, prefer a thin
rectwithwidth,height,fill, andlayout.left/layout.topinstead of a top-levelline.rectis a positioned element, so it follows the same margin-relative section placement as text. - Plan the full horizontal and vertical content area before placing elements. Do not create extra pages or forced pagination when the content can fit cleanly on one page.
- Default body layout is explicit positioning. Use explicit layout mainly for shipping labels, fixed-size labels, forms, stamps, certificates, or other layouts where every element’s rendered height is known and stable.
- For ordinary business documents such as invoices, quotations, contracts, statements, and reports, prefer global
settings.layout.flow: trueunless the user explicitly needs label-like absolute placement. Dynamic customer names, multilingual text, wrapped addresses, variable table rows, and font fallback can change rendered heights; flow prevents later elements from overlapping earlier content. - With
settings.layout.flow: true, place the first body element at the intended start, keep laterlayout.topvalues in approximate visual order as design spacing hints, and let gPdf advance text, tables, and containers by measured height. Usesettings.layout.gap_afterfor a stable default vertical gap after each flow item; useelement.layout.gap_afterto override that gap for one item. - Flow does not exempt design coordinates from validation. Under global
settings.layout.flow: true, each normal body element still needs a finite in-boxlayout.top; do not use largelayout.topvalues near the page bottom just to express source order. Use JSON order plusgap_afterfor sequencing. Omitlayout.top/layout.bottomonly when that specific element declareslayout.flow: true. - Use element-level
layout.flow: trueonly when a single body element should opt into source-order planning while global flow is off; when you do this, omitlayout.topandlayout.bottomon that element. Setelement.layout.flow: falseonly when global flow is on but that element must remain absolute-positioned. - Flow gap calculation is not simply the difference between neighbouring
layout.topvalues. For a later flow item, gPdf starts after the previous flow group’s measured bottom, then adds the larger of the original design gap, the previous item’slayout.gap_after, and any built-in minimum gap such as a section heading after a table.flowis body-only: it does not affectheader,footer,layers, or watermark content. Planning follows JSON order, notlayout.z_index. - For table-followed-by totals, notes, or signatures, use a body table followed by sibling body containers in
pages[].elements. With flow enabled, the table advances by its measured rendered height,layout.gap_aftercreates the gap after it, and the following container moves after the table. - Do not set
layout.flow: trueon containers whoselayout.children.overflowispaginate. If globalsettings.layout.flowis enabled and a page includes a paginated container, set that container’slayout.flowtofalse. - Keep generated elements inside the page or content box unless the schema explicitly allows overflow.
- Omit
settings.profilefor ordinary PDFs, ordinary invoices, quotations, reports, and labels unless the user explicitly asks for PDF/A, archival compliance, accessibility conformance, or an e-invoice standard. If the user asks for a European/EU e-invoice or Factur-X/ZUGFeRD, use the separate E-Invoice API documentation.
Defaults and omission rules
settings.outputis optional.settings.output.modehas two public values:binaryandfile. Omitsettings.outputor omitsettings.output.modeto use the defaultbinaryresponse. Both modes return the same PDF bytes;binaryreturns inlineContent-Disposition, whilefilereturns attachmentContent-Disposition.- Do not emit
settings.defaults,settings.output, or style fields just to restate defaults. Omitted fields use runtime defaults; use explicit values only when the user asks for a visual choice or when stable brand/layout control matters. - Runtime text defaults are
font_family: "RobotoMono-Regular",font_size: 8,color: "#000000",line_height: 0.9, andtext_align: "left". - Runtime primitive stroke defaults are
line.stroke: "#000000" / 0.4mmandrect.stroke: "#000000" / 1.0mm;rect.corner_radiusdefaults to0. - There is no universal fill color default for every element. Set
fillonly when a visible fill is required. font_familyis optional. If it is omitted, gPdf uses the system default family in auto font mode and may fall back through bundled fonts for text coverage, including common CJK text. For polished invoices, quotations, reports, and other business documents, prefersettings.defaults.text.font_family: "NotoSans-Regular"withfont_mode: "prefer"unless the user asks for another brand font. If no brand or visual polish is required, omitfont_family.- Common built-in font family names you may explicitly declare when needed:
RobotoMono-Regular,RobotoMono-Bold,NotoSans-Regular,NotoSans-Bold,NotoSansSC-Regular,NotoSansSC-Bold,NotoSansJP-Regular,NotoSansJP-Bold,NotoSansKR-Regular,NotoSansKR-Bold,NotoSansArabic-Regular,NotoSansArabic-Bold,NotoSansThai-Regular,NotoSansHebrew-Regular,NotoSansBengali-Regular,NotoSansTamil-Regular,NotoSans_ru-RU,NotoSans_vi-VN,NotoSansOsage-Regular, andMansalva-Regular. When unsure, omitfont_familyand let auto fallback choose. - A declared
font_familywithoutfont_mode: "prefer"is strict. If a declared Latin/default family may need Chinese, Japanese, or Korean fallback, setfont_mode: "prefer"in the same style object.
Text alignment
- Simple string and span text can use
style.text_align, but right, center, and justify alignment need a finite text box such asstyle.width. - Do not write
style.alignin simple text, table-cell text,barcode_text.style, orTextStyle. Usestyle.text_alignthere. The field namealignbelongs only to blockParagraphStyle, such asdefaults.paragraph.alignor paragraph blockstyle.align. - Block text is a
text.contentshape, not an element type; do not output an element whosetypeis"block". Block text usesdefaults.paragraph.alignor per-block paragraph style withframe.width. - Plain string variables use
{page}and{total_pages}. Do not use${page}or${total_pages}; the dollar sign is literal while the variable still resolves separately. Block text uses inline nodes such as{ "type": "variable", "name": "page", "scope": "system" }. - Table-cell text uses table width, column width, padding, offsets, and
text_align; table-cell text style must not include frame-like fields such aswidthorheight.
Two-column business sections
For paired left/right business sections, such as shipper details plus right-flush document metadata, put each pair in one invisible container. The container becomes one flow item, while its child text boxes keep predictable local positions.
- Column placement and text alignment are separate decisions. Use
layout.left: 0for the left column. Uselayout.anchor.reference: "content_right"plusstyle.widthfor the right column. - A right-side text box is not automatically right-aligned. Use
style.text_align: "right"only when the text itself should flush right inside that box, such as metadata numbers. For a right-side address block whose lines should start at the column’s left edge, omittext_alignor set it to"left". - With
settings.layout.page_margin,content_rightmeans the right edge of the content box, not the physical page edge. - Keep items that must share the same visual row inside the same container. Do not make the left item and the right item two independent body flow elements, because flow will place them one after another vertically. This applies to top header pairs, invoice/quotation metadata rows, shipper plus document-number rows, and ship-to plus bill-to rows.
{
"settings": {
"layout": {
"flow": true,
"gap_after": 6,
"page_margin": {
"top": 15,
"right": 15,
"bottom": 15,
"left": 15
}
},
"defaults": {
"text": {
"font_family": "NotoSans-Regular",
"font_mode": "prefer",
"font_size": 9,
"color": "#4B5563"
}
}
},
"pages": [
{
"size": "a4",
"elements": [
{
"type": "container",
"width": 180,
"height": 8,
"layout": {
"left": 0,
"top": 0,
"gap_after": 10
},
"elements": [
{
"type": "text",
"content": "Acme Industrial Solutions LLC",
"style": {
"width": 90,
"font_weight": "bold"
},
"layout": {
"left": 0,
"top": 0
}
},
{
"type": "text",
"content": "DELIVERY NOTE / PACKING SLIP",
"style": {
"width": 90,
"text_align": "right",
"color": "#9CA3AF"
},
"layout": {
"top": 0,
"anchor": {
"reference": "content_right",
"offset": 0
}
}
}
]
},
{
"type": "container",
"width": 180,
"height": 36,
"layout": {
"left": 0,
"top": 45,
"gap_after": 6
},
"elements": [
{
"type": "text",
"content": "FROM (SHIPPER):\nAcme Industrial Solutions LLC\n100 Enterprise Way, Suite 400\nSilicon Valley, CA 94025\nEmail: logistics@acme-solutions.com",
"style": {
"width": 82,
"line_height": 1.35
},
"layout": {
"left": 0,
"top": 0
}
},
{
"type": "text",
"content": "Packing Slip #: PS-2026-0042\nShip Date: 2026-06-20\nPurchase Order #: PO-2026-0775\nCarrier / Method: FedEx Ground",
"style": {
"width": 82,
"text_align": "right",
"line_height": 1.35
},
"layout": {
"top": 0,
"anchor": {
"reference": "content_right",
"offset": 0
}
}
}
]
},
{
"type": "container",
"width": 180,
"height": 32,
"layout": {
"left": 0,
"top": 88,
"gap_after": 6
},
"elements": [
{
"type": "text",
"content": "SHIP TO (DELIVERY ADDRESS):\nGlobal Tech Systems Inc.\nReceiving Dock B (Attn: Warehouse)\n500 Innovation Blvd\nBoston, MA 02210",
"style": {
"width": 82,
"line_height": 1.35
},
"layout": {
"left": 0,
"top": 0
}
},
{
"type": "text",
"content": "SOLD TO (BILL TO):\nGlobal Tech Systems Inc.\nAttn: Accounts Payable\n500 Innovation Blvd, Floor 12\nBoston, MA 02210",
"style": {
"width": 82,
"text_align": "left",
"line_height": 1.35
},
"layout": {
"top": 0,
"anchor": {
"reference": "content_right",
"offset": 0
}
}
}
]
}
]
}
]
}
Barcode text
- QR and other 2D matrix codes should usually use equal
widthandheightand omitbarcode_text; their encoded content is normally too long to print below the code. - 1D linear barcodes may use independent
widthandheight. Addbarcode_textonly when a short human-readable code should appear with the bars. barcode_text.styleand table-cell text styles must not include frame-like layout fields such aswidth,height,vertical_align,text_overflow,shrink_to_fit, ormin_font_size. Use the parent barcode/table size, column width, padding, offsets, andtext_aligninstead.
Path usage
- Use
pathfor native vector geometry. Thedfield is SVG path data only, such asM 0 0 L 100 0 L 100 40 Z; it is not a full SVG element. view_boxdefines the local geometry space ford. Its subfields are geometry-only and must not be used as positioned element fields.- Do not put
<path>,<defs>, CSS, transform, gradient, orurl(#...)intod. Use solidfill/stroke, multiple simple paths, or animageelement with svg/png/webp for complex artwork or gradients.
Table + Container Usage
Use a top-level body table followed by sibling body container elements when a table must be followed by totals, payment notes, signature rows, or approval blocks. This keeps the data table as a real table while letting the follow-up content use ordinary grouped layout.
- Put the
tableand followingcontainerelements directly inpages[].elements. - Do not put
tableinsidecontainer; container descendants cannot be tables. - Prefer
settings.layout.flow: truefor table-followed-by-container layouts. Keeplayout.topas a design coordinate on the table and following containers, and omit element-levellayout.flowunless the element has nolayout.toporlayout.bottom. - Use
table.layout.gap_afterfor the space between the rendered table bottom and the next totals/note/signature container. - Use container-local
layout.rightfor amount values that align to the totals container’s right edge. - Treat subtotal, tax, shipping, paid, and grand total rows as one visual totals group. Keep one left column line for labels and one right column line for amounts. Bold or color can emphasize the final row, but it should not change the row’s left/right offsets.
- Totals styles are composable: use borderless horizontal rules for compact receipt-like totals, an open summary plus a filled final total band for stronger branded invoices, or a border-only card when totals should stay grouped without row fill. Do not make every totals block the same framed card by default.
Invoice table followed by totals container
{
"settings": {
"layout": {
"flow": true,
"gap_after": 6,
"page_margin": {
"top": 15,
"right": 15,
"bottom": 15,
"left": 15
}
}
},
"pages": [
{
"size": "a4",
"elements": [
{
"type": "table",
"width": 180,
"columns": [
{
"key": "description",
"header": "Description",
"width": {
"mode": "fixed",
"value": 110
}
},
{
"key": "qty",
"header": "Qty",
"width": {
"mode": "fixed",
"value": 18
},
"cell": {
"text": {
"text_align": "right"
}
},
"header_cell": {
"text": {
"text_align": "right"
}
}
},
{
"key": "unit_price",
"header": "Unit",
"width": {
"mode": "fixed",
"value": 26
},
"cell": {
"text": {
"text_align": "right"
}
},
"header_cell": {
"text": {
"text_align": "right"
}
}
},
{
"key": "amount",
"header": "Amount",
"width": {
"mode": "fixed",
"value": 26
},
"cell": {
"text": {
"text_align": "right"
}
},
"header_cell": {
"text": {
"text_align": "right"
}
}
}
],
"rows": [
{
"description": "Design system setup",
"qty": 1,
"unit_price": "$850.00",
"amount": "$850.00"
},
{
"description": "PDF automation workflow",
"qty": 1,
"unit_price": "$400.00",
"amount": "$400.00"
}
],
"header": {
"show": true,
"repeat_on_page_break": true
},
"grid": {
"horizontal": {
"color": "#E5E7EB",
"width": 0.2
},
"vertical": false
},
"pagination": {
"row_min_height": 10,
"header_min_height": 12
},
"layout": {
"left": 0,
"top": 20,
"gap_after": 5
}
},
{
"type": "container",
"width": 78,
"height": 27,
"fill": {
"color": "#F9FAFB"
},
"stroke": {
"color": "#D1D5DB",
"width": 0.2
},
"corner_radius": 1.5,
"layout": {
"left": 102,
"top": 0
},
"elements": [
{
"type": "text",
"content": "Subtotal",
"style": {
"width": 40,
"font_size": 8
},
"layout": {
"left": 2,
"top": 3
}
},
{
"type": "text",
"content": "$1,250.00",
"style": {
"width": 32,
"font_size": 8,
"text_align": "right"
},
"layout": {
"right": 2,
"top": 3
}
},
{
"type": "text",
"content": "Tax",
"style": {
"width": 40,
"font_size": 8
},
"layout": {
"left": 2,
"top": 10
}
},
{
"type": "text",
"content": "$100.00",
"style": {
"width": 32,
"font_size": 8,
"text_align": "right"
},
"layout": {
"right": 2,
"top": 10
}
},
{
"type": "line",
"x1": 2,
"y1": 17,
"x2": 76,
"y2": 17,
"stroke": {
"color": "#9CA3AF",
"width": 0.3
}
},
{
"type": "text",
"content": "Total due",
"style": {
"width": 40,
"font_size": 9,
"font_weight": "bold"
},
"layout": {
"left": 2,
"top": 20
}
},
{
"type": "text",
"content": "$1,350.00",
"style": {
"width": 32,
"font_size": 9,
"font_weight": "bold",
"text_align": "right"
},
"layout": {
"right": 2,
"top": 20
}
}
]
}
]
}
]
}
Table column width modes
Column width and text wrapping are separate decisions.
fixed: explicit millimetre width.percent: percentage oftable.width.fit_content: measure header and body content first. Text, images, and barcodes participate in the measurement.auto: content-aware flexible width that absorbs remaining table width after fixed, percent, and fit-content allocation.
Rules:
table.widthis required when any column usespercent,auto, orfit_content.- If you need a column to stay on one line, use text wrapping controls such as
wrap_policy: "no_wrap"in the appropriate text style. Column width modes arefixed,percent,fit_content, andauto. - Do not put frame-like fields such as
width,height,vertical_align,text_overflow,shrink_to_fit, ormin_font_sizeinside table-cell text styles. Use table width, column width, padding, offsets, andtext_align. - Simple row shorthand accepts only scalar cell values:
string,number,boolean, ornull. - Rich block text, images, barcodes, merged cells, per-cell style, and cell links must use a complex cell envelope under the row key. Example:
{ "sku": { "barcode": { "format": "code128", "content": "SKU-001", "width": 32, "height": 10 }, "style": { "text": { "text_align": "center" } } }, "description": { "content": { "blocks": [{ "type": "paragraph", "content": [{ "type": "text", "text": "Bundle" }] }] }, "col_span": 2 } }. A complex cell may set at most one ofcontent,image, orbarcode; omit cells covered byrow_spanorcol_span. - Do not put a bare
{ "blocks": [...] }object directly as a bodyrows[]cell value; wrap it as{ "content": { "blocks": [...] } }. - If a table effectively has
layout.flow: false, setpagination.row_min_height; when its header is visible, also setpagination.header_min_height.
Container usage
Use container when a group should move, edit, inherit descendant defaults, or clip as one unit. It is the correct primitive for cards, address blocks, QR verification panels, status badges, totals blocks, note boxes, signature boxes, bordered groups, clipped panels, and nested groups.
The problem container solves is visual grouping and local layout management. It gives a group one outer box, one local child coordinate space, optional fill/stroke, optional descendant defaults, optional clipping, and optional body-flow pagination. It is not a table, not a document-flow engine, and not an HTML/CSS div.
Continue using other primitives when they are semantically stronger:
- Use
tablefor tabular rows, columns, spans, repeated headers, and table pagination. - Use a sibling
containerafter a bodytablefor totals, notes, and signatures that should follow the rendered table. - Use a standalone
rectfor a simple decorative bar or page background that does not own child elements. - Use
textdirectly for ungrouped labels.
Canonical container fields:
- Required:
type: "container",layout,width,height, andelements. - Placement: use
layout.toporlayout.bottomfor vertical placement, and exactly one oflayout.left,layout.right, orlayout.anchorfor horizontal placement. - Optional geometry:
fill,stroke,corner_radius. - Optional child-box controls:
layout.children.paddingandlayout.children.overflow. - Optional behavior:
layout.children.mode,layout.children.axis,layout.children.gap,layout.children.main_align,layout.children.cross_align,layout.children.wrap,defaults,link,layout.z_index, andcomment. - Child coordinates are relative to the content box after
layout.children.padding. - Valid children are
text,barcode,image,line,rect,circle,ellipse,polygon,path,link, andcontainer. tableis not a valid container child.- A container is a fixed-size outer box. Its
layoutplacement pluswidthandheightdefine the rendered box;layout.children.paddingcreates the child content box. gPdf does not auto-size a container from its children. - In
flowplanning, a non-paginated container moves as one body element and advances following elements by its own outer height. - Estimate fixed container height from the largest child bottom edge plus padding, for example
max(child layout.top + child rendered height) + padding.bottom. Leave2-4mmextra for multiline text and font fallback, but avoid oversized containers inflowbecause they push following content downward and may create an unnecessary continuation page.
Container layout rules:
- Omitted
layout.children.modemeans coordinate mode. - Use
layout.children.mode: "linear"before usingaxis,gap,main_align,cross_align, orwrap. - For
layout.children.mode: "linear", children still use normal gPdf element fields for measurement. In simple linear rows or columns, set childlayout.leftandlayout.topto0and let the container layout place them byaxis,gap,main_align,cross_align, andwrap. - Linear children are measured from their own rendered bounds. A text child without
style.widthis not automatically stretched to the container width; set explicit child widths when wrapping, alignment, orcross_align: "stretch"must be predictable. layout.children.axisishorizontalorvertical.layout.children.main_alignisstart,center,end, orspace_between.layout.children.cross_alignisstart,center,end, orstretch.layout.children.wrapis boolean. Horizontal wrap starts a new row when the next child would exceed the content-box width; vertical wrap starts a new column when the next child would exceed the content-box height.layout.children.overflowisvisible,clip, orpaginate.- Use
paginateonly for body containers that must continue across pages. A paginated container remains a fixed-width outer box; its configured height is the first fragment height, continuation fragments render the remaining children within generated page space, omit the repeated top padding after the first fragment, and draw fill/stroke as page fragments rather than auto-sizing the original container. Descendant text splits only when that text item explicitly usesframe.overflow: "paginate"; otherwise child items move whole to continuation fragments. - Do not set
layout.flow: trueon a paginated container. If globalsettings.layout.flowis enabled, set the paginated container’slayout.flowtofalse. - If the container itself has
link, descendants must not declare element-level links or standalonetype: "link"items.
Container-only linear row snippet:
{
"type": "container",
"width": 92,
"height": 18,
"layout": {
"left": 0,
"top": 0,
"children": {
"padding": { "top": 2, "right": 2, "bottom": 2, "left": 2 },
"mode": "linear",
"axis": "horizontal",
"gap": 3,
"main_align": "start",
"cross_align": "center",
"wrap": true
}
},
"elements": [
{ "type": "text", "content": "PAID", "style": { "width": 18, "font_size": 8 }, "layout": { "left": 0, "top": 0 } },
{ "type": "text", "content": "Bank transfer", "style": { "width": 36, "font_size": 8 }, "layout": { "left": 0, "top": 0 } },
{ "type": "text", "content": "Due today", "style": { "width": 28, "font_size": 8 }, "layout": { "left": 0, "top": 0 } }
]
}
Minimal container example
{
"pages": [
{
"size": "a4",
"elements": [
{
"type": "container",
"width": 84,
"height": 34,
"fill": {
"color": "#F8FAFC",
"opacity": 1
},
"stroke": {
"color": "#CBD5E1",
"width": 0.3
},
"corner_radius": 3,
"elements": [
{
"type": "text",
"style": {
"width": 72,
"font_size": 8,
"color": "#64748B"
},
"content": "Payment status",
"layout": {
"left": 0,
"top": 0
}
},
{
"type": "text",
"style": {
"width": 72,
"font_size": 15,
"font_weight": "bold",
"color": "#0F172A"
},
"content": "Paid",
"layout": {
"left": 0,
"top": 10
}
}
],
"layout": {
"left": 20,
"top": 24,
"children": {
"padding": {
"top": 5,
"right": 6,
"bottom": 5,
"left": 6
}
}
}
}
]
}
]
}
Paginated container example
Use overflow: "paginate" only for containers in pages[].elements or nested inside another body container. Do not use it in headers, footers, or layers. This example intentionally contains enough text to render continuation pages.
{
"pages": [
{
"width": 80,
"height": 28,
"elements": [
{
"type": "container",
"width": 48,
"height": 16,
"fill": {
"color": "#F8FAFC"
},
"stroke": {
"color": "#2563EB",
"width": 0.4
},
"elements": [
{
"type": "text",
"frame": {
"width": 42,
"overflow": "paginate"
},
"defaults": {
"run": {
"font_size": 8
}
},
"content": {
"blocks": [
{
"type": "paragraph",
"inlines": [
{
"type": "text",
"text": "Long container text that must continue across generated pages when the first container fragment fills. Each continuation page keeps the same container width and renders the remaining block text in the next fragment. This sample intentionally includes enough words to demonstrate real pagination instead of a one-page placeholder."
}
]
}
]
},
"layout": {
"left": 0,
"top": 0
}
}
],
"layout": {
"left": 4,
"top": 4,
"children": {
"padding": {
"top": 1,
"right": 1,
"bottom": 1,
"left": 1
},
"overflow": "paginate"
}
}
}
]
}
]
}
Testing boundary
The sandbox endpoint is POST /api/playground?endpoint=pdf-render on the website origin. It does not require an Authorization header and returns application/pdf on success. It is limited to 60 requests per minute per IP address; on sandbox HTTP 429, wait and retry with client-side exponential backoff plus jitter rather than retrying immediately in a tight loop. Production rendering uses POST https://api.gpdf.com/api/v1/pdf/render with a bearer token.
An AI assistant may say a payload is schema-oriented or expected to render only before testing. It may say rendered, verified, or visually checked only after performing the real API/tool call and inspecting the resulting PDF.
AI tool integration guide
The official prompt at https://gpdf.com/gpdf-agent-prompt.txt is the source of truth. Use one of the examples below as a short task prompt: it tells the AI to read the official prompt when URL access is available, follow gPdf syntax, generate a DocumentRequest JSON payload, and produce a PDF only through a real render call or render tool. The official prompt already directs tool-capable assistants to the OpenAPI contract when exact schema lookup is needed.
Ask an AI coding agent or web chat to create a sample bank statement and password-protect the generated PDF.
Please generate a gPdf DocumentRequest JSON payload and a PDF file.
Official gPdf system prompt: https://gpdf.com/gpdf-agent-prompt.txt
Strictly follow that prompt and gPdf syntax.
If the current chat can read URLs, first read the official prompt and use it as the source of truth. It includes schema rules, container usage, the no-auth sandbox endpoint, the sandbox fair-use policy, and render-verification boundaries.
If the URL cannot be read, say so briefly. Do not claim the PDF was rendered or visually checked unless you actually render and inspect it.
Task:
Generate a sample bank statement.
Opening the PDF must require password: 123456.
Use year-month-day-hour-minute-second in the generated file names.
Ask the AI to generate a US-market invoice sample, then return both the JSON payload and rendered PDF artifact.
Please generate a gPdf DocumentRequest JSON payload and a PDF file.
Official gPdf system prompt: https://gpdf.com/gpdf-agent-prompt.txt
Strictly follow that prompt and gPdf syntax.
If the current chat can read URLs, first read the official prompt and use it as the source of truth. It includes schema rules, container usage, the no-auth sandbox endpoint, the sandbox fair-use policy, and render-verification boundaries.
If the URL cannot be read, say so briefly. Do not claim the PDF was rendered or visually checked unless you actually render and inspect it.
Task:
Generate an invoice sample suitable for the US market.
Use a clean business layout, a totals section, and a QR code verification block.
Use year-month-day-hour-minute-second in the generated file names.
Ask the AI to generate a US-market concert ticket and keep barcode contrast high enough for scanning.
Please generate a gPdf DocumentRequest JSON payload and a PDF file.
Official gPdf system prompt: https://gpdf.com/gpdf-agent-prompt.txt
Strictly follow that prompt and gPdf syntax.
If the current chat can read URLs, first read the official prompt and use it as the source of truth. It includes schema rules, container usage, the no-auth sandbox endpoint, the sandbox fair-use policy, and render-verification boundaries.
If the URL cannot be read, say so briefly. Do not claim the PDF was rendered or visually checked unless you actually render and inspect it.
Task:
Generate a concert ticket for the US market.
The barcode color and ticket color must have strong contrast so the barcode is easy to scan.
Use year-month-day-hour-minute-second in the generated file names.