Skip to content

297 × 210 mm

Certificates

Course completion certificate

A landscape A4 certificate for training providers and online courses. It names the recipient, course, hours and completion date, prints two instructor signature lines from a list, and adds a certificate ID with a QR code for public verification inside a decorative SVG frame.

A4 landscapeLocale en-USHTML + Jinja

Opens Dynamic Document API with this template preloaded in a free workspace.

Template language features

  • Loops
  • Conditionals
  • Filters
  • QR code
  • Date formatting

Filters such as format_currency and qrcode are described in the template language reference.

Variables

Derived from the sample data: 5 top-level fields, 20 paths in total. Send the same shape as data.

PathTypeExample
issuerobject
issuer.namestring"Aldermoor Institute of Applied Technology"
issuer.websitestring"aldermoor.example.org"
certificateobject
certificate.idstring"AMI-CSE-2026-04817"
certificate.completion_datedate"2026-09-11"
certificate.verify_urlstring"https://verify.example.org/c/AMI-CSE-2026-0481…"
certificate.localestring"en-US"
recipientobject
recipient.namestring"Jordan A. Whitcombe"
courseobject
course.titlestring"Foundations of Cloud Security Engineering"
course.hoursnumber36
course.deliverystring"Live online cohort"
course.start_datedate"2026-07-20"
course.modulesarray<string> · 5"Identity and access"
course.distinctionbooleantrue
signatoriesarray<object> · 2
signatories[].namestring"Dr. Selene Oyelaran"
signatories[].titlestring"Lead Instructor"

Sample data

Fictional records used for previews. Replace them with your own data when you call the API.

data.json
{
  "issuer": {
    "name": "Aldermoor Institute of Applied Technology",
    "website": "aldermoor.example.org"
  },
  "certificate": {
    "id": "AMI-CSE-2026-04817",
    "completion_date": "2026-09-11",
    "verify_url": "https://verify.example.org/c/AMI-CSE-2026-04817",
    "locale": "en-US"
  },
  "recipient": {
    "name": "Jordan A. Whitcombe"
  },
  "course": {
    "title": "Foundations of Cloud Security Engineering",
    "hours": 36,
    "delivery": "Live online cohort",
    "start_date": "2026-07-20",
    "modules": ["Identity and access", "Network segmentation", "Secrets management", "Logging and detection", "Incident response"],
    "distinction": true
  },
  "signatories": [
    { "name": "Dr. Selene Oyelaran", "title": "Lead Instructor" },
    { "name": "Marcus Feldhaus", "title": "Director of Professional Programs" }
  ]
}

Source

The body markup with Jinja, the stylesheet placed in <head>.

{#- Course completion certificate on a single A4 landscape sheet. The frame is inline SVG in
    millimetre units (viewBox 297 × 210); the corner ornaments are placed with a loop. Signatures come
    from the signatories array and the QR code links to the public verification page. -#}
{%- set locale = certificate.locale | default("en-US") -%}

<div class="sheet">
  <svg class="frame" viewBox="0 0 297 210" preserveAspectRatio="none" aria-hidden="true">
    <defs>
      <pattern id="weave" width="5" height="5" patternUnits="userSpaceOnUse">
        <path d="M0 2.5C1.25 0.6 2.5 0.6 2.5 2.5S3.75 4.4 5 2.5" fill="none" stroke="#b08d57" stroke-width="0.28"/>
        <path d="M0 2.5C1.25 4.4 2.5 4.4 2.5 2.5S3.75 0.6 5 2.5" fill="none" stroke="#1b2a4a" stroke-width="0.18"/>
      </pattern>
    </defs>
    <rect x="7" y="7" width="283" height="196" fill="none" stroke="#1b2a4a" stroke-width="1.4"/>
    <path d="M10 10H287V200H10Z M15 15V195H282V15Z" fill="url(#weave)" fill-rule="evenodd"/>
    <rect x="10" y="10" width="277" height="190" fill="none" stroke="#b08d57" stroke-width="0.35"/>
    <rect x="15" y="15" width="267" height="180" fill="none" stroke="#b08d57" stroke-width="0.35"/>
    <rect x="18" y="18" width="261" height="174" fill="none" stroke="#1b2a4a" stroke-width="0.25"/>
    {% for x, y in [[18, 18], [279, 18], [18, 192], [279, 192]] %}
    <g transform="translate({{ x }} {{ y }})">
      <rect x="-4.2" y="-4.2" width="8.4" height="8.4" transform="rotate(45)" fill="#ffffff" stroke="#b08d57" stroke-width="0.4"/>
      <rect x="-2.4" y="-2.4" width="4.8" height="4.8" transform="rotate(45)" fill="#1b2a4a"/>
    </g>
    {% endfor %}
  </svg>

  <div class="content">
    <header class="issuer">
      <svg class="issuer-mark" viewBox="0 0 48 48" aria-hidden="true">
        <path d="M24 3l18 10.5v21L24 45 6 34.5v-21z" fill="#1b2a4a"/>
        <path d="M24 12l10 5.8v11.6L24 35l-10-5.6V17.8z" fill="none" stroke="#b08d57" stroke-width="1.8"/>
        <path d="M24 12v23M14 17.8l20 11.6M34 17.8l-20 11.6" stroke="#b08d57" stroke-width="0.9"/>
      </svg>
      <p class="issuer-name">{{ issuer.name }}</p>
    </header>

    <h1 class="title">Certificate of Completion</h1>
    <svg class="ornament" viewBox="0 0 120 8" aria-hidden="true">
      <path d="M0 4h50M70 4h50" stroke="#b08d57" stroke-width="0.6"/>
      <path d="M60 0.5l3.5 3.5-3.5 3.5-3.5-3.5z" fill="#b08d57"/>
      <circle cx="52.5" cy="4" r="1" fill="#b08d57"/>
      <circle cx="67.5" cy="4" r="1" fill="#b08d57"/>
    </svg>

    <p class="intro">This certifies that</p>
    <p class="recipient">{{ recipient.name }}</p>
    <p class="intro">has successfully completed the {{ course.hours }}-hour course</p>
    <p class="course">{{ course.title }}</p>
    <p class="details">
      {{ course.delivery }} ·
      {{ course.start_date | format_date("long", locale) }} to {{ certificate.completion_date | format_date("long", locale) }}
      {% if course.distinction %}<span class="distinction">With distinction</span>{% endif %}
    </p>
    {% if course.modules %}
    <ul class="modules">
      {% for module in course.modules %}<li>{{ module }}{% if not loop.last %}<span class="dot" aria-hidden="true">◆</span>{% endif %}</li>{% endfor %}
    </ul>
    {% endif %}

    <footer class="bottom">
      {% for person in signatories %}
      <div class="signatory">
        <div class="sig-space"></div>
        <p class="sig-name">{{ person.name }}</p>
        <p class="sig-title">{{ person.title }}</p>
      </div>
      {% endfor %}
      <div class="verify">
        <div class="verify-text">
          <p class="verify-label">Certificate ID</p>
          <p class="verify-id">{{ certificate.id }}</p>
          <p class="verify-label">Issued</p>
          <p class="verify-date">{{ certificate.completion_date | format_date("long", locale) }}</p>
          <p class="verify-url">Verify at {{ certificate.verify_url | replace("https://", "") }}</p>
        </div>
        {{ certificate.verify_url | qrcode(size=200, margin=0, ecc="Q", color="#1b2a4a", alt="QR code to verify this certificate online") }}
      </div>
    </footer>
  </div>
</div>

Render it with the API

After adding the template to your workspace, render it by ID and pass your data. Arrays are shortened here.

curl -X POST https://api-eu.dynamicdocumentapi.com/v1/renders \
  -H "Authorization: Bearer $DYNAMIC_DOCUMENT_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "input": {
    "type": "template",
    "template_id": "tpl_01J9ZK3M7Q8V5W2X4Y6Z8A0B1C"
  },
  "data": {
    "issuer": {
      "name": "Aldermoor Institute of Applied Technology",
      "website": "aldermoor.example.org"
    },
    "certificate": {
      "id": "AMI-CSE-2026-04817",
      "completion_date": "2026-09-11",
      "verify_url": "https://verify.example.org/c/AMI-CSE-2026-04817",
      "locale": "en-US"
    },
    "recipient": {
      "name": "Jordan A. Whitcombe"
    },
    "course": {
      "title": "Foundations of Cloud Security Engineering",
      "hours": 36,
      "delivery": "Live online cohort",
      "start_date": "2026-07-20",
      "modules": [
        "Identity and access",
        "Network segmentation"
      ],
      "distinction": true
    },
    "signatories": [
      {
        "name": "Dr. Selene Oyelaran",
        "title": "Lead Instructor"
      },
      {
        "name": "Marcus Feldhaus",
        "title": "Director of Professional Programs"
      }
    ]
  },
  "output": {
    "format": "pdf",
    "filename": "certificate-course-completion.pdf"
  }
}'