curl --request POST \
--url https://api.print.app/v2/designs \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"title": "Business card",
"unit": "mm",
"width": 85,
"height": 55,
"pages": 2,
"pageTitles": [
"Front",
"Back"
],
"bleed": 3,
"safeMargin": 3
}
'import requests
url = "https://api.print.app/v2/designs"
payload = {
"title": "Business card",
"unit": "mm",
"width": 85,
"height": 55,
"pages": 2,
"pageTitles": ["Front", "Back"],
"bleed": 3,
"safeMargin": 3
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
title: 'Business card',
unit: 'mm',
width: 85,
height: 55,
pages: 2,
pageTitles: ['Front', 'Back'],
bleed: 3,
safeMargin: 3
})
};
fetch('https://api.print.app/v2/designs', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.print.app/v2/designs",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'title' => 'Business card',
'unit' => 'mm',
'width' => 85,
'height' => 55,
'pages' => 2,
'pageTitles' => [
'Front',
'Back'
],
'bleed' => 3,
'safeMargin' => 3
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.print.app/v2/designs"
payload := strings.NewReader("{\n \"title\": \"Business card\",\n \"unit\": \"mm\",\n \"width\": 85,\n \"height\": 55,\n \"pages\": 2,\n \"pageTitles\": [\n \"Front\",\n \"Back\"\n ],\n \"bleed\": 3,\n \"safeMargin\": 3\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.print.app/v2/designs")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"title\": \"Business card\",\n \"unit\": \"mm\",\n \"width\": 85,\n \"height\": 55,\n \"pages\": 2,\n \"pageTitles\": [\n \"Front\",\n \"Back\"\n ],\n \"bleed\": 3,\n \"safeMargin\": 3\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.print.app/v2/designs")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"title\": \"Business card\",\n \"unit\": \"mm\",\n \"width\": 85,\n \"height\": 55,\n \"pages\": 2,\n \"pageTitles\": [\n \"Front\",\n \"Back\"\n ],\n \"bleed\": 3,\n \"safeMargin\": 3\n}"
response = http.request(request)
puts response.read_body{
"object": "design",
"id": "design_01J8Z9K2M3N4P5Q6R7S8T9V0W1",
"title": "Business Card",
"unit": "mm",
"pages": [
{
"index": 0,
"title": "Front",
"previewUrl": "https://d1p81tn8mwpox2.cloudfront.net/?k=s3%3A%2F%2Fapp-print-cdn%2Fcontent_f1.png&size=1000"
},
{
"index": 1,
"title": "Back",
"previewUrl": "https://d1p81tn8mwpox2.cloudfront.net/?k=s3%3A%2F%2Fapp-print-cdn%2Fcontent_b1.png&size=1000"
}
],
"tags": [
"cards"
],
"connectorIds": [],
"resourceProfileIds": [],
"pdfProfileId": null,
"settings": {},
"created": "2026-09-02T14:05:11Z",
"modified": "2026-10-11T08:40:27Z"
}{
"error": true,
"code": "invalid_request",
"message": "width is required.",
"param": "width",
"requestId": "FZn-uhymjoEEJow="
}{
"error": true,
"code": "unauthorized",
"message": "Missing or invalid secret key. Send it as \"Authorization: Bearer sk_…\".",
"requestId": "FZn-uhymjoEEJow="
}{
"error": true,
"code": "account_suspended",
"message": "This account is suspended. Settle the outstanding invoice in the Print.App dashboard.",
"requestId": "FZn-uhymjoEEJow="
}{
"error": true,
"code": "not_found",
"message": "Not found.",
"requestId": "FZn-uhymjoEEJow="
}{
"error": true,
"code": "unsupported_media_type",
"message": "Send the request body as JSON, with \"Content-Type: application/json\".",
"requestId": "FZn-uhymjoEEJow="
}{
"message": "Too Many Requests"
}{
"error": true,
"code": "internal_error",
"message": "Something went wrong on our side. Retry the request; if it keeps failing, contact support with the requestId.",
"requestId": "FZn-uhymjoEEJow="
}Create a design
Creates a design with blank pages at a trim size, with optional bleed and safe margin, in a folder (the top level by default). Place content on it with POST /v2/designs/{id}/ops.
curl --request POST \
--url https://api.print.app/v2/designs \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"title": "Business card",
"unit": "mm",
"width": 85,
"height": 55,
"pages": 2,
"pageTitles": [
"Front",
"Back"
],
"bleed": 3,
"safeMargin": 3
}
'import requests
url = "https://api.print.app/v2/designs"
payload = {
"title": "Business card",
"unit": "mm",
"width": 85,
"height": 55,
"pages": 2,
"pageTitles": ["Front", "Back"],
"bleed": 3,
"safeMargin": 3
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
title: 'Business card',
unit: 'mm',
width: 85,
height: 55,
pages: 2,
pageTitles: ['Front', 'Back'],
bleed: 3,
safeMargin: 3
})
};
fetch('https://api.print.app/v2/designs', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.print.app/v2/designs",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'title' => 'Business card',
'unit' => 'mm',
'width' => 85,
'height' => 55,
'pages' => 2,
'pageTitles' => [
'Front',
'Back'
],
'bleed' => 3,
'safeMargin' => 3
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.print.app/v2/designs"
payload := strings.NewReader("{\n \"title\": \"Business card\",\n \"unit\": \"mm\",\n \"width\": 85,\n \"height\": 55,\n \"pages\": 2,\n \"pageTitles\": [\n \"Front\",\n \"Back\"\n ],\n \"bleed\": 3,\n \"safeMargin\": 3\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.print.app/v2/designs")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"title\": \"Business card\",\n \"unit\": \"mm\",\n \"width\": 85,\n \"height\": 55,\n \"pages\": 2,\n \"pageTitles\": [\n \"Front\",\n \"Back\"\n ],\n \"bleed\": 3,\n \"safeMargin\": 3\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.print.app/v2/designs")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"title\": \"Business card\",\n \"unit\": \"mm\",\n \"width\": 85,\n \"height\": 55,\n \"pages\": 2,\n \"pageTitles\": [\n \"Front\",\n \"Back\"\n ],\n \"bleed\": 3,\n \"safeMargin\": 3\n}"
response = http.request(request)
puts response.read_body{
"object": "design",
"id": "design_01J8Z9K2M3N4P5Q6R7S8T9V0W1",
"title": "Business Card",
"unit": "mm",
"pages": [
{
"index": 0,
"title": "Front",
"previewUrl": "https://d1p81tn8mwpox2.cloudfront.net/?k=s3%3A%2F%2Fapp-print-cdn%2Fcontent_f1.png&size=1000"
},
{
"index": 1,
"title": "Back",
"previewUrl": "https://d1p81tn8mwpox2.cloudfront.net/?k=s3%3A%2F%2Fapp-print-cdn%2Fcontent_b1.png&size=1000"
}
],
"tags": [
"cards"
],
"connectorIds": [],
"resourceProfileIds": [],
"pdfProfileId": null,
"settings": {},
"created": "2026-09-02T14:05:11Z",
"modified": "2026-10-11T08:40:27Z"
}{
"error": true,
"code": "invalid_request",
"message": "width is required.",
"param": "width",
"requestId": "FZn-uhymjoEEJow="
}{
"error": true,
"code": "unauthorized",
"message": "Missing or invalid secret key. Send it as \"Authorization: Bearer sk_…\".",
"requestId": "FZn-uhymjoEEJow="
}{
"error": true,
"code": "account_suspended",
"message": "This account is suspended. Settle the outstanding invoice in the Print.App dashboard.",
"requestId": "FZn-uhymjoEEJow="
}{
"error": true,
"code": "not_found",
"message": "Not found.",
"requestId": "FZn-uhymjoEEJow="
}{
"error": true,
"code": "unsupported_media_type",
"message": "Send the request body as JSON, with \"Content-Type: application/json\".",
"requestId": "FZn-uhymjoEEJow="
}{
"message": "Too Many Requests"
}{
"error": true,
"code": "internal_error",
"message": "Something went wrong on our side. Retry the request; if it keeps failing, contact support with the requestId.",
"requestId": "FZn-uhymjoEEJow="
}Authorizations
A secret key from Print.App admin → Domains → Secret keys, sent as Authorization: Bearer sk_…. Server-side only.
Headers
Makes a retry safe: a second request with the same key and the same body gets the first response back (for 24 hours) instead of creating the resource again. Use a new key, such as a UUID, for every new request.
1 - 255Body
A new design with blank pages.
Trim width.
Trim height.
The design's name. Default New design.
1 - 200The unit for width, height, bleed and safeMargin, and the unit the design is measured in afterwards.
in, mm, cm, pt, px, ft How many pages.
1 <= x <= 200A title per page, for example ["Front", "Back"]. Default Page 1, Page 2, …
200100Bleed on every edge, outside the trim.
x >= 0Safe margin on every edge, inside the trim.
x >= 0The design folder to create it in. Default root, the top level.
1 - 200Labels for finding it again.
501 - 50Response
Created.
A design (template) your customers start from. Open it in the editor with new PrintAppClient({ designId }).
"design"The designId to pass to PrintAppClient.
The unit the design is measured in: mm, cm, in, pt, px or ft.
Show child attributes
Show child attributes
The connectors the design runs on the product page.
The resource profiles that limit what its editor offers.
The PDF profile its print PDF is made with; null: its own settings.
The settings this design sets for itself, over the store's (see GET /v2/settings). Settings it doesn't set follow the store.
Show child attributes
Show child attributes