CR80 PARTNER INTEGRATION
Integrate CR80 into your website
Connect the CR80 editor to your website with an iframe. Find configuration, JavaScript examples and APIs for receiving and using CR80 designs in your system.
HTTP workflow for AI agents (English) · JSON Schema v1 · Example design
- After approval, open the partner workspace and sign in with the verified email address from your application. Claim your invitation there.
- Open partner settings. Configure your brand, exact HTTPS origins and physical card catalogue. Each material and technology is a separate SKU.
- Replace YOUR_PARTNER_ID in the examples with the partner ID from settings. This is a public identifier. Licence keys and API secrets are used only on the server.
- In test mode, previews carry the PROVPERIOD watermark and the editor emits cr80-test-design. Production APIs become available when the partner has active production access.
Embed the editor
Add your website origin, including the scheme and any non-default port, in partner settings. The page embedding the editor must match an approved origin. Use HTTPS in production.
<iframe id="cr80-editor"
src="https://cr80.se/editor?partner=YOUR_PARTNER_ID&embed=1"
title="Card editor"
style="width:100%;height:760px;border:0"
></iframe>The partner selects branding, catalogue and capabilities. Browser embedding does not grant account access. CR80 accounts and partner customer accounts remain separate.
Receive a design safely
The editor sends the design to the host page using postMessage. The example filters by CR80 origin, iframe window, partner ID and message type. The message contains name and design. Test mode uses cr80-test-design with test: true; active production access uses cr80-design with test: false.
const frame = document.getElementById("cr80-editor");
const partnerId = "YOUR_PARTNER_ID";
window.addEventListener("message", (event) => {
if (event.origin !== "https://cr80.se") return;
if (event.source !== frame.contentWindow) return;
const message = event.data;
if (!message || message.partner !== partnerId) return;
if (message.type === "cr80-test-design" && message.test === true) {
// Test-mode completion uses a separate message type.
document.getElementById("result").textContent = "Test design received";
return;
}
if (message.type !== "cr80-design" || message.test !== false) return;
// message.design contains the versioned CR80 design document.
// Pass it to your backend to continue your integration.
document.getElementById("result").textContent = message.name;
});The JavaScript example applies only to communication between the iframe and host page in the browser. The server APIs below use standard HTTP requests and JSON and are independent of programming language.
Create a result element on your page: <p id="result" role="status"></p>. The example displays the design name in this element. The message transfers a design and does not create an order. Validation and any order processing take place in your server integration.
APIs and the design contract
| Endpoint | Purpose |
|---|---|
| GET /api/partner/config?id=ID | Brand, approved origins, capabilities and access mode. |
| GET /api/partner/catalog?id=ID | Physical card SKUs and public availability. |
The design format is versioned JSON. Saving and reopening a design uses the complete document, including its version and any extension fields. Measurements use millimetres and monetary amounts use integer öre. The selected SKU links the design to the partner’s material, technology and finishing options.
CR80 rendering uses the same design format for previews and production files. Production rendering is part of the server integration.
Signed launches, managed customer identities, production rendering and SPI use scoped server credentials. They are separate from the iframe integration and are enabled per partner. The partner ID provides identification, not authentication.
Render a design file using the API
An exported .cr80.json file is the design object sent in the design field. These APIs accept JSON, not multipart uploads. Neither an open editor nor a local printer is needed for PNG previews or PDF exports.
Server authentication
The APIs use HTTPS and JSON and can be called from any server-side language. Examples show the method, path, headers and JSON directly, without an SDK or a specific runtime. CR80 enables machine access for an active partner organization with a version 1 production contract. This is separate from the public iframe configuration.
Choose X-CR80-Contract per API using the table. The machine credential stays on the server. Approved iframe origins do not grant browser access to these server APIs.
| Endpoint | X-CR80-Contract | Response |
|---|---|---|
| POST /api/production/preview | print-station-v1 | PNG image |
| GET /api/production/export-profiles | print-export-v1 | JSON containing profiles |
| POST /api/production/exports | print-export-v1 | JSON containing a download URL |
| GET /api/production/exports/{id} | print-export-v1 | ZIP containing PDF and production data |
Authentication headers
The base URL is https://cr80.se. Replace YOUR_PARTNER_ID and YOUR_MACHINE_CREDENTIAL with your server credentials. Send the complete design file JSON object in design. The examples use a small name card; also replace white-pvc with your card SKU. Your HTTP client serializes the JSON and handles transport headers such as Content-Length. Allow up to 180 seconds for rendering.
X-CR80-Contract: print-station-v1
X-CR80-Partner: YOUR_PARTNER_ID
X-License-Key: YOUR_MACHINE_CREDENTIALPNG preview
POST /api/production/preview returns image/png with HTTP 200. The preview is rendered at 100 dpi using CR80’s shared renderer. The response is not cached and the request does not save a design. Test mode adds the PROVPERIOD watermark.
| Field | Description |
|---|---|
| schemaVersion | Required. The API contract version, always 1. The design’s own version is in design.version. |
| design | Required. The complete JSON object from the design file. |
| renderedAt | Required. An ISO 8601 UTC timestamp, such as 2026-09-21T12:00:00.000Z. Fixes time-dependent fields during rendering. |
| side | Optional: front or back. Defaults to front. |
| row | Optional object containing column names and string values for the displayed card. Use the column names bound in the design. |
| rowIndex / rowCount | Optional: zero-based row index and total row count. Defaults are 0 and 1. Pass the actual row separately in row. |
POST /api/production/preview HTTP/1.1
Host: cr80.se
X-CR80-Contract: print-station-v1
X-CR80-Partner: YOUR_PARTNER_ID
X-License-Key: YOUR_MACHINE_CREDENTIAL
Content-Type: application/json
{
"schemaVersion": 1,
"design": {
"version": 1,
"name": "Example card",
"orientation": "portrait",
"baseCardSku": "white-pvc",
"front": {
"background": "#ffffff",
"layers": [
{
"id": "name",
"type": "text",
"x": 6,
"y": 15,
"widthMm": 42,
"fontSizeMm": 4,
"text": "{name}"
}
]
}
},
"side": "front",
"row": {
"name": "Sample Person"
},
"rowIndex": 0,
"rowCount": 2,
"renderedAt": "2026-09-21T12:00:00.000Z"
}Response
HTTP/1.1 200 OK
Content-Type: image/png
Cache-Control: private, no-store
[binary PNG body]Save the binary response body as a PNG file. Set side to back for the reverse side. For multiple cards, send one request per side and row; set row, rowIndex and rowCount to match your data table.
PDF export
1. Retrieve an export profile
The partner’s export profile defines PDF/X-4 or PDF/X-1a:2001, the CMYK/ICC profile, bleed, crop marks and page order. Configure it under Partner workspace → Print files. GET /api/production/export-profiles returns only the authenticated partner’s active profiles.
GET /api/production/export-profiles HTTP/1.1
Host: cr80.se
X-CR80-Contract: print-export-v1
X-CR80-Partner: YOUR_PARTNER_ID
X-License-Key: YOUR_MACHINE_CREDENTIALThe response is an object containing profiles. Each entry includes id, revision, profile, iccSha256 and card. The profile object includes sku, standard and pageOrder. Without profileId, export selects the active profile for design.baseCardSku. With profileId, selection is pinned to a profile revision; a stale revision returns 409.
2. Prepare the export JSON
The rows field contains exactly the cards to include, one object per card. Values are strings and keys match the design’s bound fields. For two identical cards without data fields, use [{}, {}]. The API does not automatically select rows from the design file’s embedded data table.
[
{
"name": "Sample Person"
},
{
"name": "Another Person"
}
]| Field | Description |
|---|---|
| schemaVersion | Required. The API contract version, always 1. The design’s own version is in design.version. |
| design | Required. The complete JSON object from the design file. |
| requestKey | Required UUID identifying the export. Reuse the same key and JSON when retrying. |
| rows | Required: 1–100 objects containing string values. Each object produces one card; the export profile determines which sides are included. |
| profileId | Optional UUID from the profile’s id. Omit it to select automatically using design.baseCardSku. |
| renderedAt | Required. An ISO 8601 UTC timestamp, such as 2026-09-21T12:00:00.000Z. Fixes time-dependent fields during rendering. |
Generate a new UUID in requestKey for each new export and set the rendering timestamp in renderedAt. Replace the example values below for a new export. Store the request in your system so the complete JSON, including its key and timestamp, can be reused for retries.
3. Create and download the print file
POST /api/production/exports returns HTTP 200 with id, downloadUrl, ticket and expiresAt when the export is ready. Exporting does not start a print job or create an order.
POST /api/production/exports HTTP/1.1
Host: cr80.se
X-CR80-Contract: print-export-v1
X-CR80-Partner: YOUR_PARTNER_ID
X-License-Key: YOUR_MACHINE_CREDENTIAL
Content-Type: application/json
{
"schemaVersion": 1,
"requestKey": "5dc49711-acb9-4a92-8ed6-b6f9d0617625",
"design": {
"version": 1,
"name": "Example card",
"orientation": "portrait",
"baseCardSku": "white-pvc",
"front": {
"background": "#ffffff",
"layers": [
{
"id": "name",
"type": "text",
"x": 6,
"y": 15,
"widthMm": 42,
"fontSizeMm": 4,
"text": "{name}"
}
]
}
},
"rows": [
{
"name": "Sample Person"
},
{
"name": "Another Person"
}
],
"renderedAt": "2026-09-21T12:00:00.000Z"
}Example response (selected fields; ticket omitted)
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: private, no-store
{
"id": "export-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"downloadUrl": "/api/production/exports/export-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"expiresAt": "2026-09-22T12:00:00.000Z"
}Download the ZIP file
Use the path in the response’s downloadUrl for the next GET request to https://cr80.se, with the same print-export-v1 authentication. Save the binary response body as a ZIP file and read print.pdf from it.
GET /api/production/exports/export-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa HTTP/1.1
Host: cr80.se
X-CR80-Contract: print-export-v1
X-CR80-Partner: YOUR_PARTNER_ID
X-License-Key: YOUR_MACHINE_CREDENTIALHTTP/1.1 200 OK
Content-Type: application/zip
Cache-Control: private, no-store
[binary ZIP body]The ZIP contains print.pdf, production.json and LAS-MIG.txt. Ticket and production.json describe the frozen profile revision, page-to-row mapping, geometry and file hashes. The download URL is private, requires authentication and is valid for 24 hours as specified by expiresAt.
Retries and limits
On timeout or a transient failure, resend the same POST request with unchanged JSON. An identical retry returns the original export even if the profile has since changed. Changed JSON under the same requestKey returns 409. An expired export returns 410 and requires a new request with a new key.
The maximum request size is 32 MB. PDF exports allow up to 100 cards and a 100 MB PDF. Preview allows 60 requests/minute; PDF export allows 10 writes and 120 reads/minute per organization and server process. One PDF preparation runs at a time per server process. On 429, wait before resending the same request.
The PDF contract does not support UV/holographic panels, magnetic or chip encoding, spot colors, PDF/VT or press-sheet imposition. Such input is rejected or falls outside this API.
Responses and errors
Error responses are JSON containing error. Some also include code, issues or agreementUrl. Clients should use the HTTP status and any code rather than parse the localized error message.
| Status | Description |
|---|---|
| 400 | Invalid JSON, design or request size. |
| 401 | Missing or invalid authentication, including an incorrect contract header. |
| 403 | Insufficient access, an untrusted origin or production not activated (PARTNER_PRODUCTION_NOT_ACTIVE). |
| 404 | The export does not exist in the authenticated organization. |
| 409 | The request key was reused with different content, or the export profile is stale or missing. |
| 410 | The export has expired or been erased. |
| 415 | POST requires Content-Type: application/json. |
| 422 | The design could not be rendered or does not match the export profile. PDF validation errors may include issues. |
| 428 | The organization’s current data-processing agreement is missing (PROCESSOR_AGREEMENT_REQUIRED). The response provides agreementUrl. |
| 429 | The request limit has been reached or the PDF renderer is busy. |
| 503 | The agreement service is temporarily unavailable (PROCESSOR_AGREEMENT_UNAVAILABLE). |
Example 422 response
{
"error": "Designen uppfyller inte tryckeriets krav.",
"issues": [
"Kort 1 saknar data i kolumnerna: name."
]
}Organization export and switching
A verified owner or administrator can download a free export under Account → Organization export. Export remains available after commercial expiry and archival. You do not need a new subscription or a new agreement to retrieve existing data.
- Designs and handovers
- Versioned CR80 JSON, embedded images/fonts, variants and data rows. Only designs explicitly bound to the organization; handover snapshots belong to the sending organization, claimed copies to the receiving account.
- Partner configuration
- Branding, allowed origins, card catalogue, channel/provider revisions and PDF export profiles. ICC bytes are base64 with their SHA-256.
- Production history
- Submitted order designs and rows, deliveries, station configuration, immutable job payloads, per-card acknowledgements and recovery instructions. Provider-only orders exclude another seller’s retail pricing and invoices.
- Billing and agreements
- The organization’s billing account, subscriptions, invoice lines, invoice PDF bytes (base64), partner invoices/settlements, DPA source documents and acceptance evidence, and the accepted partner offer.
Format and boundaries
Numbered ZIP parts contain UTF-8 JSON pages and a SHA-256 manifest. Dimensions are millimetres and monetary amounts integer öre. Keep all parts. Each page is read consistently, but the full export is not a database snapshot: pause edits for a final transfer. Rows created after the export cutoff are omitted; edits and deletions can affect unread pages. Hardware reports reflect the time of each page.
Excluded: passwords, API/station/OAuth credentials, other organizations’ data, personal designs, customer-owned claimed copies, CR80 software and standard templates, transient browser sessions, expired shares and temporary production files. External URLs remain references; files stored only in a browser, partner system or external URL must be transferred from their owner. Existing print-PDF downloads retain their own 24-hour lifetime. Exporting source data does not create new production files or release print jobs.
HTTP interface
These account endpoints require the owner’s or administrator’s CR80 browser session. Partner machine credentials cannot export an entire organization. GET /api/account/organization-export lists authorized organizations (including archived ones), categories and the cutoff timestamp. POST the following JSON to /api/account/organizations/{organizationId}/export with Content-Type: application/json, the exact CR80 Origin and X-CR80-Data-Action: export-organization.
{
"action": "page",
"category": "designs",
"after": "",
"cutoff": "2026-09-21T12:00:00.000Z",
"runId": "8c987cf9-6a43-433b-9e88-c9ed0bc984f0"
}Use a new UUID and the returned cutoff. Follow nextCursor as after until null, for every category. The response has records, receiptId and X-Export-SHA256 for the exact response bytes. Pages hold up to 50 records/8 MiB, allowing one larger record up to 64 MiB; oversized records need assisted export. The limit is 120 requests/minute per account and server process. Retry the same cursor on 429/503; compare checksums because an intervening edit can change the result.
Category identifiers and exact fields
- organization
- id, name, archived_at, created_at, updated_at
- members
- id, user_id, role, created_at
- designs
- id, user_id, name, design, project_id, revision, project_metadata, created_at, updated_at
- shares
- id, design_id, name, design, expires_at, revoked_at, created_at
- quotes
- id, retail, terms_version, target_working_days, expires_at, created_at
- usage
- id, event, origin, created_at
- handovers
- id, source_design_id, source_revision, recipient_email, customer_label, name, snapshot, expires_at, revoked_at, claimed_at, created_at
- partners
- id, name, config_version, logo_url, theme, allowed_origins, portal_url, pricing_url, catalog_url, pricing_visibility, capabilities, production_contract, fulfillment, fulfillment_label, destination_type, order_email, pricing, terms_url, design_guide_url, active, created_at
- catalogue
- id, partner_id, slug, name, technology, subtype, color, color_name, surcharge_ore, stock_quantity, oversell, active, sort_order, created_at
- channels
- id, legacy_partner_id, enabled, current_revision, created_at, updated_at
- channel_revisions
- id, branded_channel_id, revision, snapshot, created_at
- providers
- id, visibility, current_revision, created_at, updated_at
- provider_revisions
- id, fulfilment_provider_id, revision, snapshot, created_at
- export_profiles
- id, partner_id, sku, revision, profile, icc_sha256, icc_base64, created_at
- orders
- id, partner_id, commercial_channel, design_name, design, data_csv, quantity, status, price_ore, partner_order_ref, partner_status, tracking_url, customer_email, customer_name, shipping_address, terms_accepted_at, terms_version, created_at
- fulfilment_orders
- id, design_name, design, data_csv, quantity, partner_order_ref, partner_status, tracking_url, shipping_address, created_at
- stations
- id, name, partner_id, service_version, last_seen_at, revoked_at, created_at, updated_at
- printers
- id, station_id, instance_id, display_name, configuration, report, health, last_seen_at
- encoders
- id, station_id, instance_id, display_name, kind, connection, health, last_seen_at
- jobs
- id, station_id, printer_instance_id, payload, state, created_at, updated_at
- acknowledgements
- id, job_id, card_id, payload, created_at
- recoveries
- id, job_id, card_id, payload, state, created_at, applied_at
- billing_accounts
- id, legal_name, organization_number, vat_number, invoice_email, invoice_reference, billing_address, currency, billing_enabled, terms_accepted_at, terms_version, created_at, updated_at
- subscriptions
- id, catalog_item_id, status, cadence, current_period_start, current_period_end, trial_ends_at, cancel_at_period_end, ended_at, unit_ore_snapshot, vat_basis_points_snapshot, entitlement_snapshot, created_at, updated_at
- subscription_history
- id, subscription_id, event_type, occurred_at, previous_status, next_status, previous_period_start, previous_period_end, next_period_start, next_period_end, cancel_at_period_end, ended_at, created_at
- invoices
- id, original_invoice_id, document_number, kind, state, payment_state, currency, total_ore, vat_ore, issue_date, due_date, pdf_base64, pdf_sha256, created_at
- invoice_lines
- id, invoice_id, position, description, quantity, unit_list_ore, list_ore, discount_ore, vat_base_ore, vat_basis_points, vat_ore, total_ore, created_at
- partner_invoices
- id, partner_id, month, status, editor_loads, designs_sent, order_count, order_value_ore, license_ore, commission_ore, created_at, updated_at
- settlements
- id, order_id, amount_ore, currency, status, provider_reference, created_at, updated_at
- agreements
- id, snapshot_id, legal_entity_name, organization_number, country_code, accepted_by_name, accepted_by_email, accepted_by_role, authority_confirmed, accepted_at
- agreement_documents
- id, document_id, version, sha256, title, markdown, source_url, captured_at
- partner_acceptance
- partner_id, accepted_at, pilot_ends_at, acceptance, approved_at
After saving and checking a part, POST {action: "confirm", receipts: [{id: receiptId, sha256: responseHash}]} (at most 100 receipts). CR80 retains metadata-only preparation and recipient-confirmation evidence, not an extra copy of the customer’s content. Confirmation can be retried safely.
Switching and termination
For an assisted transfer, a large record, a final consistent snapshot or erasure, contact contact@premex.se with your organization ID and desired outcome. CR80 verifies your authority and the recipient, records the scope, timing and receipt, and provides secure transfer assistance. Do not email cardholder data or credentials. Billing termination, data retrieval and erasure are separate steps; archived source data is not automatically erased. The partner agreement and DPA govern timing, return, erasure and any required legal retention.