NAV
cURL Python

Introduction

Welcome to Plato! Plato is a REST API that provides developers with a simple-to-use interface for templating.

In a very summarized flow, you create your own HTML templates, adding placeholders that are later filled with specific data, then you define the data the template requires via a JSON schema structure; after adding the template to your Plato instance, specific endpoints can be used to render the template in various formats with the provided data.

As an example, Plato can be used to define and render custom HTML emails.

Every endpoint available on Plato is described and accompanied by a visual example of how the API responds. For an improved experience when integrating Plato to your code, you can import our libraries:

All Python examples used in the examples are from the above library.

When executing the Plato API, a swagger page is provided, which can be used for testing or to get more information about the endpoints. Locally, it is hosted on http://localhost:5000/apidocs/. If you are using our Docker image, you can host it on any port.

Please check our Privacy Policy for more details on data collection. Furthermore, by using the Core API you are agreeing to our Terms and Conditions.

Quick Start

Plato is a microservice that should be added directly to your deployment environment. A docker image is available on Docker Hub, and this guide will show you how to integrate Plato with your existing project.

Requirements

Steps

Configure S3 Bucket

You will need to create an S3 Bucket if your project doesn't already have one, and fetch its credentials. Plato will need the AWS credentials so it can access the S3 Bucket and load the templates and static content to the machine. The AWS credentials need to be passed into the Plato container as a volume - an example docker-compose file is available later in this tutorial.

Also, please take into consideration that the bucket's structure will need to follow a specific set of rules:

For example:

Docker configuration

plato:
  image: plato-api:<VERSION>
  environment:
    DATA_DIR: /plato-data/
    TEMPLATE_DIRECTORY: /plato-data/templating/
    DB_HOST: plato-database
    DB_PORT: 5432
    DB_USERNAME: <USER>
    DB_PASSWORD: <PASSWORD>
    DB_DATABASE: <DB>
    S3_BUCKET: <PLATO_BUCKET>
    S3_TEMPLATE_DIR: <PLATO_BASE_DIRECTORY>
  depends_on:
    - plato-database
  volumes:
    - <AWS_CREDENTIALS>:/root/.aws
  ports:
    - 3000:80

plato-database:
  image: postgres:<VERSION>
  volumes:
    - <DATABASE_DIR>/plato-db:/data/db
  environment:
    POSTGRES_USER: <USER>
    POSTGRES_PASSWORD: <PASSWORD>
    POSTGRES_DB: <DB>
    PGDATA: /data/db/
  ports:
    - 5432:5432

Plato requires a Postgres database to work with; we recommend configuring it via Docker, but you can also use any external database already available on your project. Plato is currently developed with Postgres version 9.6.3, and has been successfully used with Postgres up to version 12.11. The database contains a single table called Template where all templates are stored. The Alembic table can be ignored, since it is used for migrations.

You can directly copy the accompanying docker-compose configuration to your project, but make sure to fill in the missing variables:

You should not change the values for the DATA_DIR and TEMPLATE_DIRECTORY variables. All others can be changed and adapted to fit accordingly to your project's configuration. Also note that a volume for AWS credentials is created, so you have to indicate where the credentials are in the running environment.

You can now run both docker containers and the Plato API swagger will be available on http://localhost:3000/apidocs. 3000 is the default port defined on the docker-compose file, but it can be changed for anything else.

Add Templates to Plato

{
  "title": "student-diploma",
  "schema": {
    "type": "object",
    "required": [
      "recipient_name",
      "certificate_number"
    ],
    "properties": {
      "certificate_number": {
        "type": "string"
      },
      "qr_code": {
        "type": "string"
      },
      "recipient_name": {
        "type": "string"
      }
    }
  },
  "type": "text/html",
  "metadata": {
    "qr_entries": [
      "qr_code"
    ]
  },
  "example_composition": {
    "qr_code": "https://vizidox.com",
    "recipient_name": "Alan Turing",
    "certificate_number": "123ABC"
  },
  "tags": [
    "2022"
  ]
}

If you have already added your template files to the Plato storage, per the previous instructions on this guide, and you have both the database and the API up and running, then the only thing missing is to create your JSON Schema and populate the database with the template data.

To define the JSON Schema and other data, you need to define what fields in the HTML are to be filled in, and specify their types, if they are required, etc. Check the JSON Schema specification to learn the expected syntax. Regarding the rest of the template data:

To populate the templates on the Plato database, you can follow two different approaches:

Example query to insert a template on the database

INSERT INTO public."template"
(id, "schema", "type", metadata, tags, example_composition)
VALUES('student-diploma', '{"type": "object", "required": ["recipient_name", "certificate_number"], "properties": {"qr_code": {"type": "string"}, "recipient_name": {"type": "string"}, "certificate_number": {"type": "string", "title": "Certificate Number"}}}'::jsonb, 'text/html'::public.template_mime_type, '{"qr_entries": ["qr_code"]}'::jsonb, '{}', '{"qr_code": "https://vizidox.com", "recipient_name": "Alan Turing", "certificate_number": "C5678"}'::jsonb);

An example insertion query can be found on the right side of this page.

  docker-compose run --rm plato flask <command>

  Commands:
    db                     Perform database migrations.
    export_template        Export new template to file Args: output: output...
    refresh                
    register_new_template  Imports new template from json file and inserts it...
    routes                 Show the routes for the app.
    run                    Run a development server.
    shell                  Run a shell in the app context.

After inserting the template data in the database, the Plato API needs to be refreshed. To do so, you can either restart the Plato container manually, or run the refresh command via the Plato CLI. At this time, all template files will be downloaded to Plato's local temporary storage (the aforementioned DATA_DIR), so depending on the number of templates that are configured, this might take some time. Every time Plato is restarted, these files are re-downloaded.

Create Template

A Plato template contains two parts:

To create a template, first you need to create your base HTML file. There is nothing special about this file, but there are some details that you should bear in mind:

When you are done with your template HTML file, you need to identify the fields that are to be placeholders for the template. Plato uses Jinja to compose the variable values on to the placeholders. For example, if you have want to fill a specific place on the template with a user's name, then you write {{ p.username }}, where username is a field on the JSON schema. For more details on how you can customize your template with Jinja, check the template designer page.

There are also some filters available that allow you to customize the appearance of the values added to the placeholders. For example, if you pass in a string and you want it converted to lower-case, then write the following: {{ p.name | lower }}. Multiple filters can be chained, and they are executed from the right to the left. All [Jinja pre-defined filters}{https://jinja.palletsprojects.com/templates/#filters} can be used, as well as some custom filters that have been added:

After you are done with the HTML file, then create the corresponding JSON Schema, and add everything to Plato, according to instructions on the Quick Start guide.

Template Management

Create a Template

curl -X POST "http://localhost:5000/template/create" -H  "accept: application/json" -H  "Content-Type: multipart/form-data" -F "zipfile=<file>>;type=application/zip" -F "template_details=<details>>"
template = plato_client.create_template(template, template_details)
class TemplateInfo(NamedTuple):
    template_id: str
    template_schema: dict
    type: str
    metadata: dict
    tags: List[str]

Create a new template on Plato. Adds the provided HTML and static files to Plato's long term storage, and the details are added to the database.

Parameter Type Optional Description
zipfile Form data No Archive containing the template HTML and static files
template_details Form data No Details of the template, in json format

The zipfile parameter should be a ZIP archive with a structure similar the Plato's permanent storage:

The template_details parameter should be in json format and include all relevant details for the template creation:

Name Description
id Template identifier.
schema Template JSON schema.
type Type of the template. Only "text/html" is accepted.
metadata Any additional metadata such as QR Code fields.
example_composition A JSON containing an example composition for the template.
tags Extra tags to help identify the template

HTTP Request

POST http://localhost:5000/template/create

Returns

If successful, the HTTP response is a 201 CREATED, along with the created template.

Errors

code Description
400 Provided ZIP file does not have the correct structure
409 The template already exists
415 The provided file is not a ZIP file

Update a Template

curl -X PUT "http://localhost:5000/template/<template_id>/update" -H  "accept: application/json" -H  "Content-Type: multipart/form-data" -F "zipfile=<file>>;type=application/zip" -F "template_details=<details>>"
template = plato_client.update_template(template_id, file_stream, template_details)
class TemplateInfo(NamedTuple):
    template_id: str
    template_schema: dict
    type: str
    metadata: dict
    tags: List[str]

Update an existing template on Plato. The template is fully updated, including the HTML file, static content and database entry.

Parameter Type Optional Description
zipfile Form data No Archive containing the template HTML and static files
template_details Form data No Details of the template, in json format

The format of the zipfile and the template_details parameters is the same as in the previous endpoint.

HTTP Request

PUT http://localhost:5000/template/<template_id>/update

Returns

If successful, the HTTP response is a 200 OK, along with the updated template.

Errors

code Description
400 Provided ZIP file does not have the correct structure
404 Template not found
415 The provided file is not a ZIP file

Update Template Details

curl -X PATCH "http://localhost:5000/template/<template_id>/update_details" -H  "accept: application/json" -H  "Content-Type: application/json" -d <details>
template = plato_client.update_template_details(template_id, template_details)
class TemplateInfo(NamedTuple):
    template_id: str
    template_schema: dict
    type: str
    metadata: dict
    tags: List[str]

Update the database details for an existing template on Plato. No changes are done to the HTML and static content of the template.

Parameter Type Optional Description
template_details Body No Details of the template, in json format

The format of the template_details parameter is the same as in the template creation endpoint.

HTTP Request

PATCH http://localhost:5000/template/<template_id>/update_details

Returns

If successful, the HTTP response is a 200 OK, along with the updated template.

Errors

code Description
400 Input not in correct form
404 Template not found

Template

The Template Object

{
  "metadata": {
    "qr_entries": [
      "qr_code"
    ]
  },
  "tags": ["2022"],
  "template_id": "student-diploma",
  "template_schema": {
    "properties": {
      "certificate_number": {
        "title": "Certificate Number",
        "type": "string"
      },
      "qr_code": {
        "type": "string"
      },
      "recipient_name": {
        "type": "string"
      }
    },
    "required": [
      "recipient_name",
      "certificate_number"
    ],
    "type": "object"
  },
  "type": "text/html"
}

A Template object is none other than an HTML template itself, including the json schema used to fill in the defined variables in the HTML file.

Field Description
template_id Unique identifier of the template.
metadata Extra metadata used by the template. For example, can be used to define QR Code fields.
tags Any additional tags that can identify the template.
template_schema The json schema of the template.
type The type of the template (HTML only).
example_composition A json containing example values to fill in the template.

Get All Templates

curl -X GET "http://localhost:5000/templates/" -H  "accept: application/json"
templates = plato_client.templates(tags)
class TemplateInfo(NamedTuple):
    template_id: str
    template_schema: dict
    type: str
    metadata: dict
    tags: List[str]

Retrieves all templates available on the database. Has a single query parameter, "tags", that can be used multiple times in the same requests. All the tags provided are used to filter for templates that contain at least one of the tags.

HTTP Request

GET http://localhost:5000/templates/?tags=abc&tags=xyz

Returns

If successful, the HTTP response is a 200 OK, along with all templates.

Get A Template

curl -X GET "http://localhost:5000/templates/<template_id>" -H  "accept: application/json"

Retrieves a specific template and its details.

HTTP Request

GET "http://localhost:5000/templates/<template_id>"

Returns

If successful, the HTTP response is a 200 OK, along with the template.

Errors

code Description
404 Template not found

Compose File

curl -X POST "http://localhost:5000/template/<template_id>/compose" -H  "accept: <mime_type>" -H "Content-Type: application/json" -d "{\"recipient_name\": \"Alan Turing\"}"
file = plato_client.compose(template_id, compose_data, mime_type, page, resize_height, resize_width)

Composes a template into a file of a specific type by filling in the placeholders with the intended data. The type of the file to compose can be defined by the accept header, and is expected to be in MIME format. It is currently possible to generate a file of three different types:

Other parameters include:

Parameter Type Optional Description
template_id Path No ID of the template to compose.
schema Body No Json containing the data to add to the template, according to template schema.
accept Header No Type of file to create.
page query Yes Specific page of the template to compose. If none is given, all pages are composed. Defaults to one if an image type is chosen.
height query Yes Height of the file to compose, if image type is chosen.
width query Yes Weight of the file to compose, if image type is chosen.

HTTP Request

POST http://localhost:5000/template/<template_id>/compose

Returns

If successful, the HTTP response is a 200 OK, along with the file.

Errors

code Description
400 Invalid compose data for template schema
404 Template not found
406 Unsupported MIME type for file

Compose Example

curl -X GET "http://localhost:5000/template/<template_id>/example" -H  "accept: <mime_type>
file = plato_client.compose(template_id, compose_data, mime_type, page, resize_height, resize_width)

Composes a template into an example file of a specific type. The placeholders are filled in with example data that is configured directly in the database. The type of the file to compose can be defined by the accept header, and is expected to be in MIME format. It is currently possible to generate a file of three different types:

Other parameters include:

Parameter Type Optional Description
template_id Path No ID of the template to compose.
accept Header No Type of file to create.
page query Yes Specific page of the template to compose. If none is given, all pages are composed. Defaults to one if an image type is chosen.
height query Yes Height of the file to compose, if image type is chosen.
width query Yes Weight of the file to compose, if image type is chosen.

HTTP Request

GET http://localhost:5000/template/<template_id>/example

Returns

If successful, the HTTP response is a 200 OK, along with the example file.

Errors

code Description
404 Template not found
406 Unsupported MIME type for file