Quickstart
From nothing to a PDF on your disk. Three steps, and the third one is the one that makes the file.
1. Make a credential#
Go to API access, name a credential and choose what it may do. You are shown a client id and a secret once — what we store is a SHA-256 of the secret, so nobody here can read it back to you, including us.
The API is part of Pro and Enterprise. If your account is on Free the page still explains all of this; the credential is what it will not make.
documents:read,
documents:write, or both. Scope is checked by HTTP method,
so a read credential is refused on every POST, PUT, PATCH and DELETE —
including routes that do not exist yet.2. Exchange it for a token#
Standard OAuth 2.0 client credentials. Any OAuth library does this without being told anything about us. The token lasts one hour — ask for one when you need one and keep it until it expires.
export DOCUBEND_CLIENT_ID=dbc_…
export DOCUBEND_SECRET=dbs_…
TOKEN=$(curl -s https://docubend.com/auth/oauth/token \
-d grant_type=client_credentials \
-d client_id=$DOCUBEND_CLIENT_ID \
-d client_secret=$DOCUBEND_SECRET | jq -r .access_token)
const BASE = "https://docubend.com";
const auth = await fetch(`${BASE}/auth/oauth/token`, {
method: "POST",
body: new URLSearchParams({
grant_type: "client_credentials",
client_id: process.env.DOCUBEND_CLIENT_ID,
client_secret: process.env.DOCUBEND_SECRET,
}),
});
const { access_token: TOKEN } = await auth.json();
import os, requests
BASE = "https://docubend.com"
auth = requests.post(f"{BASE}/auth/oauth/token", data={
"grant_type": "client_credentials",
"client_id": os.environ["DOCUBEND_CLIENT_ID"],
"client_secret": os.environ["DOCUBEND_SECRET"],
}, timeout=30)
auth.raise_for_status()
TOKEN = auth.json()["access_token"]
3. Make a document, and download it as a PDF#
Two calls. POST /api/v1/pdfs sets your Markdown as
real, selectable text and keeps the result as a document;
GET /api/v1/documents/<id>.pdf renders that document
as it stands right now.
The second call is not a download of a file we are holding — there is no file. Ask again after an edit and you get a different PDF, which is the right behaviour for a document and would be a bug for a blob.
ID=$(curl -s https://docubend.com/api/v1/pdfs \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"title":"Invoice 1042","markdown":"# Invoice 1042\n\n**Due 30 September.**\n\n| Item | Amount |\n| --- | --- |\n| Retainer | $2,400 |"}' \
| jq -r .document.id)
curl -s https://docubend.com/api/v1/documents/$ID.pdf \
-H "Authorization: Bearer $TOKEN" -o invoice.pdf
open invoice.pdf
import { writeFile } from "node:fs/promises";
const made = await fetch(`${BASE}/api/v1/pdfs`, {
method: "POST",
headers: { Authorization: `Bearer ${TOKEN}`,
"Content-Type": "application/json" },
body: JSON.stringify({
title: "Invoice 1042",
markdown: "# Invoice 1042\n\n**Due 30 September.**",
}),
});
if (!made.ok) throw new Error(`docubend: ${made.status}`);
const { document: doc } = await made.json();
const pdf = await fetch(doc.links.pdf,
{ headers: { Authorization: `Bearer ${TOKEN}` } });
await writeFile("invoice.pdf", Buffer.from(await pdf.arrayBuffer()));
console.log(doc.links.open); // a person can open this one in a browser
made = requests.post(f"{BASE}/api/v1/pdfs",
headers={"Authorization": f"Bearer {TOKEN}"},
json={
"title": "Invoice 1042",
"markdown": "# Invoice 1042\n\n**Due 30 September.**",
}, timeout=60)
made.raise_for_status()
doc = made.json()["document"]
pdf = requests.get(doc["links"]["pdf"],
headers={"Authorization": f"Bearer {TOKEN}"}, timeout=60)
open("invoice.pdf", "wb").write(pdf.content)
print(doc["links"]["open"]) # a person can open this one in a browser
Response
{
"ok": true,
"document": {
"id": "ba59b6ce5221411285daea90f4be16b6",
"title": "Invoice 1042",
"kind": "pdf",
"pages": 1,
"shapes": 11,
"version": 2,
"your_role": "owner",
"links": {
"self": "https://docubend.com/api/v1/documents/ba59b6ce5221411285daea90f4be16b6",
"pdf": "https://docubend.com/api/v1/documents/ba59b6ce5221411285daea90f4be16b6.pdf",
"open": "https://docubend.com/d/ba59b6ce5221411285daea90f4be16b6",
"…": "svg, png, model, mermaid"
}
}
}
Where to go next#
| What else that document can do | It is an ordinary docubend document: it opens in the editor, takes annotations and diagrams, can be shared, searched and versioned. |
| The other four things a PDF can be made from | HTML, a PNG or JPEG, somebody else's PDF, or a document model of your own. |
| Turn it into a form | Put fields on any document, send it to be filled in, and read the answers back as rows or as a spreadsheet. |