Current section
Files
Jump to
Current section
Files
README.md
# DocRaptor
Elixir client for the [DocRaptor](https://docraptor.com) HTML-to-PDF and XLS API.
Prefer `document_content` (with inlined CSS/assets) over `document_url` when
developing against localhost — DocRaptor cannot fetch private hosts without a
tunnel. See [Development Testing & Localhost Servers](https://docraptor.com/documentation/article/1986775-development-testing-localhost-servers).
## Installation
```elixir
def deps do
[
{:docraptor, "~> 0.1.0"}
]
end
```
## Usage
Built on [Req](https://hex.pm/packages/req). High-level helpers cover DocRaptor’s
create/status/download/expire API; advanced callers can attach to a
`%Req.Request{}` directly.
```elixir
{:ok, client} = DocRaptor.Client.new(api_key: "YOUR_API_KEY")
# test: true by default — watermarked, free quota
{:ok, %DocRaptor.Document{body: pdf, num_pages: pages}} =
DocRaptor.create_doc(client, %{
name: "hello.pdf",
document_type: :pdf,
document_content: "<html><body>Hello</body></html>"
})
{:ok, %DocRaptor.AsyncJob{status_id: status_id}} =
DocRaptor.create_async_doc(client, %{
name: "hello.pdf",
document_type: :pdf,
document_content: "<html><body>Hello</body></html>"
})
{:ok, document} = DocRaptor.await_async_doc(client, status_id)
```
### Low-level Req pipeline
```elixir
Req.new(method: :post, url: "/docs", json: body, decode_body: false)
|> DocRaptor.Client.attach(client)
|> Req.request()
```
Set `test: false` on the client (or per document) for production documents.
## API surface
| DocRaptor HTTP API | Client |
| --- | --- |
| `POST /docs` | `DocRaptor.create_doc/2` |
| `POST /async_docs` | `DocRaptor.create_async_doc/2` |
| `POST /hosted_docs` | `DocRaptor.create_hosted_doc/2` |
| `POST /hosted_async_docs` | `DocRaptor.create_hosted_async_doc/2` |
| `GET /status/:id` | `DocRaptor.get_async_doc_status/2` |
| `GET /download/:id` | `DocRaptor.get_async_doc/2` |
| `PATCH /expire/:id` | `DocRaptor.expire/2` |
| poll + download | `DocRaptor.await_async_doc/3` |
| custom Req | `DocRaptor.Client.attach/2` |
Document attrs are passed through to DocRaptor after validating `name`,
`document_type`/`type`, and `document_content`/`document_url`. That includes
every [API parameter](https://docraptor.com/documentation/api/parameters)
(`javascript`, `pipeline`, `referrer`, `callback_url`, `tag`, hosted limits,
`prince_options`, …).
## PDF tutorial parity
Official [PDF tutorials](https://docraptor.com/documentation/pdf_generation/tutorials)
are HTML/CSS/JS (plus a few `prince_options`). There are no extra Elixir
endpoints to implement — if the request body can express it, this client can
send it.
| Tutorial | What you send |
| --- | --- |
| [CSS Flexbox](https://docraptor.com/documentation/tutorial/css-flexbox) | Flexbox CSS in `document_content` |
| [Custom Fonts](https://docraptor.com/documentation/tutorial/custom-fonts) | `@font-face` CSS (Typekit: also `javascript: true` + `referrer`) |
| [Custom Page Size](https://docraptor.com/documentation/tutorial/custom-page-size) | `@page { size: ... }` CSS |
| [Highcharts Chart](https://docraptor.com/documentation/tutorial/highcharts-chart) | Chart HTML/JS + `javascript: true` |
| [HTML and JavaScript](https://docraptor.com/documentation/tutorial/html-and-javascript) | Script in content + `javascript: true` |
| [Image-Based Watermark](https://docraptor.com/documentation/tutorial/image-based-watermark) | Image + Prince `@prince-overlay` / `flow` CSS (`test: false`) |
| [Page Numbers](https://docraptor.com/documentation/tutorial/page-numbers) | `@page` + `counter(page)` / `counter(pages)` CSS |
| [Print Protection](https://docraptor.com/documentation/tutorial/print-protection) | `prince_options: %{encrypt: true, disallow_print: true}` |
| [Printer's Marks](https://docraptor.com/documentation/tutorial/printers-marks) | Prince marks CSS in content |
| [QR Code](https://docraptor.com/documentation/tutorial/qr-code) | QR HTML/image/JS in content (`javascript: true` if JS-generated) |
| [Rotated Text & Images](https://docraptor.com/documentation/tutorial/rotated-text-images) | CSS `transform` in content |
| [Table of Contents](https://docraptor.com/documentation/tutorial/table-of-contents) | Prince TOC / heading CSS in content |
| [Text-Based Watermark](https://docraptor.com/documentation/tutorial/text-based-watermark) | Text + `@prince-overlay` / `flow` CSS (`test: false`) |
| [Vector Images](https://docraptor.com/documentation/tutorial/vector-images) | SVG (or similar) in content |
### Example: page numbers (CSS)
Mirrors [How to create a PDF with Page Numbers](https://docraptor.com/documentation/tutorial/page-numbers):
```elixir
{:ok, client} = DocRaptor.Client.new(api_key: "YOUR_API_KEY")
html = """
<div style="page-break-after: always;">Page 1</div>
<div style="page-break-after: always;">Page 2</div>
<div style="page-break-after: always;">Page 3</div>
<div id="page4" style="page-break-after: always;">Page 4, with reset page counter</div>
<style>
@page {
@bottom {
content: "Page " counter(page, upper-alpha) " of " counter(pages, decimal);
}
}
#page4 {
counter-reset: page 1;
}
</style>
"""
{:ok, %DocRaptor.Document{body: pdf}} =
DocRaptor.create_doc(client, %{
name: "page-numbers.pdf",
document_type: :pdf,
document_content: html
})
File.write!("page-numbers.pdf", pdf)
```
### Example: print protection (`prince_options`)
Mirrors [How to create a PDF with Print Protection](https://docraptor.com/documentation/tutorial/print-protection):
```elixir
{:ok, client} = DocRaptor.Client.new(api_key: "YOUR_API_KEY")
{:ok, %DocRaptor.Document{body: pdf}} =
DocRaptor.create_doc(client, %{
name: "print-protection.pdf",
document_type: :pdf,
document_content: "You can't print me!",
prince_options: %{
encrypt: true,
disallow_print: true
}
})
File.write!("print-protection.pdf", pdf)
```
### Example: JavaScript chart (`javascript: true`)
Same pattern as the [Highcharts](https://docraptor.com/documentation/tutorial/highcharts-chart)
and [HTML + JavaScript](https://docraptor.com/documentation/tutorial/html-and-javascript)
tutorials — put the script in the HTML, enable DocRaptor’s JS engine:
```elixir
{:ok, client} = DocRaptor.Client.new(api_key: "YOUR_API_KEY")
html = """
<div id="container" style="width: 600px; height: 400px;"></div>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script>
Highcharts.chart("container", {
title: { text: "Fruit consumption" },
series: [{ name: "Jane", data: [1, 0, 4] }]
});
</script>
"""
{:ok, %DocRaptor.Document{body: pdf}} =
DocRaptor.create_doc(client, %{
name: "highcharts.pdf",
document_type: :pdf,
document_content: html,
javascript: true,
ignore_console_messages: true,
pipeline: "10.1"
})
File.write!("highcharts.pdf", pdf)
```
Other tutorial knobs that pass through the same way:
```elixir
# DocRaptor JS engine (charts / most page JS) — preferred default
javascript: true
# Prince JS engine (canvas / PDF-specific JS) — different engine; avoid enabling both
prince_options: %{javascript: true, max_passes: 3, media: "print"}
# Hosted async + callback
DocRaptor.create_hosted_async_doc(client, %{
name: "report.pdf",
document_type: :pdf,
document_content: html,
callback_url: "https://example.com/docraptor/callback",
hosted_download_limit: 25,
hosted_expires_at: "2026-12-31T23:59:59Z",
tag: "invoices"
})
```
See [Usage](docs/usage.md) for attrs, errors, sync/async/hosted choice, and pitfalls
(including when DocRaptor’s watermark tutorials use `test: false`).
## Docs
- HexDocs: https://hexdocs.pm/docraptor
- Agent/integrator reference: [Usage](docs/usage.md) (also on HexDocs)
- DocRaptor API parameters: https://docraptor.com/documentation/api/parameters
- DocRaptor PDF tutorials: https://docraptor.com/documentation/pdf_generation/tutorials