Skip to main content

Keyline’s open REST API

Create and manage permissions, with examples and additional endpoints

Written by Patric

You can find the official documentation for both of our APIs here:
​

​

The Inbox API lets you create an order in Keyline from a system such as a Web2Print shop, using defined product templates.
A virtual shopping cart is filled, and checkout then creates an order in Keyline directly with the data and products you defined.


You can then use the Advanced API to make further settings.

You can create and manage new API keys in the admin area under Accounts/API permissions.

The keys are needed to connect third-party applications such as Pipedrive, make.com, CRM systems and more.

Once you have created a new API key using the “Create API access permission” button, you can share it with the service provider and revoke it again at any time.

Caution: API keys created this way have access to all resources in your Keyline account. You can also restrict API keys to specific organizations, so they can act only on behalf of that organization. To do this, create the API key directly in the organization (Sales > Organization).

Keys that are no longer needed should be revoked immediately.
Each API key also counts towards the total number of users.

Please note that a revoked key cannot be reactivated.


Here are some additional examples, in chronological order, that are not yet included in the official API documentation:

You can use your browser’s search with Strg+F or CMD+F to search for keywords. 🔎

This takes you straight to the endpoint or function you need.


📦 Print runs – define print quantities per variant

This API section lets you define actual print runs (print quantities) per product variant, similar to the option available in the user interface (UI).

Method

Endpoint

Description

GET

/production/products/:product_id/circulations

List all circulations for a product

GET

/production/products/:product_id/circulations/:id

Retrieve a single circulation

PATCH

/production/products/:product_id/circulations/:id

Update the actual_amount of a circulation

​📤 Example payload:
​

{
"circulation":{
"actual_amount": 32
}
}

📄 Job bags, delivery notes & labels

You can generate various production and logistics documents as PDFs via the API.

Method

Endpoint

Description

GET

/production/products/:product_id/job_bag.pdf

Job bag (PDF as JSON link)

GET

/logistics/shipments/:shipment_id/delivery_note.pdf

Delivery note (PDF as JSON)

GET

/logistics/shipments/:shipment_id/proforma_invoice.pdf

Pro forma invoice

GET

/logistics/parcels/:parcel_id/label.pdf

Parcel label (PDF link)

Use the same endpoints with the following header:

Accept: application/pdf

Method

Endpoint

Description

GET

/production/products/:product_id/job_bag

Direct job bag PDF

GET

/logistics/shipments/:shipment_id/delivery_note

Direct delivery note PDF

GET

/logistics/shipments/:shipment_id/proforma_invoice

Pro forma invoice PDF

GET

/logistics/parcels/:parcel_id/label

Parcel label PDF

GET

/logistics/outsourcings/:outsourcing_id

Outsourcing Slip PDF

GET

/accounting/customer_invoices/:invoice_id

Invoice PDF

If you only need a shipment’s metadata, you can query, for example,
`logistics/shipments/{shipment_ID/.


📘 Material presets:

Material presets can be stored at different levels:

Method

Endpoint

Description

GET/POST

/conception/products/:product_id/components/:component_id/material_presets

Material presets for a specific component

GET/POST

/conception/products/:product_id/components/:component_id/finishings/:finishing_id/material_presets

Material presets for a finishing within a component

GET/POST

/conception/products/:product_id/material_presets

Material presets at product level

GET/POST

/conception/products/:product_id/finishings/:finishing_id/material_presets

Material presets at product → finishing level

GET/POST

/conception/products/:product_id/packagings/:packaging_id/material_presets

Material preset for packaging

📤 Example payload:

{
"material_preset": {
"material_id": 1
}
}

📦 Packaging workflow (step by step)

To automate the packaging process, follow these steps:

1. Create a packaging entry

POST /conception/products/{product_id}/packagings

2. Define packaging details (e.g. label type, destination, etc.)

PATCH /conception/products/{product_id}/packagings/{packaging_id}

3. Create pick instructions (which items should be packaged)

POST /conception/products/{product_id}/packagings/{packaging_id}/picks

👉 If there are several versions or packaging units, all definitions must be submitted together in a single JSON payload.

🚚 Shipping note:

If a product is to be shipped directly, the following property must be set:

"deposition": "shipment"

This skips the pick step and creates packaging that is ready for shipping straight away.

📦 Retrieve packaging units during production

To view a product’s packaging units during production, you can use the following endpoints:

GET /production/products/:id/packagings/
GET /production/products/:id/packagings/:id

🛠️ Change production resources & recalculate the estimate

These endpoints let you override preset production resources and trigger a new estimate (recalculation of the production path).


🔧 Change a production resource (e.g. a machine)

To change the production resource for a specific component:

POST /conception/products/{product_id}/production_paths/{production_path_id}/production_flow_modifications

📤 Example payload:

{
"production_flow_modification": {
"modification": "preset",
"workable_type": "component",
"workable_id": 1361413,
"stock_task_id": 6579,
"means_of_production_id": 10319
}
}
  • workable_id: corresponds to the component ID

  • means_of_production_id: the new machine or production resource

  • stock_task_id: the specific task ID within the production flow. In the admin area, https://app.keyline-mis.com/settings/stock_tasks lists all production tasks. Open a task to find its ID in the browser URL.


♻️ Recalculate the production path (product design)

After making changes, you can trigger a new estimate:

POST /conception/products/{product_id}/production_paths/{production_path_id}/conceptualize

This is not mandatory, but is recommended to update times and costs.


✂️ Enable cutting

To enable the cutting step for a particular imposition:

PATCH /conception/products/{product_id}/components/{component_id}/imposings/{imposing_id}

📤 Example payload:

{
"imposing": {
"cutting": true
}
}

📐 Adjust the folding pattern

To change the folding pattern for an imposition:

PATCH /conception/products/{product_id}/components/{component_id}/imposings/{imposing_id}

📤 Example payload:

{
"imposing": {
"default_stock_folding_pattern_id": 983
}
}

You can retrieve the available folding patterns here:

GET /configuration/stock_folding_patterns

🔄 Page arrangement options:

Value

Description

standalone

Single sheet

crossover

Contiguous page arrangement

parallel

Parallel fold (e.g. Z-fold)


🔍 Filters & search queries

Many endpoints support powerful filtering and search features using query parameters.

This lets you retrieve specific subsets of data – for example, by date range, status or keyword.

🧾 Invoices

GET /accounting/invoices?billed_from=2024-08-28&billed_to=2025-08-22

  • billed_from, billed_to – filter by invoice date

  • created_from, created_to – filter by creation date

📦 Orders

GET /sales/orders?state=draft

GET /sales/orders?created_from=2024-08-12&created_to=2024-09-12

GET /sales/orders?updated_from=2024-08-12&updated_to=2024-09-12

  • state – e.g. draft, confirmed, cancelled

  • created_from, updated_from – filter by creation or modification date

⚙️ Production tasks

GET /production/tasks?search_term=offset

GET /production/tasks?state=running

GET /production/tasks?created_from=2020-06-27&created_to=2020-06-27

GET /production/tasks?updated_from=2020-11-13&updated_to=2020-11-13

GET /production/tasks?search_term=offsetdruck&state=ready

  • search_term – keyword search (e.g. machine, process, product)

  • state – running, ready, completed, waiting_for_go, waiting_for_checkpoint, waiting_for_materials, waiting_for_outsourcing, unfulfillable_material_demand, canceled, replaced

  • created_from, updated_from – filter across the task lifecycle


✉️ Additional production information

You can attach messages to products to document internal notes or instructions.

GET /production/products/{product_id}/messages

POST /production/products/{product_id}/messages

PATCH /production/products/{product_id}/messages/{message_id}

DELETE /production/products/{product_id}/messages/{message_id}

📤 Example payload:

{
"text": "Dies ist eine Produktnotiz über die API."
}

📧 Customize the offer email

You can change the offer email’s subject and content via the API – as long as the order is still a draft.

POST /sales/orders/{order_id}/offer_mail_messages

📤 Example payload:

{
"mail_message": {
"subject": "Individueller E-Mail-Betreff über die API",
"content": "E-Mail-Inhalt über die API erstellt."
}
}

⚠️ Submitting the request sends the offer immediately with the modified email text. The order must still be in draft status.


👥 Assign a consultant or team member to an order

You can assign a user to an order and define their role (e.g. customer consultant, media designer, production employee, etc.).

POST /sales/orders/{order_id}/assignments

📤 Example payload:

{
"assignment": {
"user_id": 4033,
"role": "customer_consultant"
}
}

🎭 Available roles:

  • customer_consultant

  • sales_representative

  • media_designer

  • prepress_employee

  • production_employee

  • accounting_employee

You can find the user_id in the admin area under user management.


📎 Document callbacks (custom job bag, etc.)

Document callbacks let you replace Keyline’s standard documents (e.g. the job bag) with your own by specifying an external document URL.

POST /conception/products/{product_id}/document_callbacks

📤 Example payload:

{
"document_callback": {
"kind": "job_bag",
"url": "http://deine_dokumenten_url"
}
}

🔄 Change or delete a callback

You can also manage document callbacks during production:

PATCH /production/products/{id}/document_callbacks

DELETE /production/products/{id}/document_callbacks/{callback_id}

Or during product design:

PATCH /conception/products/{id}/document_callbacks

DELETE /conception/products/{id}/document_callbacks/{callback_id}


✅ Confirm an order (release it to production)

Use the following endpoint to release a draft order:

POST /sales/orders/{order_id}/confirm

This changes the order from “draft” to active and starts production.

📄 Download the order confirmation as a PDF

After confirmation, you can retrieve the PDF as follows:

GET /sales/orders/{order_id}/confirmation.pdf

To send the order confirmation directly through the API, use the following endpoint:

POST /sales/orders/{order_id}/order_confirmation_mail_messages/

with, for example:

{
"mail_message": {
"subject": "Betreff der Email - Test Message",
"content": "Hey! Ich dank dir für die Bestellung! Anbei findest du die AB!."
}
}

If you have subscribed to the DeepL add-on, you can also use it to translate the order confirmation directly.

"target_locale": "de"


📝 Edit the product description

To adjust the product description manually:

PATCH /conception/products/{product_id}

📤 Example payload:

{
"custom_description": "Neue Produktbeschreibung über die API!"
}

⚖️ Set the product weight manually

You can override the automatically calculated product weight manually using the following endpoint:

PATCH /conception/products/{product_id}/production_paths/{production_path_id}

📤 Example payload:

{
"weight_calculation_mode": "manual",
"product_weight": 123456
}

The product_weight value is specified in milligrams per item (e.g. 123456 = 123.456 g).


✅ Complete or cancel a product

To mark a product as fully produced:

PATCH /production/products/{product_id}/complete

This completes the product and updates its status accordingly.
To cancel the product completely:
​PATCH /production/products/{product_id}/cancel


📦 Retrieve outsourced work

List all outsourcing processes:

GET /logistics/outsourcings

This includes all externally assigned production steps managed through logistics.


📫 Announce addresses

To announce customer addresses in advance (so they can already be found through search):

POST /customer_relations/organizations/{organization_id}/address_announcements

After it has been announced, the address can be found using quick search and automatically appears in the associated organization when it is first used.


📂 Manage organization parameters via the API

In addition to an organization’s master data, you can maintain other business-related parameters in Keyline through the API. These include:

  • 💳 Payment terms (/payment_terms)

  • 📝 Additional information (/messages)

  • 🤝 Partner conditions (/affiliation_terms)

Different HTTP methods are available for each area.


💳 Payment terms

Use this endpoint to define or adjust an organization’s payment terms.

Available methods

  • GET – retrieve payment terms

  • POST – create new payment terms

  • PATCH – modify existing payment terms

  • DELETE – remove payment terms

Example endpoint

/customer_relations/organizations/{organization_ID}/payment_terms

{
"time_for_payment": 7,
"accepted_means_of_payment": null,
"time_for_first_cashback": 7,
"first_cashback_discount": 0.02,
"time_for_second_cashback": 14,
"second_cashback_discount": 0.01
}

📝 Additional information

Use /messages to store additional information about an organization

  • Individual notes for sales

  • Additional billing-related details

  • Customer-specific process notes

  • Internal notes

Available methods

  • GET – retrieve messages

  • POST – create a new message

  • PATCH – modify a message

  • DELETE – delete a message

Example endpoint

/customer_relations/organizations/{organization_ID}/messages
​
These messages can be reused in documents or in the project context, for example.


🤝 Partner conditions

Partner conditions govern commission agreements or special business relationships, for example.

Available methods

  • GET – retrieve partner conditions

⚠️ Note: Currently, only GET is available for /affiliation_terms.

Example endpoint

/customer_relations/organizations/{organization_ID}/affiliation_terms


🗂️ Retrieve actual print runs from the archive

To check a product’s actual produced quantity afterwards:

GET /archive/products/{product_id}/circulations

GET /archive/products/{product_id}/circulations/{circulation_id}

This is particularly useful for checking actual production quantities and if you have built a scenario in a tool such as make.com that proactively informs the customer when production is complete.


📦 Packaging process via the API

To automate the complete packaging process through the API, follow these steps:

1. Create a packaging unit

POST /conception/products/{product_id}/packagings

2. Define packaging details

PATCH /conception/products/{product_id}/packagings/{packaging_id}

Here you can set properties such as destination (deposition), labeling and more.

3. Create pick instructions

POST /conception/products/{product_id}/packagings/{packaging_id}/picks

This defines which items go into which packaging unit.

If you have several versions or packaging types, they must be combined in a single JSON.

👉 Note:

If the product is shipped directly, the packaging must contain the following property:

"deposition": "shipment"

In this case, no pick is required – the packaging is created directly as ready for shipping.


💸 Post-calculation and billing via the API

To complete post-calculation for a product:

PATCH /billing/products/{product_id}

🧾 Create an invoice from a completed order

Once an order has gone through post-calculation, you can create an invoice from it:

POST /accounting/customer_invoices/create_from_order?order_id={id}

Use PATCH on:

/accounting/invoices/:id to issue the invoice directly.
​

{
"invoice": {
"state": "billed"
}
}

Invoices can also be marked as billed via the API:


​PATCH on: /accounting/customer_invoices/{invoice_ID} with:

{
"paid_at": "2025-09-24"
}

If you want to mark an order as “Fully invoiced” without creating an invoice, you can do this through the API

PATCH on /sales/orders/:id/mark_fully_invoiced

To delete draft invoices through the API, send a DEL to

/accounting/customer_invoices/:id
/accounting/credit_notes/:id

🙅‍♂️ Remove a contact from an invoice or credit note

If the invoice or credit note should go only to the billing address (without a named contact):

DEL /accounting/customer_invoices/:id/contact
DEL /accounting/credit_notes/:id/contact

Did this answer your question?