blueport Developer · All APIs
API reference

Every Blueport API.

One page for every Blueport product you can integrate with: hosts, authentication, endpoints, request and response shapes, errors and billing.

Open to everyone. Browse every page here without an account or a key. You only need credentials when you start calling an API, and you can build your integration against these docs before then.

All products

ProductAPIHostAuth
PDF2JSONPublicapi.blueport.io/v1/pdf2jsonOrganisation key
HTML2PDFPublicapi.blueport.io/v1/html2pdfOrganisation key
VECTORTrackerapp.blueport.ioSite key
Email archive (MAS)Enterprisemas.blueport.ioClient credentials
PURLEnterpriseapi.purl.id/v1Domain + key
DOCGEN, BETSTOP, CRYSTAL, PORTIANo public APIn/an/a

When you are ready to make calls: Public APIs are self-serve, so subscribe at app.blueport.io and your key is issued straight away. Enterprise APIs are set up with you during onboarding, and Blueport issues their credentials then. Until then, everything on this page is yours to read.

Conventions (PDF2JSON and HTML2PDF)

BASEhttps://api.blueport.io/v1/<product>
auth: x-api-key header one key per organisation TLS only /v1 stays stable; breaking changes ship as /v2

• Auth: send your organisation key in the x-api-key header (?api_key= also works but leaks into logs; prefer the header). The same key covers PDF2JSON and HTML2PDF. Admins view the masked key and rotate it at app.blueport.io; rotation invalidates the old key immediately.
• Responses: JSON responses are {"ok": true, "data", "meta"}. Every response carries a request_id, in the body or the x-request-id header. Quote it when you contact support.
• Errors: {"ok": false, "error", "request_id"}. 401 means a missing or bad key, 400 bad input, 413 too large, 404 an unknown route. Retry 5xx with backoff.
• Billing: both products draw from the one Blueport API credit pool. Each response reports billed_units and credits. Failed calls are never billed.
• Privacy: payloads are processed in flight and not stored. Only usage counts and timings are recorded.

PDF2JSON Public

PDF in, clean JSON out. Semantic extraction of invoices, contracts and forms with typed values and grouped entities, and no templates to maintain.

Endpoints

POST/v1/pdf2jsonExtract a PDF to JSON. Needs a key.
GET/v1/pdf2json/profilesList the built-in output profiles. Add ?schema=1 for each profile's JSON Schema. No key needed.

Request

Send the PDF one of two ways (multipart uploads are not accepted, and the limit is 8 MB):

# 1. raw PDF body
curl https://api.blueport.io/v1/pdf2json \
  -H "x-api-key: $BLUEPORT_KEY" \
  -H "content-type: application/pdf" \
  --data-binary @invoice.pdf

# 2. JSON with a base64 PDF
curl https://api.blueport.io/v1/pdf2json \
  -H "x-api-key: $BLUEPORT_KEY" \
  -H "content-type: application/json" \
  -d '{"pdf": "JVBERi0xLjQK...", "document_type": "vehicle_tax_invoice"}'
FieldDescription
pdf / pdf_base64The PDF as base64 (JSON requests).
document_typeOptional profile id; the x-document-type header works for either request style. Leave it out and the document is classified for you.
schemaOptional JSON Schema object for your own output shape. The response then reports document_type: "custom".

Built-in profiles: vehicle_sale_contract, vehicle_tax_invoice, nsw_form7_dealer_notice, nsw_registration_application, generic_document.

Response

{
  "ok": true,
  "data": { /* extracted fields, in the profile's shape */ },
  "meta": {
    "request_id": "req_…", "duration_ms": 5210,
    "pages": 2, "billed_units": 1, "credits": 10,
    "document_type": "vehicle_tax_invoice", "profile_version": 2,
    "warnings": []
  }
}

Errors

StatusMeaning
400No PDF in the request, the body is not a PDF, schema is not an object, or document_type is unknown.
401Missing or invalid key.
413PDF larger than 8 MB.
422The document could not be processed (refused).
502Extraction returned unusable output (bad_output). Safe to retry.
500Unexpected error. Retry with backoff.

Billing

1 billed unit = one document of up to 5 pages (a 12-page PDF is 3 units). Each unit is 10 credits. Failed calls bill 0.

HTML2PDF Public

HTML in, pixel-perfect PDF out, rendered by a real browser engine. Send raw HTML, an inline template with data, or the id of a stored template.

Endpoints

POST/v1/html2pdfRender a PDF.
POST/v1/html2pdf/templatesCreate a template from {name, html}. Returns 201.
GET/v1/html2pdf/templatesList your templates.
GET/v1/html2pdf/templates/{id}Get one template. ?version=n for an older version.
PUT/v1/html2pdf/templates/{id}Save {html?, name?} as a new version. Earlier versions stay unchanged.
DELETE/v1/html2pdf/templates/{id}Delete a template.
POST/v1/html2pdf/templates/{id}/previewFree render with {data?, options?, template_version?}. Returns base64 by default.

Three ways to render

# 1. raw HTML
curl https://api.blueport.io/v1/html2pdf \
  -H "x-api-key: $BLUEPORT_KEY" -H "content-type: text/html" \
  --data-binary @statement.html -o statement.pdf

# 2. inline template + data (Handlebars)
-d '{"html": "<h1>Hi {{name}}</h1>", "data": {"name": "Sam"}, "options": {"size": "A4"}}'

# 3. stored template
-d '{"template_id": "tpl_…", "template_version": 3, "data": {…}}'

html and template_id cannot be sent together. Templates support the helpers formatCurrency and formatDate.

Options

OptionDescription
sizeA4 (default), A3, A5, Letter, Legal, Tabloid, or {width, height}.
landscapeBoolean, default false.
printBackgroundBoolean, default true.
marginA CSS length or {top, right, bottom, left}. Default 14 / 14 / 16 / 14 mm.
header / footerHTML repeated on every page. {{page}} and {{pages}} become page numbers.
scale0.1 to 2.
filenameName in content-disposition. Also ?filename=.

Response

By default you get the PDF bytes, with headers x-request-id, x-pages, x-billed-units and x-credits. Add ?output=base64 (or "output": "base64") for JSON:

{ "ok": true,
  "data": { "pdf": "JVBERi0…", "pages": 3, "filename": "statement.pdf" },
  "meta": { "request_id": "req_…", "pages": 3, "billed_units": 1, "credits": 1 } }

Errors

StatusMeaning
400Empty HTML, invalid JSON, both or neither of html / template_id, a template merge error, or an invalid option.
401Missing or invalid key.
404Template or template version not found.
409Template limit reached (100 per organisation).
413Request body over 2 MB, or template HTML over 512 KB.
500Unexpected error. Retry with backoff.

Billing

1 billed unit = one render of up to 20 pages. Each unit is 1 credit. Previews, template management and failed renders are free.

VECTOR Tracker

VECTOR turns website behaviour into affinities and next-best actions in Salesforce. The public integration is the browser tracker. Affinities, actions and the Salesforce sync are configured in the portal at app.blueport.io, not through an API.

Install

Paste this before </body> on every page. Your site key (vk_…) is on the VECTOR setup screen in the portal.

<script>window.BlueportVector = { k: "vk_your_site_key" };</script>
<script async src="https://app.blueport.io/v.js"></script>

Page views are tracked automatically. From your own code:

BlueportVector.track("brochure_download");   // custom event
BlueportVector.identify("sam@example.com"); // link the visitor to a known contact

Endpoints

GEThttps://app.blueport.io/v.jsThe tracker script.
POSThttps://app.blueport.io/collectEvent intake, called by the tracker. You only need it for server-side events.
FieldDescription
kSite key (required).
vidVisitor id (bpv_…), set by the tracker.
eEvent name. Default pageview.
u, t, rPage URL, page title, referrer.
emEmail, sent after identify().
ts, lang, tz, sw, shTimestamp, language, time zone, screen width and height.
/collect always answers 200 {"ok": true}, even for an invalid key, so the tracker never breaks your page. Check events arrive on the VECTOR screen in the portal. Each site key accepts up to 36,000 events an hour; events over that are dropped. Events are kept for 90 days.

Email archive (MAS) Enterprise

Every email sent from Marketing Cloud is archived as a PDF against the subscriber. Your systems (a contact centre, a customer portal) can list a subscriber's archived emails and fetch each PDF. Your client_id and client_secret are issued when the archive is set up for you.

Endpoints

POSThttps://mas.blueport.io/authExchange client credentials for an access token.
GEThttps://mas.blueport.io/files/subscriber/{subscriber_key}List a subscriber's archived emails, newest first.
GEThttps://mas.blueport.io/files/v2/id/{id}Download one archived email as a PDF.

1. Get a token

curl https://mas.blueport.io/auth \
  -H "content-type: application/json" \
  -d '{"client_id": "…", "client_secret": "…"}'

{ "access_token": "eyJ…", "expires_in": 3600 }

Tokens last one hour. Send them as Authorization: Bearer <token>.

2. List a subscriber's emails

curl "https://mas.blueport.io/files/subscriber/0035g00000AbCdE?page_size=50" \
  -H "Authorization: Bearer $TOKEN"

{ "items": [ { "bp_file_key": "…", "bp_date_sent": "2026-10-14T09:12:00Z",
               "bp_signed_url": "https://…", "mc_*": "send attributes…" } ],
  "next": "…" }

Paging: page_num and page_size (default 1000); follow next / prev. bp_signed_url is a short-lived direct download link.

Errors

StatusMeaning
400Invalid JSON or parameters.
401Bad or inactive credentials, or a missing or expired token.
404File not found.
503Temporarily unavailable. Retry after the Retry-After header.

Archiving itself needs no code from you: Blueport connects your Marketing Cloud account to the archive during onboarding.

PURL Enterprise

Personalised short links for Marketing Cloud sends, on purl.id or your own branded domain. Each subscriber gets a stable short link per long URL, so clicks are attributed to the person. Your domain and API key are issued during onboarding.

Endpoint

POSThttps://api.purl.id/v1/shortenCreate or return the short link for a subscriber and URL.

All inputs are sent as request headers, which suits AMPscript HTTPPost:

HeaderDescription
domainYour short-link domain (required).
api_keyYour PURL key (required).
long_urlThe destination URL (required).
subscriber_keyThe Marketing Cloud subscriber key (required).
utm_*, mc_*Optional tracking values, stored with the link as sent.
curl -X POST https://api.purl.id/v1/shorten \
  -H "domain: go.example.com" -H "api_key: $PURL_KEY" \
  -H "long_url: https://example.com/offer" -H "subscriber_key: 0035g00000AbCdE"

https://go.example.com/aB3dE9x

The response is the short URL as plain text. The same long_url and subscriber_key always return the same link.

Errors

StatusMeaning
400Missing domain, long_url or subscriber_key.
401Invalid key for this domain.
404Unable to process your request. Any other failure; retry once, then contact support.

Products without a public API Portal & managed

ProductHow you use it
DOCGENDocument generation built into your Marketing Cloud sends. Set up and run by Blueport for each customer.
BETSTOPA Journey Builder activity that checks the National Self-Exclusion Register before each send. You add it to a journey; there is nothing to call.
CRYSTALSalesforce org health scans, run from the portal at app.blueport.io.
PORTIABlueport's AI agents, delivered as a managed service.

Need programmatic access to any of these? Tell us what you are building.

Support

Person-to-person, included with every plan: portia@blueport.io. Include the request_id from the response. Keys, usage and billing live at app.blueport.io.