Skip to content

gPdf API 接口规范

版本: Unified API / Current Engine 更新: 2026-03-24

说明: 本文描述当前正式公开 schema。唯一 canonical 路由为 POST /api/v1/renderprod/test 仅通过环境与 token 区分。


1. 接口概览

路由鉴权方式用途
POST /api/v1/renderAuthorization: Bearer <token>唯一公开请求入口
  • Content-Type: application/json
  • 成功响应: application/pdf (二进制流)
  • 默认输出模式: binary
  • binaryfile 都返回 PDF 二进制;差异只在 Content-Disposition

2. 请求结构

json
{
  "settings": {
    "defaults": {
      "text": {
        "font_family": "NotoSans-Regular",
        "font_size": 11,
        "color": "#111111"
      },
      "stroke": {
        "color": "#000000",
        "width": 0.4
      },
      "fill": {
        "color": "#FFFFFF",
        "opacity": 1.0
      },
      "shape": {
        "corner_radius": 0
      }
    },
    "metadata": {
      "title": "gPdf Document",
      "author": "gPdf"
    },
    "output": {
      "mode": "file",
      "file_name": "invoice-20260310.pdf"
    },
    "profile": "pdfa-2b"
  },
  "layers": {
    "background": {
      "elements": []
    },
    "watermark": {
      "elements": []
    }
  },
  "header": {
    "height": 12,
    "elements": []
  },
  "footer": {
    "height": 10,
    "elements": []
  },
  "pages": [
    {
      "size": "label_100_150",
      "elements": []
    }
  ]
}

3. 顶层对象

3.1 DocumentRequest

字段类型必填说明
settingsSettings全局设置
layersLayers全局页面装饰层
pagesPage[]页面数组
headerSection全局页眉
footerSection全局页脚

3.1.1 Page 尺寸

每个页面必须显式指定尺寸,支持两种写法,二选一:

  • size
  • width + height

规则:

  • sizewidth/height 不能同时出现
  • 不写 size 时,必须同时提供 widthheight
  • size 不区分大小写

3.1.2 Layers(页面装饰层)

layers 用于定义文档级重复装饰层,不参与正文分页,也不占用 header/footer 的布局高度。

第一版支持:

  • background
  • watermark
  • stamp

结构:

  • background
    • 使用普通 elements[]
  • watermark
    • 使用算法化 spec:template + style + layout + opacity
  • stamp
    • 使用普通 elements[]

background / stamp 结构:

json
{
  "repeat": "all_pages",
  "elements": []
}

watermark 结构:

json
{
  "repeat": "all_pages",
  "opacity": 0.12,
  "template": {
    "type": "text",
    "content": "PRIVATE COPY"
  },
  "style": {
    "font_family": "NotoSans-Regular",
    "font_size": 10.5,
    "font_weight": "bold",
    "color": "#B91C1C",
    "width": 56,
    "text_align": "center"
  },
  "layout": {
    "preset": "diagonal_tile",
    "angle": 330,
    "gap_x": 18,
    "gap_y": 16,
    "offset_x": 8,
    "offset_y": 10,
    "stagger_x": 34
  }
}

规则:

  • repeat 可选,默认 all_pages
  • 支持值:
    • all_pages
    • first_page
    • last_page
  • background 在正文前渲染
  • watermark / stamp 在正文后渲染
  • stamp 是最上层,适合最后一页的盖章、审批标记、状态角标
  • background.elements / stamp.elements 仅允许轻量元素:
    • text
    • image
    • rect
    • line
    • circle
    • ellipse
    • polygon
    • link
  • background / stamp 不允许:
    • table
    • stack
  • 第一版 watermark.template.type 仅支持:
    • text
  • watermark.layout.preset 支持:
    • center
    • tile
    • diagonal_tile
  • watermark.opacity0..1
  • watermark.layout.angle 使用度数,支持任意角度

常见用法:

  • background
    • 适合整页底色、底纹、背景图
    • 常见写法是在 background.elements 里放一个整页 rectimage
  • watermark
    • 适合大量重复的提示文字、品牌浅色文字、斜向平铺文案
    • 只需要定义一个模板,系统会按 layout 自动铺满页面
  • stamp
    • 适合最后一页盖章、审批通过标记、对账完成标记
    • 常见写法是 repeat: "last_page",再组合 circle + line + text

当前边界:

  • layers 不参与正文分页,也不会占用 header/footer 高度
  • 其他元素的旋转能力仍以各自字段说明为准
  • watermark.layout.angle 是专门给水印平铺使用的
  • 如果需要半透明图片盖章,优先使用带 alpha 的 PNG/SVG 资源

示例:背景 + 算法平铺水印 + 最后一页盖章

json
{
  "layers": {
    "background": {
      "elements": [
        {
          "type": "rect",
          "x": 0,
          "y": 0,
          "width": 215.9,
          "height": 279.4,
          "fill": { "color": "#FFFBEB" }
        }
      ]
    },
    "watermark": {
      "repeat": "all_pages",
      "opacity": 0.12,
      "template": {
        "type": "text",
        "content": "PRIVATE COPY"
      },
      "style": {
        "font_family": "NotoSans-Regular",
        "font_size": 10.5,
        "font_weight": "bold",
        "color": "#B91C1C",
        "width": 56,
        "text_align": "center"
      },
      "layout": {
        "preset": "diagonal_tile",
        "angle": 330,
        "gap_x": 18,
        "gap_y": 16,
        "offset_x": 8,
        "offset_y": 10,
        "stagger_x": 34
      }
    },
    "stamp": {
      "repeat": "last_page",
      "elements": [
        {
          "type": "circle",
          "cx": 171,
          "cy": 228,
          "r": 18,
          "stroke": { "color": "#B91C1C", "width": 0.9 }
        },
        {
          "type": "text",
          "x": 152,
          "y": 220,
          "content": "PAID",
          "style": {
            "font_size": 12,
            "font_weight": "bold",
            "color": "#B91C1C",
            "width": 38,
            "text_align": "center"
          }
        }
      ]
    }
  }
}

支持的 size 预设:

  • a4 = 210 x 297 mm
  • a6 = 105 x 148 mm
  • letter = 215.9 x 279.4 mm
  • legal = 215.9 x 355.6 mm
  • label_100_100 = 100 x 100 mm
  • label_100_150 = 100 x 150 mm
  • label_4_6_in = 101.6 x 152.4 mm

示例:

json
{
  "pages": [
    { "size": "A4", "elements": [] },
    { "width": 100, "height": 150, "elements": [] }
  ]
}

3.1.2 Page Margin / Content Box

可选配置:

  • settings.page_margin
  • pages[].margin

示例:

json
{
  "settings": {
    "page_margin": { "top": 10, "right": 12, "bottom": 10, "left": 12 }
  },
  "pages": [
    {
      "size": "letter",
      "margin": { "top": 8, "right": 10, "bottom": 12, "left": 10 },
      "elements": []
    }
  ]
}

规则:

  • 未配置 page_margin 时,正文元素维持当前页面绝对坐标语义。
  • 一旦配置 page_marginpages[].elementsx/y 改为相对 content box 左上角。
  • pages[].elements 超出 content box 会直接校验报错,不做自动裁剪或纠偏。
  • header/footer 仍按页面坐标工作,不受 page_margin 约束。
  • 正文自动分页到后续页时,会从下一页 content box 顶部继续排版。

headerfooter 共用同一个结构:

json
{
  "height": 12,
  "elements": [
    { "type": "text", "x": 5, "y": 8, "content": "Page Header" }
  ]
}
字段类型必填说明
heightnumber区域高度,单位 mm
elementsElement[]该区域内渲染的元素列表

语义说明:

  • header全局页眉,会应用到每一页。
  • footer全局页脚,会应用到每一页。
  • elements 为空时,该区域本身仍然存在;不要依赖"空数组自动忽略区域"。

坐标与定位:

  • header.elements页面绝对坐标渲染,通常约定写在 y = 0 .. header.height 区间内。
  • footer.elements 会自动整体下移到页面底部,偏移量为 page.height - footer.height。 也就是说,footer 内部元素通常写成相对页脚区域的坐标,例如 y = 0 .. footer.height

与正文的关系:

  • header 不会自动把正文元素整体下移。正文元素仍按页面绝对坐标渲染。
  • 因此如果你使用页眉,建议正文元素自己避开页眉区域,例如从 y >= header.height 开始排布。
  • footer.height 会参与正文可用高度计算,正文分页/溢出时会避开页脚底部区域。
  • 配置 page_margin 后,正文自动分页到后续页会从下一页 content box 顶部开始。

实践建议:

  • header.height / footer.height 应与内部元素实际占用高度大体一致,不要随意写过大。
  • 如果只是普通固定区域装饰,推荐把页眉内容放在 header,页脚内容放在 footer,不要手工复制到每页。
  • 如果需要每页不同的顶部/底部内容,仍应放在 pages[].elements 中单独控制,而不是使用全局 header/footer

3.3 Settings

字段类型必填说明
defaultsDefaults全局默认样式
metadataMetadataPDF 元数据
outputOutputSettings响应输出模式与文件名
profilestringPDF/A 配置
page_marginPageMargin正文内容区页边距

profile 支持: pdfa-1b, pdfa-2b, pdfa-3b, pdfa-4, pdfa-2u, pdfa-3u, pdfa-ua1 等。

3.3.1 OutputSettings

字段类型必填说明
modebinary | file响应呈现方式,默认 binary
file_namestring自定义文件名,binaryfile 都可用

规则:

  • binary 或不传:返回 PDF 二进制,并附带 Content-Disposition: inline; filename=\"...\"
  • file:仍然返回 PDF 二进制,但使用 Content-Disposition: attachment; filename=\"...\",用于下载。
  • file_name 不传:回退到默认文件名 gPdf-MMDDHHmmssSSS.pdf
  • file_name 会经过安全清洗,并自动补 .pdf 后缀。

3.4 Defaults

字段类型说明
textTextStyle文本默认样式
strokeStrokeStyle线条/描边默认样式
fillFillStyle填充默认样式
shapeShapeDefaults形状默认样式

ShapeDefaults:

字段类型说明
corner_radiusnumber矩形默认圆角半径(mm)

说明:

  • settings.defaults 只接受结构化写法:text / stroke / fill / shape
  • settings.defaults.text 也属于字体作用域;如果这里显式设置 font_family 且未写 font_mode,默认按 strict 处理

3.5 Metadata

字段类型说明
titlestring标题
authorstring作者
subjectstring主题
creatorstring创建工具
producerstring生成器
languagestring语言代码

4. 元素类型

elements[] 中每项都必须带 type:

  • text
  • barcode
  • line
  • rect
  • circle
  • ellipse
  • polygon
  • link
  • image
  • table
  • stack

通用字段:

  • 大多数元素支持 z_index (默认 0)
  • 大多数元素支持 comment (仅备注,不渲染)
  • 支持旋转的元素:
    • text 支持任意整数角度
    • image 支持任意角度
    • barcode 及其附带文本当前只支持 0/90/180/270
    • rectellipse 当前建议仍使用 0/90/180/270
  • 超链接支持两种模式:
    • 元素挂载 link 字段(text/barcode/line/rect/circle/ellipse/polygon/image
    • 独立热点元素 type: "link"

4.1 x_anchor(横向锚定定位)

x_anchor 用于按参考边界自动计算元素的最终 x

当前支持的元素:

  • text
  • barcode
  • rect
  • image
  • link

不支持:

  • line / circle / ellipse / polygon / table / stack / block

规则:

  • xx_anchor 互斥,同时传入会直接报错
  • 不使用 x_anchor 时,仍按原有 x 绝对定位
  • text 使用 x_anchor 时必须提供宽度:
    • 纯文本 / spans 简写使用 style.width
    • block text 使用 frame.width
  • barcode / rect / image / link 使用 x_anchor 时,使用元素自身 width
  • table_left / table_right 只允许在 stack -> block 内使用

参考值:

  • page_left
  • page_right
  • content_left
  • content_right
  • table_left
  • table_right

计算规则:

  • 左侧参考:resolved_x = reference + offset
  • 右侧参考:resolved_x = reference - offset - width

示例:

json
{
  "type": "text",
  "x_anchor": { "reference": "content_right", "offset": 8 },
  "y": 12,
  "content": "$1,235.85",
  "style": {
    "width": 24,
    "text_align": "right"
  }
}

5. 样式对象

5.1 StrokeStyle

json
{
  "color": "#111111",
  "width": 0.5,
  "opacity": 1.0,
  "cap": "butt",
  "join": "miter",
  "miter_limit": 10,
  "dash": {
    "preset": "dashed",
    "pattern": [3, 2],
    "phase": 0
  },
  "compound": {
    "kind": "double",
    "gap": 0.3
  }
}

字段说明:

  • cap: butt / round / square
  • join: miter / round / bevel
  • dash.preset: solid / dashed / dotted / custom
  • dash.pattern 仅在 preset=custom 时建议提供
  • compound.kind: 当前仅支持 double
  • compound.gap: 双线两根线之间的净距(mm)

说明:

  • 未设置 compound 时按单线处理。
  • compoundlinetable.gridtable.cell.borders 统一复用。
  • double + dash 为非法组合。
  • double + marker 为非法组合。
  • rect/circle/ellipse/polygon 若传入 compound 会报不支持。

5.2 FillStyle

json
{
  "color": "#F5F5F5",
  "opacity": 1.0,
  "rule": "nonzero"
}

rule: nonzero / even_odd

5.3 MarkerStyle (Line)

json
{
  "start": "none",
  "end": "arrow",
  "size": 2.5
}

start/end: none / arrow / open_arrow / circle / bar

5.4 LinkSpec (超链接)

json
{
  "target": { "type": "url", "url": "https://example.com" },
  "alt": "open official site",
  "padding": 1.0,
  "border": { "color": "#1A202C", "width": 0.3 }
}

LinkTarget:

  • URL: { "type": "url", "url": "https://..." }
  • 页内跳转: { "type": "page", "page": 2, "x": 10, "y": 20 }

LinkBorderStyle:

  • color: hex 颜色
  • width: 线宽(mm),0 视为不绘制

约束:

  • URL 仅支持 http://https://mailto:tel:
  • URL 前后空白会被裁剪(trim)后再写入
  • page1 开始,且不能超过请求中显式 pages
  • padding 必须为有限数且 >= 0
  • border.width 必须为有限数且 >= 0
  • border.color(若提供)必须是合法 hex 颜色
  • 任一 link 字段不合法会直接返回 ValidationError(不会静默跳过)

6. Shape 元素

line/rect/circle/ellipse/polygon 均可选挂载 link: LinkSpec

6.1 Line

json
{
  "type": "line",
  "x1": 4,
  "y1": 99,
  "x2": 96,
  "y2": 99,
  "stroke": {
    "color": "#000000",
    "width": 0.4,
    "dash": { "preset": "solid" }
  },
  "link": {
    "target": { "type": "url", "url": "https://example.com/spec" }
  }
}

stroke 省略时会走默认链路(见第 9 节)。

6.2 Rect

json
{
  "type": "rect",
  "x_anchor": { "reference": "content_right", "offset": 6 },
  "y": 20,
  "width": 60,
  "height": 20,
  "fill": { "color": "#FFFFFF" },
  "stroke": { "color": "#222222", "width": 0.6 },
  "corner_radius": 2
}

6.3 Circle

json
{
  "type": "circle",
  "cx": 40,
  "cy": 40,
  "r": 12,
  "fill": { "color": "#E6F4FF" },
  "stroke": { "color": "#2B6CB0", "width": 0.5 }
}

6.4 Ellipse

json
{
  "type": "ellipse",
  "cx": 70,
  "cy": 40,
  "rx": 16,
  "ry": 10,
  "rotation": 0,
  "fill": { "color": "#FFF7E6" },
  "stroke": { "color": "#C05621", "width": 0.5 }
}

6.5 Polygon

json
{
  "type": "polygon",
  "points": [
    { "x": 20, "y": 80 },
    { "x": 35, "y": 60 },
    { "x": 50, "y": 80 },
    { "x": 40, "y": 95 }
  ],
  "fill": { "color": "#F0FFF4" },
  "stroke": { "color": "#2F855A", "width": 0.5 }
}
json
{
  "type": "link",
  "x_anchor": { "reference": "content_left", "offset": 10 },
  "y": 10,
  "width": 40,
  "height": 8,
  "target": { "type": "url", "url": "https://example.com" },
  "alt": "Open website"
}

7. 其他元素

7.1 Text

公开 text 元素支持 3 种输入形式:

  • 纯文本简写:"content": "Hello gPdf"
  • spans 富文本简写:"content": { "spans": [...] }
  • block text:"content": { "blocks": [...] }

这 3 种写法在校验与渲染阶段会得到一致处理。
其中 block text 的表达能力最完整,适合复杂排版、变量、列表和分页控制。

必填字段:

  • y
  • content
  • 且必须二选一提供:
    • x
    • x_anchor

纯文本简写:

json
{
  "type": "text",
  "x": 18,
  "y": 18,
  "content": "Hello gPdf"
}

spans 富文本简写:

json
{
  "type": "text",
  "x": 18,
  "y": 30,
  "content": {
    "spans": [
      { "text": "Hello ", "style": { "font_weight": "bold" } },
      { "text": "gPdf", "style": { "color": "#2563EB" } }
    ]
  },
  "style": {
    "font_family": "NotoSans-Regular",
    "font_size": 11,
    "width": 80
  }
}

block text:

json
{
  "type": "text",
  "x": 18,
  "y": 42,
  "rotation": 0,
  "frame": {
    "width": 120,
    "overflow": "paginate"
  },
  "defaults": {
    "run": {
      "font_family": "NotoSans-Regular",
      "font_size": 11,
      "color": "#111111"
    },
    "paragraph": {
      "align": "left",
      "direction": "auto",
      "line_height": 1.35
    }
  },
  "content": {
    "blocks": [
      {
        "type": "paragraph",
        "inlines": [
          { "type": "text", "text": "Page " },
          { "type": "variable", "name": "page", "scope": "system" }
        ]
      },
      { "type": "page_break" },
      {
        "type": "paragraph",
        "inlines": [
          { "type": "text", "text": "Page " },
          { "type": "variable", "name": "page", "scope": "system" },
          { "type": "text", "text": " / " },
          { "type": "variable", "name": "total_pages", "scope": "system" }
        ]
      }
    ]
  }
}

顶层字段:

字段类型必填说明
type"text"元素类型
ynumber页面坐标,单位 mm
xnumber二选一页面坐标,单位 mm
x_anchorHorizontalAnchor二选一锚定定位
rotationinteger元素级旋转,单位为角度
z_indexnumber层级
commentstring备注
_ifstring模板链路元字段;POST /api/v1/render 不会执行 _if 条件过滤
linkLinkSpec整个文本元素级链接
styleTextStyle纯文本 / spans 简写的样式
frameBlockTextFrameblock text 文本框样式
defaultsBlockTextDefaultsblock text 默认样式
contentstring | { spans: TextSpan[] } | BlockTextContent文本内容,支持 3 种输入形式

顶层规则:

  • xx_anchor 互斥
  • 使用 x_anchor 时必须提供宽度:
    • 纯文本 / spans 简写使用 style.width
    • block text 使用 frame.width
  • text.link 与任意 inline link 互斥
  • rotation 使用整数角度值,例如 037-15

7.1.1 BlockTextDefaults

json
{
  "run": {},
  "paragraph": {},
  "frame": {}
}
  • run: 行内默认样式
  • paragraph: 段落默认样式
  • frame: 文本框默认样式

7.1.2 BlockTextContent

json
{
  "blocks": [
      {
        "type": "paragraph",
        "inlines": [
          { "type": "text", "text": "Page " },
          { "type": "variable", "name": "page", "scope": "system" },
          { "type": "text", "text": " / " },
          { "type": "variable", "name": "total_pages", "scope": "system" }
        ]
      }
    ]
}

blocks 当前公开三种类型:

  • paragraph
  • list
  • page_break

page_break 是显式 block 节点。公开 block text contract 不再使用 \f{page}{total_pages} 这类字符串控制语法。

7.1.3 Paragraph Block

json
{
  "type": "paragraph",
  "style": {
    "align": "justify",
    "direction": "auto",
    "line_height": 1.35,
    "space_after": 2.5,
    "indent_first_line": 6
  },
  "inlines": [
    { "type": "text", "text": "页码:" },
    { "type": "variable", "name": "page", "scope": "system" }
  ]
}

paragraph.style 支持:

  • align: left | center | right | justify
  • direction: auto | ltr | rtl
  • line_height
  • space_before
  • space_after
  • indent_left
  • indent_right
  • indent_first_line
  • hanging_indent
  • keep_together
  • keep_with_next
  • widow_orphan_control
  • tabs

7.1.4 List Block

json
{
  "type": "list",
  "list": {
    "kind": "ordered",
    "marker_gap": 2.5,
    "item_spacing": 1.5,
    "start_at": 1
  },
  "items": [
    {
      "blocks": [
        {
          "type": "paragraph",
          "inlines": [{ "type": "text", "text": "第一条" }]
        }
      ]
    }
  ]
}

list 当前只在 full_text_profile 中开放,不允许出现在:

  • section_text_profile
  • table_text_profile
  • barcode_text_profile

7.1.5 Inline Nodes

当前公开四种 inline 节点:

  • text
  • variable
  • line_break
  • tab

text 示例:

json
{
  "type": "text",
  "text": "Hello",
  "style": {
    "font_weight": "bold",
    "color": "#B91C1C"
  },
  "link": {
    "target": { "type": "url", "url": "https://example.com" }
  }
}

variable 示例:

json
{
  "type": "variable",
  "name": "page",
  "scope": "system"
}

variable.scope 只允许:

  • system
  • binding
  • computed

其中:

  • systemPOST /api/v1/render 中目前只公开支持 pagetotal_pages
  • binding 的值来源于模板数据链路;如果你需要业务数据替换,请使用 POST /api/v1/template-render
  • computed 当前未作为公开能力开放

也就是说,直渲染接口当前只保证页码类系统变量。如果你需要业务数据替换或条件过滤,请使用模板接口。

7.1.6 InlineTextStyle

run 级样式支持:

  • font_family
  • font_size
  • font_weight: normal | medium | semibold | bold
  • font_style: normal | italic
  • font_mode: strict | prefer
  • color
  • opacity
  • letter_spacing
  • script: normal | superscript | subscript
  • background
  • decoration
  • link_style

规则:

  • 不支持在 run 级直接写段落或 frame 字段
  • font_mode 不允许脱离同层 font_family 单独出现
  • font_mode = "auto" 不是公开输入值;自动模式只来自“当前链路没有显式字体”
  • strict 覆盖失败返回 API-002
  • 自动 / prefer 完整回退失败返回 API-504

7.1.7 BlockTextFrame

frame 支持:

  • width
  • height
  • vertical_align: top | middle | bottom
  • overflow: visible | clip | ellipsis | paginate
  • shrink_to_fit
  • min_font_size
  • padding
  • border
  • background
  • columns
  • column_gap

规则:

  • frametable_text_profilebarcode_text_profile 中不允许出现
  • rotation != 0 不允许与 frame.overflow = "paginate" 同时出现
  • frame.height 不允许与 page_break 同时出现
  • frame.overflow = clip | ellipsis 不允许与 page_break 同时出现
  • frame.overflow = paginate 不允许与 shrink_to_fit = true 同时出现
  • section_text_profile 不允许 overflow = paginate 或多栏布局

7.1.8 Feature Profiles

text 能力会按上下文收缩,profile 不需要在 JSON 中显式传入,而是由元素所在位置决定:

  • full_text_profile

    • 顶层普通 text
    • block: paragraph | list | page_break
    • inline: text | variable | line_break | tab
  • section_text_profile

    • header / footer / layers.background / layers.watermark / layers.stamp
    • block: paragraph
    • inline: text | variable | line_break | tab
    • 不允许 list
    • 不允许 page_break
    • 不允许 frame.overflow = paginate
    • 不允许多栏布局
  • table_text_profile

    • table 文本
    • block: paragraph
    • inline: text | variable | line_break
    • 不允许 list
    • 不允许 page_break
    • 不允许 tab
    • 不允许 inline link
    • 不允许 frame
  • barcode_text_profile

    • barcode_text
    • block: paragraph
    • inline: text | variable | line_break
    • 不允许 list
    • 不允许 page_break
    • 不允许 tab
    • 不允许 inline link
    • 不允许 frame

7.2 Barcode

必填字段: y, format, content, width, height,并且必须二选一提供:

  • x
  • x_anchor

可选: style, options, barcode_text, rotation, z_index, comment, link

说明:

  • rotation 当前只支持 090180270
  • barcode_text 会继承条码旋转,因此也只支持同一组角度
  • format 当前大小写不敏感,并将 -_ 视为等价分隔符。
  • 2D / 矩阵类条码以模块矩阵方式编码;1D / 线性类条码以条带方式编码;maxicode 使用六边形网格。
  • 当前构建支持的 format 值包括:
    • 2D / 矩阵类:qrcode(qr)、microqr(micro-qr)、pdf417micropdf417(micro-pdf417)、datamatrix(data-matrix)、gs1datamatrix(gs1-datamatrix, gs1_datamatrix)、aztecmaxicodegs1qrcode(gs1-qrcode, gs1_qr, gs1-qr)
    • 1D / 线性类:code128(code-128)、code128a(code-128a)、code128b(code-128b)、code128c(code-128c)、gs1128(gs1-128)、code39(code-39)、code93(code-93)、codabarean8(ean-8)、ean13(ean-13)、upca(upc-a)、upce(upc-e)、itf(interleaved2of5)、itf14(itf-14)、gtin8(gtin-8)、gtin12(gtin-12)、gtin13(gtin-13)、gtin14(gtin-14)、isbn(isbn-13)、sscc(sscc-18)
    • 其他业务类:msi(msi-plessey)、msi10(msi-10)、msi11(msi-11)、msi1010(msi-1010)、msi1110(msi-1110)、upus10(s10)、uspsimb(usps-imb, intelligent-mail)、upcacomposite(upca-composite)、upcecomposite(upce-composite)

7.3 Image

必填字段: y, width, height,并且必须二选一提供:

  • x
  • x_anchor

可选: rotation, z_index, comment, link

图片来源支持两种互斥写法:

  • 简写:顶层 asset,可选顶层 format
  • 显式:顶层 source

规则:

  • assetsource 必须二选一
  • 顶层 format 仅用于顶层 asset 简写
  • 使用 source 时,格式提示写在 source 内部
  • 不支持 data:image/...;base64,... 形式的 Data URI

source.kind 当前支持:

  • asset
  • base64

说明:

  • asset 指服务托管的资源 key,不是客户端本地文件路径。
  • source.kind = "base64"payload 仅接受原始 Base64 内容,不带 data:image/...;base64, 前缀。
  • rotation 使用角度值,图片支持任意角度,例如 45-30

资源简写:

json
{
  "type": "image",
  "x": 4,
  "y": 8,
  "width": 15,
  "height": 6.5,
  "asset": "pdn_express_logo",
  "format": "jpg"
}

显式资源写法:

json
{
  "type": "image",
  "x": 4,
  "y": 8,
  "width": 15,
  "height": 6.5,
  "source": {
    "kind": "asset",
    "key": "pdn_express_logo",
    "format": "jpg"
  }
}

显式 Base64 写法:

json
{
  "type": "image",
  "x": 4,
  "y": 8,
  "width": 15,
  "height": 6.5,
  "source": {
    "kind": "base64",
    "format": "jpg",
    "payload": "/9j/4AAQSkZJRgABAQ..."
  }
}

7.3.1 核心元素样式 JSON 示例

带样式 text

json
{
  "type": "text",
  "x": 18,
  "y": 18,
  "content": "Invoice #INV-2026-001",
  "style": {
    "font_family": "NotoSans-Regular",
    "font_mode": "prefer",
    "font_size": 12,
    "font_weight": "bold",
    "color": "#111827",
    "width": 90,
    "text_align": "left",
    "line_height": 1.25,
    "letter_spacing": 0.2
  }
}

带样式 barcode

json
{
  "type": "barcode",
  "x": 18,
  "y": 34,
  "format": "qrcode",
  "content": "https://example.com/track/INV-2026-001",
  "width": 28,
  "height": 28,
  "style": {
    "color": "#111111",
    "background_color": "#FFFFFF"
  },
  "barcode_text": {
    "enabled": true,
    "position": "bottom",
    "offset": 1.5,
    "style": {
      "font_family": "NotoSans-Regular",
      "font_mode": "prefer",
      "font_size": 8,
      "color": "#374151",
      "width": 28,
      "text_align": "center"
    }
  }
}

带样式 rect

json
{
  "type": "rect",
  "x": 12,
  "y": 70,
  "width": 80,
  "height": 18,
  "corner_radius": 2,
  "fill": {
    "color": "#F9FAFB",
    "opacity": 1
  },
  "stroke": {
    "color": "#D1D5DB",
    "width": 0.4
  }
}

带样式 image

json
{
  "type": "image",
  "x": 14,
  "y": 92,
  "width": 18,
  "height": 9,
  "rotation": -8,
  "asset": "pdn_express_logo",
  "format": "jpg",
  "link": {
    "target": {
      "type": "url",
      "url": "https://example.com"
    }
  }
}

带样式 header / footer

json
{
  "header": {
    "height": 14,
    "elements": [
      {
        "type": "text",
        "x": 12,
        "y": 8,
        "content": "Monthly Report",
        "style": {
          "font_family": "NotoSans-Regular",
          "font_mode": "prefer",
          "font_size": 10,
          "font_weight": "bold",
          "color": "#111827",
          "width": 80
        }
      }
    ]
  },
  "footer": {
    "height": 12,
    "elements": [
      {
        "type": "text",
        "x": 150,
        "y": 6,
        "content": "Page 1 / 12",
        "style": {
          "font_family": "NotoSans-Regular",
          "font_mode": "prefer",
          "font_size": 8,
          "color": "#6B7280",
          "width": 40,
          "text_align": "right"
        }
      }
    ]
  }
}

7.4 Table

说明:

  • 当前公开 table schema 仅支持本节定义的结构。

顶层结构:

json
{
  "type": "table",
  "x": 12,
  "y": 24,
  "width": 180,
  "columns": [],
  "rows": [],
  "cell": {},
  "header": {},
  "row_header": {},
  "body": {},
  "grid": {},
  "pagination": {}
}

顶层字段:

字段类型必填说明
xnumber左上角 X(mm)
ynumber左上角 Y(mm)
z_indexinteger层级
commentstring备注
widthnumber表格总宽度
columnsTableColumn[]列定义
rowsTableRow[]行数据
cellTableCellStyle全表默认单元格样式
headerTableHeaderConfig列表头配置
row_headerTableZoneConfig行表头区配置
bodyTableBodyConfig正文区配置
gridTableGridConfig网格线配置
paginationTablePaginationConfig分页配置

7.4.1 Column

json
{
  "key": "amount",
  "header": "Amount",
  "width": { "mode": "fixed", "value": 30 },
  "role": "data",
  "cell": {
    "text": { "text_align": "right" }
  },
  "header_cell": {
    "text": { "font_weight": "bold" }
  }
}
字段类型必填说明
keystring列 key,必须唯一
headerstring叶子列表头文本,默认空字符串
widthTableColumnWidth列宽模型
rolestringdata / row_header,默认 data
cellTableCellStyle该列正文单元格样式
header_cellTableCellStyle该列列表头单元格样式

规则:

  • columns[].key 必须唯一。
  • role = "row_header" 的列必须连续放在最左侧。
  • 支持多个行表头列。

TableColumnWidth:

json
{ "mode": "fixed", "value": 30 }
{ "mode": "percent", "value": 25 }
{ "mode": "auto" }

7.4.2 Row / Cell

rows 为对象数组,key 对应 columns[].key

简写单元格:

json
{ "name": "Apple", "qty": 2, "enabled": true, "note": null }

复杂单元格:

json
{
  "group": {
    "content": "Fruit",
    "row_span": 2,
    "col_span": 1,
    "style": {
      "text": { "font_weight": "bold" }
    },
    "link": {
      "target": { "type": "url", "url": "https://example.com" }
    }
  }
}

复杂单元格字段:

字段类型必填说明
contentstring | number | boolean | null | BlockTextContent单元格内容;可为标量或富文本
row_spaninteger向下合并行数
col_spaninteger向右合并列数
styleTableCellStyle单元格样式覆盖
linkLinkSpec单元格超链接

规则:

  • row_span >= 1
  • col_span >= 1
  • span 不能越界,也不能和其他 span 重叠
  • null 渲染为空字符串
  • boolean 渲染为 "true" / "false"
  • BlockTextContenttable_text_profile 处理
  • link 仅能出现在复杂单元格对象中

7.4.3 TableCellStyle

json
{
  "padding": { "x": 1, "y": 1 },
  "text": { "font_size": 9, "color": "#111111" },
  "fill": { "color": "#FFFFFF" },
  "content_offset_x": 1.5,
  "content_offset_y": 0.5,
  "borders": {
    "top": false,
    "right": { "color": "#111111", "width": 0.2 },
    "bottom": { "color": "#111111", "width": 0.2 },
    "left": false
  }
}
字段类型说明
paddingTablePadding单元格内边距
textTextStyle文本样式
fillFillStyle填充样式
content_offset_xnumber单元格内容横向微调(mm)
content_offset_ynumber单元格内容纵向微调(mm)
bordersTableBorders单元格单边边框

TablePadding:

字段类型说明
xnumber水平内边距(mm)
ynumber垂直内边距(mm)

TableBorders:

  • top?: false | StrokeStyle
  • right?: false | StrokeStyle
  • bottom?: false | StrokeStyle
  • left?: false | StrokeStyle
  • diagonal_tl_br?: false | StrokeStyle
  • diagonal_bl_tr?: false | StrokeStyle

7.4.4 Header / Row Header / Body

header:

json
{
  "show": true,
  "repeat_on_page_break": true,
  "rows": [
    {
      "cells": [
        { "content": "Product", "col_span": 2 },
        { "content": "Stock", "row_span": 2 }
      ]
    }
  ],
  "cell": {
    "fill": { "color": "#F3F4F6" },
    "text": { "font_weight": "bold" }
  }
}

字段:

  • show?: boolean,默认 true
  • repeat_on_page_break?: boolean,默认 true
  • rows?: TableHeaderRow[],分组表头行;叶子表头仍来自 columns[].header
  • cell?: TableCellStyle

row_header:

json
{
  "cell": {
    "fill": { "color": "#F8F8F8" },
    "text": { "font_weight": "bold" }
  }
}

字段:

  • cell?: TableCellStyle

body:

json
{
  "cell": {},
  "alternate_fill": { "color": "#FAFAFA" }
}

字段:

  • cell?: TableCellStyle
  • alternate_fill?: FillStyle

表达规则:

  • 分组表头使用 header.rows
  • 叶子列表头使用 columns[].header
  • 行表头使用 columns[].role = "row_header"
  • header.rows[].cells[].contentcolumns[].header 都支持 string | number | boolean | null | BlockTextContent

7.4.5 Grid

json
{
  "top": {
    "color": "#111111",
    "width": 0.3,
    "compound": { "kind": "double", "gap": 0.3 }
  },
  "right": {
    "color": "#111111",
    "width": 0.3,
    "compound": { "kind": "double", "gap": 0.3 }
  },
  "bottom": {
    "color": "#111111",
    "width": 0.3,
    "compound": { "kind": "double", "gap": 0.3 }
  },
  "left": {
    "color": "#111111",
    "width": 0.3,
    "compound": { "kind": "double", "gap": 0.3 }
  },
  "horizontal": { "color": "#D1D5DB", "width": 0.2 },
  "vertical": false
}

字段:

  • top?: false | StrokeStyle
  • right?: false | StrokeStyle
  • bottom?: false | StrokeStyle
  • left?: false | StrokeStyle
  • horizontal?: false | StrokeStyle
  • vertical?: false | StrokeStyle

说明:

  • grid.top/right/bottom/left/horizontal/vertical 统一使用 StrokeStyle

7.4.6 Pagination

json
{
  "keep_spans_together": true,
  "row_min_height": 10,
  "header_min_height": 12
}

字段:

  • keep_spans_together?: boolean,默认 true
  • row_min_height?: number
  • header_min_height?: number

说明:

  • 当存在 row_span 时,要求 keep_spans_together = true

7.4.7 宽度与样式规则

宽度规则:

  • columns.length >= 1
  • columns[].width 统一使用 fixed / percent / auto
  • 若提供 table.width:
    • fixed 先按 mm 占用
    • percenttable.width 百分比分配
    • auto 吃剩余空间,并基于表头/正文内容测量分配
    • 若不存在 auto,列宽求解结果必须精确填满 table.width
  • 若未提供 table.width:
    • 所有列都必须使用 fixed
  • percent 总和不得超过 100
  • rows 中出现未在 columns[].key 定义的字段会报错
  • header.show = false 时,header.rowscolumns[].headerheader_cell 视为忽略
  • 当使用 row_span 时,不支持 keep_spans_together = false

样式优先级:

  1. settings.defaults
  2. table.cell
  3. header.cell / row_header.cell / body.cell
  4. columns[].cell / columns[].header_cell
  5. cell.style

边框优先级:

  1. grid
  2. table.cell.borders
  3. 区域级 cell.borders
  4. 列级 cell/header_cell.borders
  5. cell.style.borders

7.5 Stack / Block

用途:

  • stack 用于"表格结束后再跟随一组内容"的发票/对账单场景。
  • 它不接管 table 的原有定位;table.x/y/width 仍按当前语义工作。
  • stack 只解决 table 与后续内容块之间的顺序排版和分页问题。

结构:

json
{
  "type": "stack",
  "gap": 6,
  "children": [
    {
      "type": "table",
      "x": 18,
      "y": 123,
      "width": 180,
      "columns": [],
      "rows": []
    },
    {
      "type": "block",
      "elements": [
        { "type": "text", "x": 128, "y": 0, "content": "Subtotal" },
        { "type": "text", "x": 168, "y": 0, "content": "$1,343.65" },
        { "type": "line", "x1": 128, "y1": 7, "x2": 178, "y2": 7 }
      ]
    }
  ]
}

顶层字段:

字段类型必填说明
gapnumber前后 child 之间的垂直间距(mm),默认 0
childrenStackChild[]顺序排版的子项

规则:

  • stack 仅允许出现在 pages[].elements
  • stack.children[0] 必须是 table
  • stack.children[1..] 只能是 block
  • children.length >= 2

block:

json
{
  "type": "block",
  "elements": [
    { "type": "text", "x": 128, "y": 0, "content": "Subtotal" },
    { "type": "text", "x": 168, "y": 0, "content": "$1,343.65" }
  ]
}

规则:

  • block 不提供自己的 x/y/width/height
  • block.elements[].x 继续使用现有 body 元素语义
  • block.elements[].y 为相对 block 起点的偏移
  • block 内不允许再嵌套 table / stack / block
  • block 高度由系统根据内部元素自动测量

分页语义:

  • table 先按现有逻辑分页
  • 只有在 table 真正结束后,后续 block 才开始排版
  • 若某个 block 当前页放不下,则整块移到下一页
  • 若某个 block 自身高度已超过一页可用高度,则直接报错
  • gap 表示前一个 child 最终结束位置到下一个 child 起始位置的垂直距离
  • block 被整体移到下一页时,不保留上一页的 gap

8. 坐标与单位

  • 坐标单位: mm
  • 原点: 左上角 (0, 0)
  • X 轴向右, Y 轴向下

9. 默认值优先级

9.1 样式优先级

  1. 元素本身字段(例如 line.stroke.width
  2. settings.defaults 对应字段(如 defaults.stroke.width
  3. 系统默认配置

table 的优先级为:

  1. settings.defaults
  2. table.cell
  3. header.cell / row_header.cell / body.cell
  4. columns[].cell / columns[].header_cell
  5. cell.style

9.2 线条/形状默认行为

  • line.stroke 全省略时:
    • color 默认 #000000
    • width 默认 0.4
  • rect/circle/ellipse/polygon.stroke 全省略时:
    • 不绘制边框
    • 若显式提供 stroke,缺失字段会继续按公开默认链路补齐
  • fill 全省略时默认不填充(透明)
  • rect.corner_radius 默认链路:
    • element.corner_radius
    • settings.defaults.shape.corner_radius
    • 系统默认值 0

10. 错误码

错误码HTTP触发条件
API-001400JSON 非法
API-002400请求校验失败
API-003400PDF/A profile 非法或不支持
API-004400页数超限
API-005400页面尺寸或边距非法
API-006400链接参数非法
API-007400图片 payload 超限
API-008400请求体过大
API-009400文本 form feed 使用受限
API-010400Stack 布局参数错误
API-101401Authorization 缺失或格式错误
API-102403鉴权失败
API-103403鉴权失败(token 已列入黑名单)
API-501500PDF 渲染失败
API-502500PDF/A 合规校验失败
API-503500布局溢出错误
API-504500资源加载失败
API-505500字体解析失败
API-506500图片未找到
API-507500分页内部错误
API-900500系统内部错误
API-901500系统内部错误
API-902500系统内部错误
API-999500未知内部错误

脱敏规则:

  • API-102API-103 以及系统错误(API-900 / API-901 / API-902 / API-999)对外返回脱敏后的公开文案。
  • 输入错误与渲染错误(API-501 ~ API-507)会保留可用于定位问题的细节。

常见 ValidationError 触发:

  • link 非法(不支持的 URL scheme、页码越界、非法 padding/border
  • table 非法(未知列 key、table.width 无法为未声明列分配正宽度、非法 span)
  • profile 非法
  • font_mode 脱离同层 font_family 单独出现
  • 显式 strict 字体无法覆盖提交文本
  • xx_anchor 同时出现

边界说明:

  • API-008 当前默认是 16 MiB;不同服务部署可以配置不同上限
  • API-004 不是固定常量:实际生效值可能同时受服务配置与当前 token 有效策略约束
  • API-007 按策略生效:仅当当前请求命中的有效策略启用了图片大小上限时才会触发