Skip to main content
Glama

Lulu Print MCP Server

by devlimelabs
openapi_public.yml385 kB
openapi: 3.0.0 servers: - url: https://api.lulu.com description: Production server, uses live data - url: https://api.sandbox.lulu.com description: Sandbox server, uses test data info: description: | # Getting Started The Lulu Print API allows you to use [Lulu](https://www.lulu.com/) as your production and fulfillment network. The API provides access to the same functionality that Lulu uses internally to normalize files and send Print-Jobs to our production partners around the world. The Lulu Print API is a **RESTful API** that communicates with JSON encoded messages. Communication is secured with **OpenID Connect** and **transport layer security** (HTTPS). Working with the API requires intermediate level programming skills and a general understanding of web APIs. Check out Lulu's **[printing and fulfillment](https://www.lulu.com/sell)** options without having to do technical work upfront. ## Registration You have to create an account to start using the Lulu Print API. Your account will automatically receive a client-key and a client-secret. ## Sandbox Environment The API is available in a production and a sandbox environment. The sandbox can be used for development and testing purposes. Print-Jobs created on the sandbox will never be forwarded to a real production and can be paid for with test credit cards. To access the sandbox, you have to create a separate account at [https://developers.sandbox.lulu.com/](https://developers.sandbox.lulu.com/). The sandbox API endpoint URL is `https://api.sandbox.lulu.com/`. ## Authorization The Lulu API uses [OpenID Connect](https://en.wikipedia.org/wiki/OpenID_Connect), an authentication layer built on top of [OAuth 2.0](https://en.wikipedia.org/wiki/OAuth). Instead of exchanging username and password, the API uses [JSON Web Token (JWT)](https://en.wikipedia.org/wiki/JSON_Web_Token) to authorize client requests. To interact with the API you need a **client-key** and a **client-secret**. Open the [Client Keys & Secret](https://developers.lulu.com/user-profile/api-keys) ([Sandbox](https://developers.sandbox.lulu.com/user-profile/api-keys)) page to generate them. <img src="https://api.lulu.com/api-docs/assets/keyAndSecretExample.png"> ## Generate a Token To interact with the API you first have to generate an OAuth token. This requires the following parameters: * `client_key` * `client_secret` * `grant-type` must be set to `client_credentials` You have to send a POST request to the token endpoint a special Authorization header. For your convenience, you can copy the authorization string directly from your [API Keys](https://developers.lulu.com/user-profile/api-keys) page: ```bash curl -X POST https://api.lulu.com/auth/realms/glasstree/protocol/openid-connect/token \ -d 'grant_type=client_credentials' \ -H 'Content-Type: application/x-www-form-urlencoded' \ -H 'Authorization: Basic ZjJjNDdmMTctOWMxZi00ZWZlLWIzYzEtMDI4YTNlZTRjM2M3OjMzOTViZGU4LTBkMjQtNGQ0Ny1hYTRjLWM4NGM3NjI0OGRiYw==' ``` The request will return a JSON response that contains an `access_token` key: ```json { "access_token":"eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkI...", "expires_in":3600, "refresh_expires_in":604800, "refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6...", "token_type":"bearer", "not-before-policy":0, "session_state":"a856fb91-eafc-460e-8f6a-f09325062c88" } ``` Store this `access_token` and use it to authorize all further requests. The token will expire after a few minutes, but you can always request a fresh token from the server as outlined above. We recommend to use an OAuth capable client lib in your favorite programming language to simplify working with client credentials and tokens. Some might even automatically refresh your token after it expired. ## Make authenticated requests To authenticate subsequent API requests, you must provide a valid access token in the HTTP header of the request: `Authorization: Bearer {access_token}`: ```bash curl -X GET https://api.lulu.com/{some_api_endpoint}/ \ -H 'Authorization: Bearer {access_token}' \ -H 'Content-Type: application/json' ``` ## Select a Product Lulu's Print API offers a wide range of products. Each product is represented by a 27 character code call **pod_package_id**: > Trim Size + Color + Print Quality + Bind + Paper + PPI + Finish + Linen + Foil = **pod_package_id** Here are a few examples: | pod_package_id | Description | | --- | --- | | `0850X1100BWSTDLW060UW444MNG` | `0850X1100`: trim size 8.5” x 11”<br>`BW`: black-and-white<br>`STD`: standard quality <br>`LW`: linen wrap binding<br>`060UW444`: 60# uncoated white paper with a bulk of 444 pages per inch <br>`M`: matte cover coating <br>`N`: navy colored linen<br>`G`: golden foil stamping | | `0600X0900FCSTDPB080CW444GXX` | `0600X0900`: trim size 6” x 9” <br>`FC`: full color<br>`STD`: standard quality<br>`PB`: perfect binding<br>`080CW444`: 80# coated white paper with a bulk of 444 ppi<br>`G`: gloss cover coating<br>`X`: no linen<br>`X`: no foil| | `0700X1000FCPRECO060UC444MXX` | 7" x 10" black-and-white premium coil-bound book printed on 60# cream paper with a matte cover | | `0600X0900BWSTDPB060UW444MXX` | 6" x 9" black-and-white standard quality paperback book printed on 60# white paper with a matte cover | Use the [Pricing Calculator](https://developers.lulu.com/price-calculator) to input your product specifications and generate a SKU for your product. Once a price is calculated, the SKU will be available in the Your Selection area. For a full listing of Lulu SKUs and product specification, download the [Product Specification Sheet](https://assets.lulu.com/media/specs/lulu-print-api-spec-sheet.xlsx). Also, please download and review our [Production Templates](https://developers.lulu.com/products-and-shipping#production-templates) for additional guidance with formatting and file preparation. If you have general questions about which Lulu products are right for your business, please [contact one of our experts](https://help.api.lulu.com) through our Technical Support form. ## Validate files ### Validate interior file Print API allows you to validate your interior file without creating a Print-Job. Interior validation requires publicly exposed URL to download and validate a file. File validation is being done asynchronously, it may take a while, so to retrieve validation result, use GET endpoint. File validation result may return different statuses: * `NULL` - file validation is not started yet * `VALIDATING` - file validation is still running * `VALIDATED` - file validation finished without any errors * `NORMALIZING` - file normalization (next step of validation, available only if `pod_package_id` is was passed in the payload) is still running * `NORMALIZED` - file normalization finished without any errors * `ERROR` - file is invalid, list of errors is included in the response So there are 3 possible final statuses of validation: * `VALIDATED` - validation succeeded * `NORMALIZED` - validation succeeded, possible only if `pod_package_id` was added to the payload * `ERROR` - validation failed Example reasons of `ERROR` status: * invalid PDF file * not enough pages - at least 2 pages are required * different sizes of pages * fonts not embedded * corrupted images Applicable reasons should be included in `errors` field in the file validation response. You can find the detailed endpoints documentation in [interior validation section](#operation/Validate-Interior_create). ### Calculate cover dimensions You can also calculate required cover dimensions basing on interior data by using [cover dimensions](#operation/Cover-Dimensions_create) endpoint. This endpoint returns cover width and height in requested unit (print points by default). ### Validate cover file As it was possible with interior file, Print API also allows you to validate cover files. Just as interior validation, cover validation requires publicly exposed URL to download and validate a file. Other required attributes are POD package ID of your book and interior page count to correctly validate cover file. Also in this case, file validation is being done asynchronously, it may take a while, so to retrieve validation result, use GET endpoint. File validation result may return different statuses: * `NULL` - file validation is not started yet * `NORMALIZING` - file validation is still running * `NORMALIZED` - file validation finished without any errors * `ERROR` - file is invalid, list of errors is included in the response Example reasons of `ERROR` status: * invalid PDF file * invalid file size Applicable reasons should be included in `errors` field in the file validation response. You can find the detailed endpoints documentation in [cover validation section](#operation/Validate-Cover_create). ## Create a Print-Job Now you can start to create Print-Jobs. A Print-Job request consists of at least three data fields: * `line_items` **(required)**: the list of books that shall be printed * `shipping_address` **(required)**: the (end) customer’s address where Lulu should send the books - including a phone number. * `contact_email` **(required)**: an email address for questions regarding the Print-Job - normally, you want to use the email address of a developer or shop owner, not the end customer * `shipping_level`**(required)**: Lulu offers five different quality levels for shipping: * `MAIL` - Slowest ship method. Depending on the destination, tracking might not be available. * `PRIORITY_MAIL` - priority mail shipping * `GROUND` - Courier based shipping using ground transportation in the US. * `EXPEDITED` - expedited (2nd day) delivery via air mail or equivalent * `EXPRESS` - overnight delivery. Fastest shipping available. * `external_id` (optional): a reference number to link the Print-Job to your system (e.g. your order number) The **shipping address must contain a phone number**. This is required by our shipping carriers. If the shipping address does not contain a phone number, the default phone number from the account will be used. If neither the account nor the shipping address contain a phone number, the Print-Job can not be created. You can find the detailed documentation for [Creating a new Print-Job](#) below. ## Check Print-Job Status After sending a Print-Job, you can check its status. Normally, a Print-Job goes through the following stages: <img src="https://api.lulu.com/api-docs/assets/print-job-stages.svg"> * **CREATED**: Print-Job created * **UNPAID**: Print-Job can be paid * **PAYMENT_IN_PROGRESS**: Payment is in Progress * **PRODUCTION_DELAYED**: Print-Job is paid and will move to production after the mandatory production delay. * **PRODUCTION_READY**: Production delay has ended and the Print-Job will move to "in production" shortly. * **IN_PRODUCTION**: Print-Job submitted to printer * **SHIPPED**: Print-Job is fully shipped There are a few more status that can occur when there is a problem with the Print-Job: * **REJECTED**: When there is a problem with the input data or the file, Lulu will reject a Print-Job with a detailed error message. Please [contact our experts](https://help.api.lulu.com) if you need help in resolving this issue. * **CANCELED**: You can cancel a Print-Job as long as it is “unpaid” using an API request to the status endpoint. In rare cases, Lulu might also cancel a Print-Job if a problem has surfaced in production and the order cannot be fulfilled. ## Shipping Notification Once an order has been shipped, Lulu will provide tracking information in the Print-Job and Print-Job Status endpoint. Example shipped response: ```json { "name": "SHIPPED", "message": "All line-items were shipped", "changed": "2024-04-10T09:28:34.870842Z", "line_item_statuses": [ { "name": "SHIPPED", "messages": { "tracking_id": "3d4a53da-cc42-44c2-b47b-c3da8fa37491_1", "tracking_urls": [ "https://api.sandbox.lulu.com/printer-wannabe-tracking/3d4a53da-cc42-44c2-b47b-c3da8fa37491_1" ], "carrier_name": "Carrier" }, "line_item_id": 57999 } ], "print_job_id": 42776 } ``` ## Webhooks > **You can subscribe to receive webhooks on the following topics:** > * **PRINT_JOB_STATUS_CHANGED** To subscribe to webhooks, create a webhook configuration by calling <a href="#operation/subscribe-webhooks" target="_blank">this </a> endpoint. You have to select topics that you want to subscribe to and the URL where webhooks should be sent. You can create multiple webhooks, but the URL has to be unique for each of them. Once you created a webhook configuration, you can retrieve a <a href="#operation/retrieve-webhooks" target="_blank">list</a> of owned webhook or <a href="#operation/retrieve-webhook" target="_blank"> single webhook</a> to check data: * id * topics * URL * is_active It can be <a href="#operation/update-webhook" target="_blank">updated</a>, for example, if you want to update the URL, list of subscribed topics or activate it after automatic deactivation. It can be also <a href="#operation/delete-webhook" target="_blank">deleted</a> - this operation cannot be undone. Once the webhook configuration is created, you should start receiving webhooks depending on topics that you are subscribed to. Each submission payload contains 2 fields: * topic * data - depends on the topic Each webhook submission has calculated HMAC - a request payload signed with webhook's owner API secret. HMAC is sent in `Lulu-HMAC-SHA256` header. HMAC is calculated with API secret as a key (UTF-8 encoded), payload as a message (UTF-8 encoded) and SHA-256 as hash function. To validate HMAC, it should be calculated using *raw response data* - parsing it to JSON can cause formatting issues. If a webhook submission fails for any reason (connection error, HTTP error, etc.), it is retried 5 times. After 5 different failed submissions in a row, the webhook is deactivated (`is_active` field is set to `false`). It can be activated back by updating it. There is an option to test webhook submission by calling <a href="#operation/test-webhook-submission" target="_blank">test</a> endpoint. It sends dummy data of the selected topic to configured URL. All webhooks submissions can be retrieved by calling <a href="#operation/retrieve-webhook-submissions" target="_blank">this</a> endpoint. It returns all submissions created during the last 30 days. ### PRINT_JOB_STATUS_CHANGED topic PRINT_JOB_STATUS_CHANGED webhook is sent every time owned print job status is updated. The data sent in the payload is print job data, the same as returned by <a href="#operation/Print-Jobs_read" target="_blank">print job details </a> endpoint. title: Universal Publishing Platform API version: v1 x-logo: url: https://api.lulu.com/api-docs/assets/logo-lulu-api.svg altText: LULU API logo paths: /print-job-cost-calculations/: post: description: This endpoint allows you to calculate product and shipping cost without creating a Print-Job. Typically used in an offer or checkout situation. The address is required to calculate sales tax / VAT and shipping cost. operationId: Print-Job-cost-calculations_create requestBody: content: application/json: schema: description: A Print-Job Cost Calculation represents a price calculation for multiple print job line items properties: line_items: description: The line items that should be calculated items: description: A Print-Job Cost Calculation Line Item represents a price calculation for a print job line item properties: page_count: description: The page count of the book type: integer writeOnly: true pod_package_id: description: The id of the PodPackage of the book type: string writeOnly: true quantity: description: The quantity of printables to base the calculations on format: int32 type: number writeOnly: true required: - quantity - pod_package_id - page_count type: object type: array writeOnly: true shipping_address: description: The shipping address for calculating Print-Job cost properties: city: type: string country_code: description: '[ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) country code' maxLength: 2 minLength: 2 type: string email: format: email type: string is_business: default: false description: Only relevant for US addresses. Some US carriers don't deliver to business-addresses on Saturday. type: boolean name: description: Full name of the person, including first and last name. type: string organization: description: Name of an organization. Required if no person name is given. type: string phone_number: description: "Validation Regex Pattern: `^\\+?[\\d\\s\\-.\\/()]{8,20}$`\n" maxLength: 20 type: string postcode: description: Required for most countries maxLength: 64 type: string state_code: description: 2 or 3 letter state codes (officially called [ISO-3166-2 subdivision codes](https://en.wikipedia.org/wiki/ISO_3166-2)). They are required for some countries (e.g. US, MX, CA, AU) type: string street1: description: First address line type: string street2: description: Second address line type: string title: enum: - MR - MISS - MRS - MS - DR type: string required: - street1 - city - country_code - postcode - phone_number type: object writeOnly: true shipping_option: description: The shipping option level enum: - MAIL - PRIORITY_MAIL - GROUND_HD - GROUND_BUS - GROUND - EXPEDITED - EXPRESS type: string writeOnly: true required: - shipping_option - shipping_address - line_items type: object examples: Shipping Express to Germany: value: line_items: - page_count: 32 pod_package_id: 0600X0900BWSTDPB060UW444MXX quantity: 20 - page_count: 324 pod_package_id: 0425X0687BWSTDPB060UW444GXX quantity: 200 shipping_address: city: Lübeck country_code: DE postcode: '23552' state_code: street1: Holstenstr. 40 phone_number: 844-212-0689 shipping_option: EXPRESS Shipping Mail to United Kingdom: value: line_items: - page_count: 120 pod_package_id: 0827X1169BWPRELW080CW444MGG quantity: 5 shipping_address: city: Wetherby country_code: GB postcode: LS22 6LL street1: Lucky Garden, 11, West Gate phone_number: +44 113 496 0000 shipping_option: MAIL responses: 201: content: application/json: schema: description: Summary of the costs of a Print-Job properties: shipping_address: description: The shipping address of the customer. properties: city: type: string country_code: description: '[ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) country code' maxLength: 2 minLength: 2 type: string email: format: email type: string description: "Shipping carriers require an email address for notifications or handling delivery issues. If no email is given, the default email in the user profile will be used.\n" is_business: default: false description: Only relevant for US addresses. Some US carriers don't deliver to business-addresses on Saturday. type: boolean name: description: Full name of the person, including first and last name. type: string organization: description: Name of an organization. Required if no person name is given. type: string phone_number: description: "Shipping carriers require a phone number for handling delivery issues. If no phone number is given, the default in the API user profile will be used. Validation Regex Pattern for phone numbers `^\\+?[\\d\\s\\-.\\/()]{8,20}$`\n" maxLength: 20 type: string postcode: description: Required for most countries maxLength: 64 type: string state_code: description: 2 or 3 letter state codes (officially called [ISO-3166-2 subdivision codes](https://en.wikipedia.org/wiki/ISO_3166-2)). They are required for some countries (e.g. US, MX, CA, AU) type: string street1: description: First address line type: string street2: description: Second address line type: string title: enum: - MR - MISS - MRS - MS - DR type: string warnings: description: Warnings found during address validation readOnly: true type: array items: properties: type: description: Type of warning type: string readOnly: true code: description: Warning code which describe what was suggested by validation type: string readOnly: true path: description: Describes the validation origin of warning type: string readOnly: true message: description: Warning message with suggested change type: string readOnly: true suggested_address: description: Suggested address returned by shipping address validation readOnly: true type: object properties: country_code: description: Suggested country code type: string readOnly: true state_code: description: Suggested state code type: string readOnly: true postcode: description: Suggested postal code type: string readOnly: true city: description: Suggested city type: string readOnly: true street1: description: Suggested first address line type: string readOnly: true street2: description: Suggested second address line type: string readOnly: true currency: description: Currency for the costs readOnly: true type: string line_item_costs: description: List of cost summaries for each line item items: description: Costs for a Print-Job line item properties: cost_excl_discounts: description: Per unit cost without any discounts applied as a decimal string readOnly: true type: string discounts: description: Discounts applied to this line item items: properties: amount: description: The deducted amount as a decimal string readOnly: true type: string description: description: Description of the discount readOnly: true type: string required: - amount - description type: object readOnly: true type: array quantity: description: The quantity of printables to base the calculations on format: int32 readOnly: true type: number tax_rate: description: The tax rate applied to the line as a decimal string readOnly: true type: string total_cost_excl_discounts: description: The total line price without any discounts applied as a decimal string readOnly: true type: string total_cost_excl_tax: description: The total line price including discounts excluding tax as a decimal string readOnly: true type: string total_cost_incl_tax: description: The total line price including discounts and taxes as a decimal string readOnly: true type: string total_tax: description: The total line tax amount as a decimal string readOnly: true type: string unit_tier_cost: description: Per unit cost with tier discount applied, null for list price (non-tier) customers readOnly: true type: string required: - quantity - cost_excl_discounts - cost_excl_tax - tax_rate - discounts - total_cost_excl_discounts - total_tax - total_cost_excl_tax - total_cost_incl_tax type: object readOnly: true type: array shipping_cost: description: Summary of the combined shipping and handling costs properties: tax_rate: description: Tax rate that was applied on shipping and handling costs as a decimal string readOnly: true type: string total_cost_excl_tax: description: Total shipping and handling costs excluding taxes as a decimal string readOnly: true type: string total_cost_incl_tax: description: Total shipping and handling costs including taxes as a decimal string readOnly: true type: string total_tax: description: Total amount of taxes on shipping and handling as a decimal string readOnly: true type: string readOnly: true type: object fulfillment_cost: description: Summary of the fulfillment fee costs type: object readOnly: true properties: total_cost_excl_tax: description: Total fulfillment fee costs excluding taxes as a decimal string type: string readOnly: true total_cost_incl_tax: description: Total fulfillment fee costs including taxes as a decimal string type: string readOnly: true total_tax: description: Total amount of taxes on fulfillment fee as a decimal string type: string readOnly: true tax_rate: description: Tax rate that was applied on fulfillment fee costs as a decimal string total_cost_excl_tax: description: Total costs of the job excluding taxes as a decimal string readOnly: true type: string total_cost_incl_tax: description: Total costs of the job including taxes as a decimal string readOnly: true type: string total_discount_amount: description: The total discount amount as a decimal string readOnly: true type: string total_tax: description: Total amount of taxes on the job as a decimal string readOnly: true type: string fees: description: All fees applied to Print Job readOnly: true type: array items: properties: currency: description: Print Job Fee currency type: string readOnly: true fee_type: description: Print Job Fee type type: string readOnly: true sku: description: Print Job Fee unique sku type: string readOnly: true tax_rate: type: string description: The tax rate applied to the fee as a decimal string readOnly: true total_cost_excl_tax: type: string description: The total fee rate excluding tax as a decimal string readOnly: true total_cost_incl_tax: type: string description: The total fee rate including tax as a decimal string readOnly: true total_tax: type: string description: The total fee rate tax amount as a decimal string readOnly: true readOnly: true required: - shipping_cost - line_item_costs - total_cost_excl_tax - total_cost_incl_tax - total_discount_amount - total_tax - currency type: object example: shipping_address: city: Lübeck country_code: DE is_business: false name: Hans Dampf phone_number: 844-212-0689 postcode: '23552' state_code: '' street1: Holstenstr. 40 street2: '' warnings: type: validation_warning path: external code: REPLACED message: 'street1: Holstenstr. 40 -> Holstenstraße 40' suggested_address: country_code: DE state_code: postcode: 23552 city: Lübeck street1: Holstenstraße 40" street2: currency: USD fees: - currency: USD fee_type: HANDLING_FEE sku: HANDLING_FEE tax_rate: '0.060000' total_cost_excl_tax: '14.00' total_cost_incl_tax: '14.84' total_tax: '0.84' - currency: USD fee_type: FULFILLMENT_FEE sku: FULFILLMENT_FEE tax_rate: '0.060000' total_cost_excl_tax: '0.75' total_cost_incl_tax: '0.80' total_tax: '0.05' fulfillment_cost: tax_rate: '0.06' total_cost_excl_tax: '0.75' total_cost_incl_tax: '0.80' total_tax: '0.05' line_item_costs: - cost_excl_discounts: '2.55' discounts: [] quantity: 20 tax_rate: '0.060000' total_cost_excl_discounts: '51.00' total_cost_excl_tax: '51.00' total_cost_incl_tax: '54.06' total_tax: '3.06' unit_tier_cost: - cost_excl_discounts: '9.26' discounts: - amount: '92.60' description: Volume Discount 5% quantity: 200 tax_rate: '0.060000' total_cost_excl_discounts: '1852.00' total_cost_excl_tax: '1759.40' total_cost_incl_tax: '1864.96' total_tax: '105.56' unit_tier_cost: shipping_cost: tax_rate: '0.06' total_cost_excl_tax: '318.44' total_cost_incl_tax: '337.55' total_tax: '19.11' total_cost_excl_tax: '2129.59' total_cost_incl_tax: '2257.37' total_discount_amount: '92.60' total_tax: '127.78' description: Created 400: $ref: '#/components/responses/BadRequest' 401: $ref: '#/components/responses/Unauthorized' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' security: - oauth2: [] summary: Create a Print-Job cost calculation tags: - Print-Job Cost Calculations x-code-samples: - lang: Python source: | import requests import json url = "https://api.lulu.com/print-job-cost-calculations/" payload = json.dumps({ "line_items": [ { "page_count": 32, "pod_package_id": "0600X0900BWSTDPB060UW444MXX", "quantity": 20 }, { "page_count": 324, "pod_package_id": "0425X0687BWSTDPB060UW444GXX", "quantity": 200 } ], "shipping_address": { "city": "Washington", "country_code": "US", "postcode": "20540", "state_code": "DC", "street1": "101 Independence Ave SE", "phone_number": "+1 206 555 0100" }, "shipping_option": "EXPRESS" }) headers = { 'Authorization': 'Check Authentication menu', 'Cache-Control': 'no-cache', 'Content-Type': 'application/json' } response = requests.request("POST", url, headers=headers, data=payload) print(response.text) - lang: Ruby source: | require "uri" require "json" require "net/http" url = URI("https://api.lulu.com/print-job-cost-calculations/") https = Net::HTTP.new(url.host, url.port) https.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = "Check Authentication menu" request["Cache-Control"] = "no-cache" request["Content-Type"] = "application/json" request.body = JSON.dump({ "line_items": [ { "page_count": 32, "pod_package_id": "0600X0900BWSTDPB060UW444MXX", "quantity": 20 }, { "page_count": 324, "pod_package_id": "0425X0687BWSTDPB060UW444GXX", "quantity": 200 } ], "shipping_address": { "city": "Washington", "country_code": "US", "postcode": "20540", "state_code": "DC", "street1": "101 Independence Ave SE", "phone_number": "+1 206 555 0100" }, "shipping_option": "EXPRESS" }) response = https.request(request) puts response.read_body - lang: Node source: | var request = require('request'); var options = { 'method': 'POST', 'url': 'https://api.lulu.com/print-job-cost-calculations/', 'headers': { 'Authorization': 'Check Authentication menu', 'Cache-Control': 'no-cache', 'Content-Type': 'application/json' }, body: JSON.stringify({ "line_items": [ { "page_count": 32, "pod_package_id": "0600X0900BWSTDPB060UW444MXX", "quantity": 20 }, { "page_count": 324, "pod_package_id": "0425X0687BWSTDPB060UW444GXX", "quantity": 200 } ], "shipping_address": { "city": "Washington", "country_code": "US", "postcode": "20540", "state_code": "DC", "street1": "101 Independence Ave SE", "phone_number": "+1 206 555 0100" }, "shipping_option": "EXPRESS" }) }; request(options, function (error, response) { if (error) throw new Error(error); console.log(response.body); }); - lang: Java source: | Unirest.setTimeouts(0, 0); HttpResponse<String> response = Unirest.post("https://api.lulu.com/print-job-cost-calculations/") .header("Authorization", "Check Authentication menu") .header("Cache-Control", "no-cache") .header("Content-Type", "application/json") .body("{\n \"line_items\": [\n {\n \"page_count\": 32,\n \"pod_package_id\": \"0600X0900BWSTDPB060UW444MXX\",\n \"quantity\": 20\n },\n {\n \"page_count\": 324,\n \"pod_package_id\": \"0425X0687BWSTDPB060UW444GXX\",\n \"quantity\": 200\n }\n ],\n \"shipping_address\": {\n \"city\": \"Washington\",\n \"country_code\": \"US\",\n \"postcode\": \"20540\",\n \"state_code\": \"DC\",\n \"street1\": \"101 Independence Ave SE\",\n \"phone_number\": \"+1 206 555 0100\"\n },\n \"shipping_option\": \"EXPRESS\"\n}") .asString(); - lang: Javascript source: | var myHeaders = new Headers(); myHeaders.append("Authorization", "Check Authentication menu"); myHeaders.append("Cache-Control", "no-cache"); myHeaders.append("Content-Type", "application/json"); var raw = JSON.stringify({ "line_items": [ { "page_count": 32, "pod_package_id": "0600X0900BWSTDPB060UW444MXX", "quantity": 20 }, { "page_count": 324, "pod_package_id": "0425X0687BWSTDPB060UW444GXX", "quantity": 200 } ], "shipping_address": { "city": "Washington", "country_code": "US", "postcode": "20540", "state_code": "DC", "street1": "101 Independence Ave SE", "phone_number": "+1 206 555 0100" }, "shipping_option": "EXPRESS" }); var requestOptions = { method: 'POST', headers: myHeaders, body: raw, redirect: 'follow' }; fetch("https://api.lulu.com/print-job-cost-calculations/", requestOptions) .then(response => response.text()) .then(result => console.log(result)) .catch(error => console.log('error', error)); - lang: cURL source: | curl --location 'https://api.lulu.com/print-job-cost-calculations/' \ --header 'Authorization: Check Authentication menu' \ --header 'Cache-Control: no-cache' \ --header 'Content-Type: application/json' \ --data '{ "line_items": [ { "page_count": 32, "pod_package_id": "0600X0900BWSTDPB060UW444MXX", "quantity": 20 }, { "page_count": 324, "pod_package_id": "0425X0687BWSTDPB060UW444GXX", "quantity": 200 } ], "shipping_address": { "city": "Washington", "country_code": "US", "postcode": "20540", "state_code": "DC", "street1": "101 Independence Ave SE", "phone_number": "+1 206 555 0100" }, "shipping_option": "EXPRESS" }' /print-jobs/: get: description: | Use this request to show a list of Print-Jobs. The list is paginated and can be filtered by various attributes that are given as query parameters. Timestamps like `created_after`, `created_before`, `modified_after`, and `modified_before` can be entered as [ISO8601 datetime strings](https://www.w3.org/TR/NOTE-datetime). Internally, the Lulu API uses [Coordinated Universal Time (UTC)](https://en.wikipedia.org/wiki/Coordinated_Universal_Time). The following formats are valid: * `2017-11-09` (date only) * `2017-11-09T09:30` (datetime with minute precision) * `2017-11-09T09:30:08` (datetime with second precision) * `2017-11-09T09:30:08Z` (UTC datetime) * `2017-11-09T09:30:08+06:00` (datetime with offset) To filter Print-Jobs by status you can use any valid status string (`CREATED`, `REJECTED`, `UNPAID`, `PAYMENT_IN_PROGRESS`, `PRODUCTION_READY`, `PRODUCTION_DELAYED`, `IN_PRODUCTION`, `ERROR`, `SHIPPED`, `CANCELED`). `PAYMENT_IN_PROGRESS` and `PRODUCTION_READY` are rather short-lived states that exist only for a few minutes at max; filtering by these status will rarely yield any results. operationId: Print-Jobs_list parameters: - description: 'Result page, default: 1' in: query name: page schema: type: integer - description: The default is 100. in: query name: page_size schema: type: integer - description: Filter by creation timestamp after the given ([ISO 8601](https://www.w3.org/TR/NOTE-datetime)) timestamp. in: query name: created_after required: false schema: type: string - description: Filter by creation timestamp before the given ([ISO 8601](https://www.w3.org/TR/NOTE-datetime)) timestamp. in: query name: created_before required: false schema: type: string - description: Filter by modification timestamp after the given ([ISO 8601](https://www.w3.org/TR/NOTE-datetime)) timestamp. in: query name: modified_after required: false schema: type: string - description: Filter by modification timestamp before the given ([ISO 8601](https://www.w3.org/TR/NOTE-datetime)) timestamp. in: query name: modified_before required: false schema: type: string - description: Filter by status in: query name: status required: false schema: type: string - description: Filter by id in: query name: id required: false schema: type: string - description: Filter by order_id in: query name: order_id required: false schema: type: string - description: Leave the list of line_items out of the Print-Jobs in the response. in: query name: exclude_line_items required: false schema: type: boolean - description: Search across the fields `id`, `external_id`, `order_id`, `status`, `line_item_id`, `line_item_external_id`, `line_item_title`, `line_item_tracking_id` and `shipping_address` in: query name: search required: false schema: type: string - description: Which field to use when ordering the results. in: query name: ordering required: false schema: type: string responses: 200: content: application/json: schema: properties: count: example: 1 type: integer next: example: https://api.lulu.com/resources/?page=1&page_size=1 type: string previous: example: https://api.lulu.com/resources/?page=1&page_size=1 type: string results: items: description: The job resource that represents a print order properties: contact_email: description: | Email address that should be contacted if questions regarding the Print-Job arise. Lulu recommends to use the email of a person who is responsible for placing the Print-Job like a developer or business owner. format: email type: string costs: description: Summary of the costs of a Print-Job properties: line_item_costs: description: Costs for a Print-Job line item properties: cost_excl_discounts: description: Per unit cost without any discounts applied as a decimal string readOnly: true type: string discounts: description: Discounts applied to this line item items: properties: amount: description: The deducted amount as a decimal string readOnly: true type: string description: description: Description of the discount readOnly: true type: string required: - amount - description type: object readOnly: true type: array quantity: description: The quantity of printables to base the calculations on format: int32 readOnly: true type: number tax_rate: description: The tax rate applied to the line as a decimal string readOnly: true type: string total_cost_excl_discounts: description: The total line price without any discounts applied as a decimal string readOnly: true type: string total_cost_excl_tax: description: The total line price including discounts excluding tax as a decimal string readOnly: true type: string total_cost_incl_tax: description: The total line price including discounts and taxes as a decimal string readOnly: true type: string total_tax: description: The total line tax amount as a decimal string readOnly: true type: string unit_tier_cost: description: Per unit cost with tier discount applied, null for list price (non-tier) customers readOnly: true type: string required: - quantity - cost_excl_discounts - cost_excl_tax - tax_rate - discounts - total_cost_excl_discounts - total_tax - total_cost_excl_tax - total_cost_incl_tax type: object currency: description: Currency for the costs readOnly: true type: string shipping_cost: description: Summary of the combined shipping and handling costs properties: tax_rate: description: Tax rate that was applied on shipping and handling costs as a decimal string readOnly: true type: string total_cost_excl_tax: description: Total shipping and handling costs excluding taxes as a decimal string readOnly: true type: string total_cost_incl_tax: description: Total shipping and handling costs including taxes as a decimal string readOnly: true type: string total_tax: description: Total amount of taxes on shipping and handling as a decimal string readOnly: true type: string readOnly: true type: object fulfillment_cost: description: Summary of the fulfillment fee costs type: object readOnly: true properties: total_cost_excl_tax: description: Total fulfillment fee costs excluding taxes as a decimal string type: string readOnly: true total_cost_incl_tax: description: Total fulfillment fee costs including taxes as a decimal string type: string readOnly: true total_tax: description: Total amount of taxes on fulfillment fee as a decimal string type: string readOnly: true tax_rate: description: Tax rate that was applied on fulfillment fee costs as a decimal string fees: description: All fees applied to Print Job readOnly: true type: array items: properties: currency: description: Print Job Fee currency type: string readOnly: true fee_type: description: Print Job Fee type type: string readOnly: true sku: description: Print Job Fee unique sku type: string readOnly: true tax_rate: type: string description: The tax rate applied to the fee as a decimal string readOnly: true total_cost_excl_tax: type: string description: The total fee rate excluding tax as a decimal string readOnly: true total_cost_incl_tax: type: string description: The total fee rate including tax as a decimal string readOnly: true total_tax: type: string description: The total fee rate tax amount as a decimal string readOnly: true total_cost_excl_tax: description: Total costs of the job excluding taxes as a decimal string readOnly: true type: string total_cost_incl_tax: description: Total costs of the job including taxes as a decimal string readOnly: true type: string total_tax: description: Total amount of taxes on the job as a decimal string readOnly: true type: string readOnly: true type: object estimated_shipping_dates: description: The estimated ship and delivery dates for a Print-Job properties: arrival_max: description: | The slowest estimated delivery date for a Print-Job in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601)) format readOnly: true type: string arrival_min: description: | The fastest estimated delivery date for a Print-Job in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601)) format readOnly: true type: string dispatch_max: description: | The slowest estimated ship date for a Print-Job in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601)) format readOnly: true type: string dispatch_min: description: | The fastest estimated ship date for a Print-Job in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601)) format readOnly: true type: string readOnly: true type: object external_id: description: | Arbitrary string to identify and connect a print job to your systems. Set it to an order number, a purchase order or whatever else works for your particular use case. type: string id: format: int64 readOnly: true type: number line_items: description: The line items of a Print-Job, defining it's Printables and their quantities. The property name 'items' can be used instead. items: description: The line item of a Print-Job, defining it's printable and quantity properties: cover: oneOf: - properties: source_md5_sum: description: A md5 hash of the source file to check it's integrity type: string source_url: description: The url of the source file. type: string required: - source_url type: object - description: The url of the interior source file. type: string writeOnly: true writeOnly: true description: Shorthand of the cover source definition. If used together with 'interior' , it can replace 'printable_normalization', Alternatively to both options, a 'printable_id' of an existing printable can be provided. external_id: description: Arbitrary string to identify and connect a print job to your systems. Set it to an order number, a purchase order or whatever else works for your particular use case type: string id: format: int64 readOnly: true type: number interior: oneOf: - properties: source_md5_sum: description: A md5 hash of the source file to check it's integrity type: string source_url: description: The url of the source file. type: string required: - source_url type: object - description: The url of the interior source file. type: string writeOnly: true writeOnly: true description: Shorthand of the interior source definition. If used together with 'cover' , it can replace 'printable_normalization'. Alternatively to both options, a 'printable_id' of an existing printable can be provided. page_count: description: The page count of the printable format: int32 readOnly: true type: number pod_package_id: description: The id of the PodPackage of the printable of this line item maxLength: 27 type: string printable_id: description: Id of the Printable of of this line item. It can be used instead of 'printable_normalization' / 'interior' / 'cover' format: uuid type: string printable_normalization: description: Represents the normalization processes of the interior and cover source files. Alternatively, 'interior' and 'cover' can be set as a shorthand for creation or a 'printable_id' of an existing printable can be provided. properties: cover: properties: job_id: description: The id of the normalization job (either a InteriorNormalizationJob or a CoverNormalizationJob) format: int32 type: number normalized_file: description: The resulting normalized file properties: file_id: format: int64 readOnly: true type: number filename: description: Filename of the normalized file readOnly: true type: string readOnly: true type: object source_md5_sum: description: A md5 hash of the source file to check it's integrity type: string source_url: description: The url of the source file. type: string required: - source_url type: object description: Represents the normalization process of the cover source files interior: properties: job_id: description: The id of the normalization job (either a InteriorNormalizationJob or a CoverNormalizationJob) format: int32 type: number normalized_file: description: The resulting normalized file properties: file_id: format: int64 readOnly: true type: number filename: description: Filename of the normalized file readOnly: true type: string readOnly: true type: object source_md5_sum: description: A md5 hash of the source file to check it's integrity type: string source_url: description: The url of the source file. type: string required: - source_url type: object description: Represents the normalization process of the interior source files required: - interior - cover type: object quantity: description: Quantity of printed books for this line item format: int32 type: number status: default: messages: {} name: CREATED description: Status object that contains the actual line item processing status as well as additional status related data properties: messages: description: A map of status related messages / data properties: delay: description: Expected delay in hours for error status' maxLength: 64 readOnly: true type: string error: description: General status error message readOnly: true type: string info: description: General info message on the status readOnly: true type: string printable_normalization: description: A map of printable normalization related messages / data properties: cover: description: Array of messages related to the cover file normalization items: readOnly: true type: string type: array interior: description: Array of messages related to the interior file normalization items: readOnly: true type: string type: array readOnly: true type: object timestamp: description: '[ISO 8601](https://www.w3.org/TR/NOTE-datetime)) timestamp of last status change' maxLength: 64 readOnly: true type: string tracking_urls: anyOf: - type: string - items: type: string type: array description: Tracking url(s) tracking_id: description: Tracking id for this line item's shipment readOnly: true type: string carrier_name: description: Name of the carrier handling shipment readOnly: true type: string readOnly: true type: object name: default: CREATED description: The actual processing status of the Print-Job. enum: - CREATED - ACCEPTED - REJECTED - IN_PRODUCTION - ERROR - SHIPPED type: string readOnly: true required: - name type: object title: description: The title of the line item. Should be on the cover. This field will become mandatory on October 1, 2019! maxLength: 255 type: string tracking_id: description: Tracking id for this line item's shipment readOnly: true type: string tracking_urls: description: A list of tracking urls for this line item's shipment. items: type: string readOnly: true type: array carrier_name: description: Name of the carrier handling shipment readOnly: true type: string required: - id - status - quantity type: object type: array order_id: description: Reference to the order, which this PrintJob has created readOnly: true type: string production_delay: default: 60 description: Delay before a newly created Print-Job is sent to production. Minimum is 60 minutes, maximum is 2880 minutes (=48 hours). As most cancellation requests occur right after an order has been placed, it makes sense to wait for some time before sending an order to production. Once production has started, orders cannot be canceled anymore. format: int32 maximum: 2880 minimum: 60 type: integer production_due_time: description: Target timestamp of when this job will move into production ([ISO 8601](https://www.w3.org/TR/NOTE-datetime)) format: date-time readOnly: true type: string shipping_address: description: The shipping address of the customer. properties: city: type: string country_code: description: '[ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) country code' maxLength: 2 minLength: 2 type: string email: format: email type: string description: "Shipping carriers require an email address for notifications or handling delivery issues. If no email is given, the default email in the user profile will be used.\n" is_business: default: false description: Only relevant for US addresses. Some US carriers don't deliver to business-addresses on Saturday. type: boolean name: description: Full name of the person, including first and last name. type: string organization: description: Name of an organization. Required if no person name is given. type: string phone_number: description: "Shipping carriers require a phone number for handling delivery issues. If no phone number is given, the default in the API user profile will be used. Validation Regex Pattern for phone numbers `^\\+?[\\d\\s\\-.\\/()]{8,20}$`\n" maxLength: 20 type: string postcode: description: Required for most countries maxLength: 64 type: string state_code: description: 2 or 3 letter state codes (officially called [ISO-3166-2 subdivision codes](https://en.wikipedia.org/wiki/ISO_3166-2)). They are required for some countries (e.g. US, MX, CA, AU) type: string street1: description: First address line type: string street2: description: Second address line type: string title: enum: - MR - MISS - MRS - MS - DR type: string warnings: description: Warnings found during address validation readOnly: true type: array items: properties: type: description: Type of warning type: string readOnly: true code: description: Warning code which describe what was suggested by validation type: string readOnly: true path: description: Describes the validation origin of warning type: string readOnly: true message: description: Warning message with suggested change type: string readOnly: true suggested_address: description: Suggested address returned by shipping address validation readOnly: true type: object properties: country_code: description: Suggested country code type: string readOnly: true state_code: description: Suggested state code type: string readOnly: true postcode: description: Suggested postal code type: string readOnly: true city: description: Suggested city type: string readOnly: true street1: description: Suggested first address line type: string readOnly: true street2: description: Suggested second address line type: string readOnly: true required: - name - street1 - city - country_code - postcode - phone_number - email type: object shipping_level: description: The shipping level that this Print-Job is shipped with enum: - MAIL - PRIORITY_MAIL - GROUND_HD - GROUND_BUS - GROUND - EXPEDITED - EXPRESS type: string tax_country: description: '[ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) country code of the tax country determined for this job' maxLength: 2 readOnly: true type: string required: - id - status - line_items - shipping_address - contact_email - shipping_level type: object example: contact_email: test@test.com costs: line_item_costs: shipping_cost: total_cost_excl_tax: '132.74' total_cost_incl_tax: '132.74' total_tax: '0.00' tax_rate: '0.000000' fulfillment_cost: total_cost_excl_tax: '0.75' total_cost_incl_tax: '0.81' total_tax: '0.06' tax_rate: '0.080000' fees: - currency: USD fee_type: HANDLING_FEE sku: HANDLING_FEE_6 tax_rate: '0.088750' total_cost_excl_tax: '4.00' total_cost_incl_tax: '4.36' total_tax: '0.36' total_cost_excl_tax: total_cost_incl_tax: total_tax: date_created: '2017-08-07T08:47:26.485456Z' date_modified: '2017-08-07T08:47:26.485490Z' estimated_shipping_dates: arrival_max: '2017-08-12' arrival_min: '2017-08-10' dispatch_max: '2017-08-09' dispatch_min: '2017-08-07' external_id: demo-time id: 1 line_items: - external_id: item-reference-1 id: 1 printable_id: printable_normalization: cover: job_id: normalized_file: page_count: source_file: source_md5sum: e78512c777e7f5841fe8f1992cefb898 source_url: https://www.dropbox.com/sh/p3zh22vzsaegiri/AADP367j0bTWlt8fCu-_tm2ia/161025/139056_cover.pdf?dl=1 interior: job_id: normalized_file: page_count: source_file: source_md5sum: 7f8af20c296747689756f8e310135d79 source_url: https://www.dropbox.com/sh/p3zh22vzsaegiri/AACOUn3LFKsITDzylh13bQpsa/161025/thesis2.pdf?dl=1 pod_package_id: 0600X0900BWSTDPB060UW444MXX quantity: 20 status: messages: info: Line-item is currently being validated name: CREATED title: My Book production_delay: 120 production_due_time: shipping_address: city: Lübeck country_code: DE is_business: false name: Hans Dampf phone_number: 844-212-0689 postcode: '23552' state_code: '' street1: Holstenstr. 40 street2: '' warnings: type: validation_warning path: external code: REPLACED message: 'street1: Holstenstr. 40 -> Holstenstraße 40' suggested_address: country_code: DE state_code: postcode: 23552 city: Lübeck street1: Holstenstraße 40" street2: shipping_level: MAIL shipping_option_level: MAIL status: changed: '2017-08-07T08:47:26.480493Z' message: Print-job is currently being validated name: CREATED type: array description: OK 401: $ref: '#/components/responses/Unauthorized' 403: $ref: '#/components/responses/Forbidden' security: - oauth2: [] summary: Retrieve a list of Print-Jobs tags: - Print-Jobs x-code-samples: - lang: Python source: | import requests url = "https://api.lulu.com/print-jobs/" payload = {} headers = { 'Authorization': 'Check Authentication menu', 'Cache-Control': 'no-cache' } response = requests.request("GET", url, headers=headers, data=payload) print(response.text) - lang: Ruby source: | require "uri" require "net/http" url = URI("https://api.lulu.com/print-jobs/") https = Net::HTTP.new(url.host, url.port) https.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = "Check Authentication menu" request["Cache-Control"] = "no-cache" response = https.request(request) puts response.read_body - lang: Node source: | var request = require('request'); var options = { 'method': 'GET', 'url': 'https://api.lulu.com/print-jobs/', 'headers': { 'Authorization': 'Check Authentication menu', 'Cache-Control': 'no-cache' } }; request(options, function (error, response) { if (error) throw new Error(error); console.log(response.body); }); - lang: Java source: | Unirest.setTimeouts(0, 0); HttpResponse<String> response = Unirest.get("https://api.lulu.com/print-jobs/") .header("Authorization", "Check Authentication menu") .header("Cache-Control", "no-cache") .asString(); - lang: Javascript source: | var myHeaders = new Headers(); myHeaders.append("Authorization", "Check Authentication menu"); myHeaders.append("Cache-Control", "no-cache"); var requestOptions = { method: 'GET', headers: myHeaders, redirect: 'follow' }; fetch("https://api.lulu.com/print-jobs/", requestOptions) .then(response => response.text()) .then(result => console.log(result)) .catch(error => console.log('error', error)); - lang: cURL source: | curl --location 'https://api.lulu.com/print-jobs/' \ --header 'Authorization: Check Authentication menu' \ --header 'Cache-Control: no-cache' post: description: | Print-Jobs are the core resource of the Print API. A Printjob consists of line items, shipping information and some additional metadata. ## Elements of a Print-Job ### Line Items A line item represents a book that should be printed or in short a **printable**. Printables consist of cover and interior files as well as a `pod_package_id`. The `pod_package_id` represents the manufacturing options; see the ["Select a product"](#section/Select-a-Product) section for details. Each printable can be identified by an immutable `printable_id`. The `printable_id` can be used for re-orders so that the files don''t have to be transferred again. #### Linen Wrap Foil Foil stamping is available on Hardcover Linen with Dust Jacket products only. The foil stamp is placed on the spine of your book and cannot exceed 42 characters. Lulu's foil stamping supports the following characters: * Roman Character sets (A-Z, a-z, 0-9) * [];',./!`^&*()~+=:?"]ˇ˘°´¨¸¯- ØŁ * ÀÁÃĀÄĂĆČÇĎÈÉËĒĔĚĞÌÍĨÏĪĬĽĹÑŃŇÒÓÕÖŌŎŔŘŚŞŠŢŤÙÚŨŪÜŬÝŸŹŽ * àáãäāăćčçďèéëēĕěğìíĩïīĭľĺñńňòóõöōŏŕřśşšţťùúũūüŭýÿźž Unsupported characters: - _ and all non-roman character sets (Cyrillic, Arabic, Hebrew, Farsi, Chinese, Japanese, Thai, etc.) Your linen and foil stamping color selections should be included at the end of your SKU using the following letters to indicate color, with the linen option first and the foil stamping option last: * Linen: * Navy: N * Gray: G * Red: R * Black: B * Tan: T * Forest: F * Foil: * Gold: G * Black: B * White: W For example: 0600X0900BWSTDPB060UW444M**NG** ### Shipping Information & Metadata Print-Jobs have to contain a `shipping_address` as well as a `shipping_level`. Lulu offers five different service levels that differ in speed and traceability. ### Additional Metadata A few additional metadata fields can be specified in the Print-Job as well: * `contact_email` for questions related to the Print-Job itself * `production_delay` allows you to specify a delay (between 60 minutes and 2,880 minutes) before the Print-Job goes to production. * `external_id` allows you to link the Print-Job to an internal order number or other reference. * `recipient_tax_id` is required for shipping addresses to Brazil, Chile, and Mexico. This field holds the recipient's tax identification number (CPF/CNPJ for Brazil, RUT for Chile, and RFC for Mexico). The tax ID can be provided in formatted form (with dots, dashes, or slashes), but will be standardized to a compact version without separators (e.g., "12.345.678/0001-90" will be converted to "12345678000190") for further processing. ## File Handling and Normalization Interior and cover files have to be specified with a URL from which Lulu can download the files. Using encoded [basic authentication](https://en.wikipedia.org/wiki/Basic_access_authentication#URL_encoding) in the URL is ok. All files processed by Lulu will be validated and normalized before sending them to production. If problems with the file occur, the PrintJob will be rejected or cancelled and an error message will be displayed. ## Automation and Payment After a Print-Job has been created successfully, it will remain in an `UNPAID` state until it is paid for through the developer portal. However, you can automate the process by putting a credit card on file. Then, the Print-Job will automatically transition to the `PRODUCTION_DELAY` status and your card will charged when the Print-Job is sent to production. For any questions related to alternative payment options, [contact our support team](https://help.api.lulu.com/en/support/tickets/new). operationId: Print-Jobs_create requestBody: content: application/json: schema: description: The job resource that represents a print order properties: contact_email: description: "Email address that should be contacted if questions regarding the Print-Job arise. Lulu recommends to use the email of a person who is responsible for placing the Print-Job like a developer or business owner.\n" format: email type: string costs: description: Summary of the costs of a Print-Job properties: line_item_costs: description: Costs for a Print-Job line item properties: cost_excl_discounts: description: Per unit cost without any discounts applied as a decimal string readOnly: true type: string discounts: description: Discounts applied to this line item items: properties: amount: description: The deducted amount as a decimal string readOnly: true type: string description: description: Description of the discount readOnly: true type: string required: - amount - description type: object readOnly: true type: array quantity: description: The quantity of printables to base the calculations on format: int32 readOnly: true type: number tax_rate: description: The tax rate applied to the line as a decimal string readOnly: true type: string total_cost_excl_discounts: description: The total line price without any discounts applied as a decimal string readOnly: true type: string total_cost_excl_tax: description: The total line price including discounts excluding tax as a decimal string readOnly: true type: string total_cost_incl_tax: description: The total line price including discounts and taxes as a decimal string readOnly: true type: string total_tax: description: The total line tax amount as a decimal string readOnly: true type: string unit_tier_cost: description: Per unit cost with tier discount applied, null for list price (non-tier) customers readOnly: true type: string required: - quantity - cost_excl_discounts - cost_excl_tax - tax_rate - discounts - total_cost_excl_discounts - total_tax - total_cost_excl_tax - total_cost_incl_tax type: object shipping_cost: description: Summary of the shipping costs properties: tax_rate: description: Tax rate that was applied on shipping costs as a decimal string readOnly: true type: string total_cost_excl_tax: description: Total shipping costs excluding taxes as a decimal string readOnly: true type: string total_cost_incl_tax: description: Total shipping costs including taxes as a decimal string readOnly: true type: string total_tax: description: Total amount of taxes on shipping as a decimal string readOnly: true type: string readOnly: true type: object total_cost_excl_tax: description: Total costs of the job excluding taxes as a decimal string readOnly: true type: string total_cost_incl_tax: description: Total costs of the job including taxes as a decimal string readOnly: true type: string total_tax: description: Total amount of taxes on the job as a decimal string readOnly: true type: string readOnly: true type: object estimated_shipping_dates: description: The estimated ship and delivery dates for a Print-Job properties: arrival_max: description: The slowest estimated delivery date for a Print-Job in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601)) format readOnly: true type: string arrival_min: description: The fastest estimated delivery date for a Print-Job in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601)) format readOnly: true type: string dispatch_max: description: The slowest estimated ship date for a Print-Job in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601)) format readOnly: true type: string dispatch_min: description: The fastest estimated ship date for a Print-Job in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601)) format readOnly: true type: string readOnly: true type: object external_id: description: Arbitrary string to identify and connect a print job to your systems. Set it to an order number, a purchase order or whatever else works for your particular use case. type: string id: format: int64 readOnly: true type: number line_items: description: The line items of a Print-Job, defining it's Printables and their quantities. The property name 'items' can be used instead. items: description: The line item of a Print-Job, defining it's printable and quantity properties: cover: oneOf: - properties: source_md5_sum: description: A md5 hash of the source file to check it's integrity type: string source_url: description: The url of the source file. type: string required: - source_url type: object - description: The url of the interior source file. type: string writeOnly: true writeOnly: true description: Shorthand of the cover source definition. If used together with 'interior' , it can replace 'printable_normalization', Alternatively to both options, a 'printable_id' of an existing printable can be provided. external_id: description: Arbitrary string to identify and connect a print job to your systems. Set it to an order number, a purchase order or whatever else works for your particular use case type: string id: format: int64 readOnly: true type: number interior: oneOf: - properties: source_md5_sum: description: A md5 hash of the source file to check it's integrity type: string source_url: description: The url of the source file. type: string required: - source_url type: object - description: The url of the interior source file. type: string writeOnly: true writeOnly: true description: Shorthand of the interior source definition. If used together with 'cover' , it can replace 'printable_normalization'. Alternatively to both options, a 'printable_id' of an existing printable can be provided. page_count: description: The page count of the printable format: int32 readOnly: true type: number pod_package_id: description: The id of the PodPackage of the printable of this line item maxLength: 27 type: string printable_id: description: Id of the Printable of of this line item. It can be used instead of 'printable_normalization' / 'interior' / 'cover' format: uuid type: string printable_normalization: description: Represents the normalization processes of the interior and cover source files. Alternatively, 'interior' and 'cover' can be set as a shorthand for creation or a 'printable_id' of an existing printable can be provided. properties: cover: properties: job_id: description: The id of the normalization job (either a InteriorNormalizationJob or a CoverNormalizationJob) format: int32 type: number normalized_file: description: The resulting normalized file properties: file_id: format: int64 readOnly: true type: number filename: description: Filename of the normalized file readOnly: true type: string readOnly: true type: object source_md5_sum: description: A md5 hash of the source file to check it's integrity type: string source_url: description: The url of the source file. type: string required: - source_url type: object description: Represents the normalization process of the cover source files interior: properties: job_id: description: The id of the normalization job (either a InteriorNormalizationJob or a CoverNormalizationJob) format: int32 type: number normalized_file: description: The resulting normalized file properties: file_id: format: int64 readOnly: true type: number filename: description: Filename of the normalized file readOnly: true type: string readOnly: true type: object source_md5_sum: description: A md5 hash of the source file to check it's integrity type: string source_url: description: The url of the source file. type: string required: - source_url type: object description: Represents the normalization process of the interior source files required: - interior - cover type: object quantity: description: Quantity of printed books for this line item format: int32 type: number status: default: messages: {} name: CREATED description: Status object that contains the actual line item processing status as well as additional status related data properties: messages: description: A map of status related messages / data properties: delay: description: Expected delay in hours for error status' maxLength: 64 readOnly: true type: string error: description: General status error message readOnly: true type: string info: description: General info message on the status readOnly: true type: string printable_normalization: description: A map of printable normalization related messages / data properties: cover: description: Array of messages related to the cover file normalization items: readOnly: true type: string type: array interior: description: Array of messages related to the interior file normalization items: readOnly: true type: string type: array readOnly: true type: object timestamp: description: '[ISO 8601](https://www.w3.org/TR/NOTE-datetime)) timestamp of last status change' maxLength: 64 readOnly: true type: string url: anyOf: - type: string - items: type: string type: array description: Tracking url(s) readOnly: true type: object name: default: CREATED description: The actual processing status of the Print-Job. enum: - CREATED - ACCEPTED - REJECTED - IN_PRODUCTION - ERROR - SHIPPED type: string readOnly: true required: - name type: object title: description: The title of the line item. Should be on the cover. This field will become mandatory on October 1, 2019! maxLength: 255 type: string tracking_id: description: A list of tracking ids for this line item's shipment readOnly: true type: string tracking_urls: description: A list of tracking urls for this line item's shipment. items: type: string readOnly: true type: array required: - id - status - quantity type: object type: array order_id: description: Reference to the order, which this PrintJob has created readOnly: true type: string production_delay: default: 60 description: Delay before a newly created Print-Job is sent to production. Minimum is 60 minutes, maximum is 2880 minutes (=48 hours). As most cancellation requests occur right after an order has been placed, it makes sense to wait for some time before sending an order to production. Once production has started, orders cannot be canceled anymore. format: int32 maximum: 2880 minimum: 60 type: integer production_due_time: description: Target timestamp of when this job will move into production ([ISO 8601](https://www.w3.org/TR/NOTE-datetime)) format: date-time readOnly: true type: string shipping_address: description: The shipping address of the customer. properties: city: type: string country_code: description: '[ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) country code' maxLength: 2 minLength: 2 type: string email: format: email type: string description: "Shipping carriers require an email address for notifications or handling delivery issues. If no email is given, the default email in the user profile will be used.\n" is_business: default: false description: Only relevant for US addresses. Some US carriers don't deliver to business-addresses on Saturday. type: boolean name: description: Full name of the person, including first and last name. type: string organization: description: Name of an organization. Required if no person name is given. type: string phone_number: description: "Shipping carriers require a phone number for handling delivery issues. If no phone number is given, the default in the API user profile will be used. Validation Regex Pattern for phone numbers `^\\+?[\\d\\s\\-.\\/()]{8,20}$`\n" maxLength: 20 type: string postcode: description: Required for most countries maxLength: 64 type: string state_code: description: 2 or 3 letter state codes (officially called [ISO-3166-2 subdivision codes](https://en.wikipedia.org/wiki/ISO_3166-2)). They are required for some countries (e.g. US, MX, CA, AU) type: string street1: description: First address line type: string street2: description: Second address line type: string title: enum: - MR - MISS - MRS - MS - DR type: string recipient_tax_id: description: The recipient’s tax identification number. Required for shipping addresses to Brazil, Chile, and Mexico. type: string required: - name - street1 - city - country_code - postcode - phone_number - email type: object shipping_level: description: The shipping level that this Print-Job is shipped with enum: - MAIL - PRIORITY_MAIL - GROUND_HD - GROUND_BUS - GROUND - EXPEDITED - EXPRESS type: string tax_country: description: '[ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) country code of the tax country determined for this job' maxLength: 2 readOnly: true type: string required: - id - status - line_items - shipping_address - contact_email - shipping_level type: object examples: Example Book: value: contact_email: test@test.com external_id: demo-time line_items: - external_id: item-reference-1 printable_normalization: cover: source_url: https://www.dropbox.com/s/7bv6mg2tj0h3l0r/lulu_trade_perfect_template.pdf?dl=1&raw=1 interior: source_url: https://www.dropbox.com/s/r20orb8umqjzav9/lulu_trade_interior_template-32.pdf?dl=1&raw=1 pod_package_id: 0600X0900BWSTDPB060UW444MXX quantity: 30 title: My Book production_delay: 120 shipping_address: city: Lübeck country_code: GB name: Hans Dampf phone_number: 844-212-0689 postcode: PO1 3AX state_code: '' street1: Holstenstr. 48 shipping_level: MAIL Example Linen Wrap Book: value: contact_email: test@test.com external_id: demo-time line_items: - external_id: item-reference-1 printable_normalization: cover: source_url: https://www.dropbox.com/scl/fi/7t4muts0gh4qe7833ay8b/cover_template.pdf?rlkey=0jlesya87pd9xe5k1u2l7lcws&st=75qgd5jt&dl=1 interior: source_url: https://www.dropbox.com/s/r20orb8umqjzav9/lulu_trade_interior_template-32.pdf?dl=1&raw=1 pod_package_id: 0600X0900BWPRELW060UW444MFB foil_stamp_author_text: Author name foil_stamp_title_text: My Book quantity: 5 title: My Book production_delay: 120 shipping_address: city: Lübeck country_code: GB name: Hans Dampf phone_number: 844-212-0689 postcode: PO1 3AX state_code: '' street1: Holstenstr. 48 shipping_level: MAIL responses: 201: content: application/json: schema: description: The job resource that represents a print order properties: contact_email: description: Email address that should be contacted if questions regarding the Print-Job arise. Lulu recommends to use the email of a person who is responsible for placing the Print-Job like a developer or business owner. format: email type: string costs: description: Summary of the costs of a Print-Job properties: line_item_costs: description: Costs for a Print-Job line item properties: cost_excl_discounts: description: Per unit cost without any discounts applied as a decimal string readOnly: true type: string discounts: description: Discounts applied to this line item items: properties: amount: description: The deducted amount as a decimal string readOnly: true type: string description: description: Description of the discount readOnly: true type: string required: - amount - description type: object readOnly: true type: array quantity: description: The quantity of printables to base the calculations on format: int32 readOnly: true type: number tax_rate: description: The tax rate applied to the line as a decimal string readOnly: true type: string total_cost_excl_discounts: description: The total line price without any discounts applied as a decimal string readOnly: true type: string total_cost_excl_tax: description: The total line price including discounts excluding tax as a decimal string readOnly: true type: string total_cost_incl_tax: description: The total line price including discounts and taxes as a decimal string readOnly: true type: string total_tax: description: The total line tax amount as a decimal string readOnly: true type: string unit_tier_cost: description: Per unit cost with tier discount applied, null for list price (non-tier) customers readOnly: true type: string required: - quantity - cost_excl_discounts - cost_excl_tax - tax_rate - discounts - total_cost_excl_discounts - total_tax - total_cost_excl_tax - total_cost_incl_tax type: object shipping_cost: description: Summary of the shipping costs properties: tax_rate: description: Tax rate that was applied on shipping costs as a decimal string readOnly: true type: string total_cost_excl_tax: description: Total shipping costs excluding taxes as a decimal string readOnly: true type: string total_cost_incl_tax: description: Total shipping costs including taxes as a decimal string readOnly: true type: string total_tax: description: Total amount of taxes on shipping as a decimal string readOnly: true type: string readOnly: true type: object total_cost_excl_tax: description: Total costs of the job excluding taxes as a decimal string readOnly: true type: string total_cost_incl_tax: description: Total costs of the job including taxes as a decimal string readOnly: true type: string total_tax: description: Total amount of taxes on the job as a decimal string readOnly: true type: string readOnly: true type: object estimated_shipping_dates: description: The estimated ship and delivery dates for a Print-Job properties: arrival_max: description: The slowest estimated delivery date for a Print-Job in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601)) format readOnly: true type: string arrival_min: description: The fastest estimated delivery date for a Print-Job in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601)) format readOnly: true type: string dispatch_max: description: The slowest estimated ship date for a Print-Job in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601)) format readOnly: true type: string dispatch_min: description: The fastest estimated ship date for a Print-Job in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601)) format readOnly: true type: string readOnly: true type: object external_id: description: Arbitrary string to identify and connect a print job to your systems. Set it to an order number, a purchase order or whatever else works for your particular use case. type: string id: format: int64 readOnly: true type: number line_items: description: The line items of a Print-Job, defining it's Printables and their quantities. The property name 'items' can be used instead. items: description: The line item of a Print-Job, defining it's printable and quantity properties: cover: oneOf: - properties: source_md5_sum: description: A md5 hash of the source file to check it's integrity type: string source_url: description: The url of the source file. type: string required: - source_url type: object - description: The url of the interior source file. type: string writeOnly: true writeOnly: true description: Shorthand of the cover source definition. If used together with 'interior' , it can replace 'printable_normalization', Alternatively to both options, a 'printable_id' of an existing printable can be provided. external_id: description: Arbitrary string to identify and connect a print job to your systems. Set it to an order number, a purchase order or whatever else works for your particular use case type: string id: format: int64 readOnly: true type: number interior: oneOf: - properties: source_md5_sum: description: A md5 hash of the source file to check it's integrity type: string source_url: description: The url of the source file. type: string required: - source_url type: object - description: The url of the interior source file. type: string writeOnly: true writeOnly: true description: Shorthand of the interior source definition. If used together with 'cover' , it can replace 'printable_normalization'. Alternatively to both options, a 'printable_id' of an existing printable can be provided. page_count: description: The page count of the printable format: int32 readOnly: true type: number pod_package_id: description: The id of the PodPackage of the printable of this line item maxLength: 27 type: string printable_id: description: Id of the Printable of of this line item. It can be used instead of 'printable_normalization' / 'interior' / 'cover' format: uuid type: string printable_normalization: description: Represents the normalization processes of the interior and cover source files. Alternatively, 'interior' and 'cover' can be set as a shorthand for creation or a 'printable_id' of an existing printable can be provided. properties: cover: properties: job_id: description: The id of the normalization job (either a InteriorNormalizationJob or a CoverNormalizationJob) format: int32 type: number normalized_file: description: The resulting normalized file properties: file_id: format: int64 readOnly: true type: number filename: description: Filename of the normalized file readOnly: true type: string readOnly: true type: object source_md5_sum: description: A md5 hash of the source file to check it's integrity type: string source_url: description: The url of the source file. type: string required: - source_url type: object description: Represents the normalization process of the cover source files interior: properties: job_id: description: The id of the normalization job (either a InteriorNormalizationJob or a CoverNormalizationJob) format: int32 type: number normalized_file: description: The resulting normalized file properties: file_id: format: int64 readOnly: true type: number filename: description: Filename of the normalized file readOnly: true type: string readOnly: true type: object source_md5_sum: description: A md5 hash of the source file to check it's integrity type: string source_url: description: The url of the source file. type: string required: - source_url type: object description: Represents the normalization process of the interior source files required: - interior - cover type: object quantity: description: Quantity of printed books for this line item format: int32 type: number status: default: messages: {} name: CREATED description: Status object that contains the actual line item processing status as well as additional status related data properties: messages: description: A map of status related messages / data properties: delay: description: Expected delay in hours for error status' maxLength: 64 readOnly: true type: string error: description: General status error message readOnly: true type: string info: description: General info message on the status readOnly: true type: string printable_normalization: description: A map of printable normalization related messages / data properties: cover: description: Array of messages related to the cover file normalization items: readOnly: true type: string type: array interior: description: Array of messages related to the interior file normalization items: readOnly: true type: string type: array readOnly: true type: object timestamp: description: '[ISO 8601](https://www.w3.org/TR/NOTE-datetime)) timestamp of last status change' maxLength: 64 readOnly: true type: string url: anyOf: - type: string - items: type: string type: array description: Tracking url(s) readOnly: true type: object name: default: CREATED description: The actual processing status of the Print-Job. enum: - CREATED - ACCEPTED - REJECTED - IN_PRODUCTION - ERROR - SHIPPED type: string readOnly: true required: - name type: object title: description: The title of the line item. Should be on the cover. This field will become mandatory on October 1, 2019! maxLength: 255 type: string tracking_id: description: A list of tracking ids for this line item's shipment readOnly: true type: string tracking_urls: description: A list of tracking urls for this line item's shipment. items: type: string readOnly: true type: array required: - id - status - quantity type: object type: array order_id: description: Reference to the order, which this PrintJob has created readOnly: true type: string production_delay: default: 60 description: Delay before a newly created Print-Job is sent to production. Minimum is 60 minutes, maximum is 2880 minutes (=48 hours). As most cancellation requests occur right after an order has been placed, it makes sense to wait for some time before sending an order to production. Once production has started, orders cannot be canceled anymore. format: int32 maximum: 2880 minimum: 60 type: integer production_due_time: description: Target timestamp of when this job will move into production ([ISO 8601](https://www.w3.org/TR/NOTE-datetime)) format: date-time readOnly: true type: string shipping_address: description: The shipping address of the customer. properties: city: type: string country_code: description: '[ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) country code' maxLength: 2 minLength: 2 type: string email: format: email type: string description: "Shipping carriers require an email address for notifications or handling delivery issues. If no email is given, the default email in the user profile will be used.\n" is_business: default: false description: Only relevant for US addresses. Some US carriers don't deliver to business-addresses on Saturday. type: boolean name: description: Full name of the person, including first and last name. type: string organization: description: Name of an organization. Required if no person name is given. type: string phone_number: description: "Shipping carriers require a phone number for handling delivery issues. If no phone number is given, the default in the API user profile will be used. Validation Regex Pattern for phone numbers `^\\+?[\\d\\s\\-.\\/()]{8,20}$`\n" maxLength: 20 type: string postcode: description: Required for most countries maxLength: 64 type: string state_code: description: 2 or 3 letter state codes (officially called [ISO-3166-2 subdivision codes](https://en.wikipedia.org/wiki/ISO_3166-2)). They are required for some countries (e.g. US, MX, CA, AU) type: string street1: description: First address line type: string street2: description: Second address line type: string title: enum: - MR - MISS - MRS - MS - DR type: string warnings: description: Warnings found during address validation readOnly: true type: array items: properties: type: description: Type of warning type: string readOnly: true code: description: Warning code which describe what was suggested by validation type: string readOnly: true path: description: Describes the validation origin of warning type: string readOnly: true message: description: Warning message with suggested change type: string readOnly: true suggested_address: description: Suggested address returned by shipping address validation readOnly: true type: object properties: country_code: description: Suggested country code type: string readOnly: true state_code: description: Suggested state code type: string readOnly: true postcode: description: Suggested postal code type: string readOnly: true city: description: Suggested city type: string readOnly: true street1: description: Suggested first address line type: string readOnly: true street2: description: Suggested second address line type: string readOnly: true required: - name - street1 - city - country_code - postcode - phone_number - email type: object shipping_level: description: The shipping level that this Print-Job is shipped with enum: - MAIL - PRIORITY_MAIL - GROUND_HD - GROUND_BUS - GROUND - EXPEDITED - EXPRESS type: string tax_country: description: '[ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) country code of the tax country determined for this job' maxLength: 2 readOnly: true type: string required: - id - status - line_items - shipping_address - contact_email - shipping_level type: object example: contact_email: test@test.com costs: line_item_costs: shipping_cost: total_cost_excl_tax: total_cost_incl_tax: total_tax: date_created: '2017-08-07T08:47:26.485456Z' date_modified: '2017-08-07T08:47:26.485490Z' estimated_shipping_dates: arrival_max: '2017-08-12' arrival_min: '2017-08-10' dispatch_max: '2017-08-09' dispatch_min: '2017-08-07' external_id: demo-time id: 1 line_items: - external_id: item-reference-1 id: 1 printable_id: printable_normalization: cover: job_id: normalized_file: page_count: source_file: source_md5sum: e78512c777e7f5841fe8f1992cefb898 source_url: https://www.dropbox.com/sh/p3zh22vzsaegiri/AADP367j0bTWlt8fCu-_tm2ia/161025/139056_cover.pdf?dl=1 interior: job_id: normalized_file: page_count: source_file: source_md5sum: 7f8af20c296747689756f8e310135d79 source_url: https://www.dropbox.com/sh/p3zh22vzsaegiri/AACOUn3LFKsITDzylh13bQpsa/161025/thesis2.pdf?dl=1 pod_package_id: 0600X0900BWSTDPB060UW444MXX quantity: 20 status: messages: info: Line-item is currently being validated name: CREATED title: My Book production_delay: 120 production_due_time: shipping_address: city: Lübeck country_code: DE is_business: false name: Hans Dampf phone_number: 844-212-0689 postcode: '23552' state_code: '' street1: Holstenstr. 48 street2: '' shipping_level: MAIL shipping_option_level: MAIL status: changed: '2017-08-07T08:47:26.480493Z' message: Print-job is currently being validated name: CREATED example: contact_email: test@test.com costs: line_item_costs: shipping_cost: total_cost_excl_tax: total_cost_incl_tax: total_tax: date_created: '2017-08-07T08:47:26.485456Z' date_modified: '2017-08-07T08:47:26.485490Z' estimated_shipping_dates: arrival_max: '2017-08-12' arrival_min: '2017-08-10' dispatch_max: '2017-08-09' dispatch_min: '2017-08-07' external_id: demo-time id: 1 line_items: - external_id: item-reference-1 id: 1 printable_id: printable_normalization: cover: job_id: normalized_file: page_count: source_file: source_md5sum: e78512c777e7f5841fe8f1992cefb898 source_url: https://www.dropbox.com/sh/p3zh22vzsaegiri/AADP367j0bTWlt8fCu-_tm2ia/161025/139056_cover.pdf?dl=1 interior: job_id: normalized_file: page_count: source_file: source_md5sum: 7f8af20c296747689756f8e310135d79 source_url: https://www.dropbox.com/sh/p3zh22vzsaegiri/AACOUn3LFKsITDzylh13bQpsa/161025/thesis2.pdf?dl=1 pod_package_id: 0600X0900BWSTDPB060UW444MXX quantity: 20 status: messages: info: Line-item is currently being validated name: CREATED title: My Book production_delay: 120 production_due_time: shipping_address: city: Lübeck country_code: DE is_business: false name: Hans Dampf phone_number: 844-212-0689 postcode: '23552' state_code: '' street1: Holstenstr. 40 street2: '' warnings: type: validation_warning path: external code: REPLACED message: 'street1: Holstenstr. 40 -> Holstenstraße 40' suggested_address: country_code: DE state_code: postcode: 23552 city: Lübeck street1: Holstenstraße 40" street2: shipping_level: MAIL shipping_option_level: MAIL status: changed: '2017-08-07T08:47:26.480493Z' message: Print-job is currently being validated name: CREATED description: Created 400: content: application/json: schema: example: attribute_1: - This field is required. attribute_2: - This field is required. title: Bad Request example: attribute_1: - This field is required. attribute_2: - This field is required. description: Bad Request 401: $ref: '#/components/responses/Unauthorized' 403: $ref: '#/components/responses/Forbidden' security: - oauth2: [] summary: Create a new Print-Job tags: - Print-Jobs x-code-samples: - lang: Python source: | import requests import json url = "https://api.lulu.com/print-jobs/" payload = json.dumps({ "contact_email": "test@test.com", "external_id": "demo-time", "line_items": [ { "external_id": "item-reference-1", "printable_normalization": { "cover": { "source_url": "https://www.dropbox.com/s/7bv6mg2tj0h3l0r/lulu_trade_perfect_template.pdf?dl=1&raw=1" }, "interior": { "source_url": "https://www.dropbox.com/s/r20orb8umqjzav9/lulu_trade_interior_template-32.pdf?dl=1&raw=1" }, "pod_package_id": "0600X0900BWSTDPB060UW444MXX" }, "quantity": 30, "title": "My Book" } ], "production_delay": 120, "shipping_address": { "city": "Lübeck", "country_code": "GB", "name": "Hans Dampf", "phone_number": "844-212-0689", "postcode": "PO1 3AX", "state_code": "", "street1": "Holstenstr. 48" }, "shipping_level": "MAIL" }) headers = { 'Authorization': 'Check Authentication menu', 'Cache-Control': 'no-cache', 'Content-Type': 'application/json' } response = requests.request("POST", url, headers=headers, data=payload) print(response.text) - lang: Ruby source: | require "uri" require "json" require "net/http" url = URI("https://api.lulu.com/print-jobs/") https = Net::HTTP.new(url.host, url.port) https.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = "Check Authentication menu" request["Cache-Control"] = "no-cache" request["Content-Type"] = "application/json" request.body = JSON.dump({ "contact_email": "test@test.com", "external_id": "demo-time", "line_items": [ { "external_id": "item-reference-1", "printable_normalization": { "cover": { "source_url": "https://www.dropbox.com/s/7bv6mg2tj0h3l0r/lulu_trade_perfect_template.pdf?dl=1&raw=1" }, "interior": { "source_url": "https://www.dropbox.com/s/r20orb8umqjzav9/lulu_trade_interior_template-32.pdf?dl=1&raw=1" }, "pod_package_id": "0600X0900BWSTDPB060UW444MXX" }, "quantity": 30, "title": "My Book" } ], "production_delay": 120, "shipping_address": { "city": "Lübeck", "country_code": "GB", "name": "Hans Dampf", "phone_number": "844-212-0689", "postcode": "PO1 3AX", "state_code": "", "street1": "Holstenstr. 48" }, "shipping_level": "MAIL" }) response = https.request(request) puts response.read_body - lang: Node source: | var request = require('request'); var options = { 'method': 'POST', 'url': 'https://api.lulu.com/print-jobs/', 'headers': { 'Authorization': 'Check Authentication menu', 'Cache-Control': 'no-cache', 'Content-Type': 'application/json' }, body: JSON.stringify({ "contact_email": "test@test.com", "external_id": "demo-time", "line_items": [ { "external_id": "item-reference-1", "printable_normalization": { "cover": { "source_url": "https://www.dropbox.com/s/7bv6mg2tj0h3l0r/lulu_trade_perfect_template.pdf?dl=1&raw=1" }, "interior": { "source_url": "https://www.dropbox.com/s/r20orb8umqjzav9/lulu_trade_interior_template-32.pdf?dl=1&raw=1" }, "pod_package_id": "0600X0900BWSTDPB060UW444MXX" }, "quantity": 30, "title": "My Book" } ], "production_delay": 120, "shipping_address": { "city": "Lübeck", "country_code": "GB", "name": "Hans Dampf", "phone_number": "844-212-0689", "postcode": "PO1 3AX", "state_code": "", "street1": "Holstenstr. 48" }, "shipping_level": "MAIL" }) }; request(options, function (error, response) { if (error) throw new Error(error); console.log(response.body); }); - lang: Java source: | Unirest.setTimeouts(0, 0); HttpResponse<String> response = Unirest.post("https://api.lulu.com/print-jobs/") .header("Authorization", "Check Authentication menu") .header("Cache-Control", "no-cache") .header("Content-Type", "application/json") .body("{\n \"contact_email\": \"test@test.com\",\n \"external_id\": \"demo-time\",\n \"line_items\": [\n {\n \"external_id\": \"item-reference-1\",\n \"printable_normalization\": {\n \"cover\": {\n \"source_url\": \"https://www.dropbox.com/s/7bv6mg2tj0h3l0r/lulu_trade_perfect_template.pdf?dl=1&raw=1\"\n },\n \"interior\": {\n \"source_url\": \"https://www.dropbox.com/s/r20orb8umqjzav9/lulu_trade_interior_template-32.pdf?dl=1&raw=1\"\n },\n \"pod_package_id\": \"0600X0900BWSTDPB060UW444MXX\"\n },\n \"quantity\": 30,\n \"title\": \"My Book\"\n }\n ],\n \"production_delay\": 120,\n \"shipping_address\": {\n \"city\": \"L\\u00fcbeck\",\n \"country_code\": \"GB\",\n \"name\": \"Hans Dampf\",\n \"phone_number\": \"844-212-0689\",\n \"postcode\": \"PO1 3AX\",\n \"state_code\": \"\",\n \"street1\": \"Holstenstr. 48\"\n },\n \"shipping_level\": \"MAIL\"\n}") .asString(); - lang: Javascript source: | var myHeaders = new Headers(); myHeaders.append("Authorization", "Check Authentication menu"); myHeaders.append("Cache-Control", "no-cache"); myHeaders.append("Content-Type", "application/json"); var raw = JSON.stringify({ "contact_email": "test@test.com", "external_id": "demo-time", "line_items": [ { "external_id": "item-reference-1", "printable_normalization": { "cover": { "source_url": "https://www.dropbox.com/s/7bv6mg2tj0h3l0r/lulu_trade_perfect_template.pdf?dl=1&raw=1" }, "interior": { "source_url": "https://www.dropbox.com/s/r20orb8umqjzav9/lulu_trade_interior_template-32.pdf?dl=1&raw=1" }, "pod_package_id": "0600X0900BWSTDPB060UW444MXX" }, "quantity": 30, "title": "My Book" } ], "production_delay": 120, "shipping_address": { "city": "Lübeck", "country_code": "GB", "name": "Hans Dampf", "phone_number": "844-212-0689", "postcode": "PO1 3AX", "state_code": "", "street1": "Holstenstr. 48" }, "shipping_level": "MAIL" }); var requestOptions = { method: 'POST', headers: myHeaders, body: raw, redirect: 'follow' }; fetch("https://api.lulu.com/print-jobs/", requestOptions) .then(response => response.text()) .then(result => console.log(result)) .catch(error => console.log('error', error)); - lang: cURL source: | curl --location 'https://api.lulu.com/print-jobs/' \ --header 'Authorization: Check Authentication menu' \ --header 'Cache-Control: no-cache' \ --header 'Content-Type: application/json' \ --data-raw '{ "contact_email": "test@test.com", "external_id": "demo-time", "line_items": [ { "external_id": "item-reference-1", "printable_normalization": { "cover": { "source_url": "https://www.dropbox.com/s/7bv6mg2tj0h3l0r/lulu_trade_perfect_template.pdf?dl=1&raw=1" }, "interior": { "source_url": "https://www.dropbox.com/s/r20orb8umqjzav9/lulu_trade_interior_template-32.pdf?dl=1&raw=1" }, "pod_package_id": "0600X0900BWSTDPB060UW444MXX" }, "quantity": 30, "title": "My Book" } ], "production_delay": 120, "shipping_address": { "city": "L\u00fcbeck", "country_code": "GB", "name": "Hans Dampf", "phone_number": "844-212-0689", "postcode": "PO1 3AX", "state_code": "", "street1": "Holstenstr. 48" }, "shipping_level": "MAIL" }' # use empty path param to show multiple examples for same path. see https://github.com/OAI/OpenAPI-Specification/issues/182# /print-jobs/ : post: description: | ### Usage of printable_id The immutable `printable_id` can be used for re-orders so that the files don't have to be transferred again. Given there is an already created and validated Print-Job, you can use the `printable_id` of each line-item to create re-orders for that particular printable. As the normalized files are already on the server, you omit the complete `printable_normalization` object from the request and send a valid `printable_id` instead. ### Shipping Information & Metadata Print-Jobs have to contain a `shipping_address` as well as a `shipping_level`. Lulu offers five different service levels that differ in speed and traceability. ### Additional Metadata A few additional metadata fields can be specified in the Print-Job as well: * `contact_email` for questions related to the Print-Job itself, * `production_delay` allows you to specify a delay (between 60 minutes and 2,880 minutes) before the Print-Job goes to production, * `external_id` allows you to link the Print-Job to an internal order number or other reference. ## File Handling and Normalization If there is an existing printable for the given `printable_id` the already processed and normalized files are used for production. If there are are problems with the `printable_id`, the PrintJob will be rejected or cancelled and an error message will be displayed. ## Automation and Payment After a Print-Job has been created successfully, it will remain in an `UNPAID` state until it is paid for through the developer portal. However, you can automate the process by putting a credit card on file. Then, the Print-Job will automatically transition to the `PRODUCTION_DELAY` status and your card will charged when the Print-Job is sent to production. operationId: Print-Jobs_reprint requestBody: content: application/json: schema: description: The job resource that represents a print order properties: contact_email: description: Email address that should be contacted if questions regarding the Print-Job arise. Lulu recommends to use the email of a person who is responsible for placing the Print-Job like a developer or business owner. format: email type: string costs: description: Summary of the costs of a Print-Job properties: line_item_costs: description: Costs for a Print-Job line item properties: cost_excl_discounts: description: Per unit cost without any discounts applied as a decimal string readOnly: true type: string discounts: description: Discounts applied to this line item items: properties: amount: description: The deducted amount as a decimal string readOnly: true type: string description: description: Description of the discount readOnly: true type: string required: - amount - description type: object readOnly: true type: array quantity: description: The quantity of printables to base the calculations on format: int32 readOnly: true type: number tax_rate: description: The tax rate applied to the line as a decimal string readOnly: true type: string total_cost_excl_discounts: description: The total line price without any discounts applied as a decimal string readOnly: true type: string total_cost_excl_tax: description: The total line price including discounts excluding tax as a decimal string readOnly: true type: string total_cost_incl_tax: description: The total line price including discounts and taxes as a decimal string readOnly: true type: string total_tax: description: The total line tax amount as a decimal string readOnly: true type: string unit_tier_cost: description: Per unit cost with tier discount applied, null for list price (non-tier) customers readOnly: true type: string required: - quantity - cost_excl_discounts - cost_excl_tax - tax_rate - discounts - total_cost_excl_discounts - total_tax - total_cost_excl_tax - total_cost_incl_tax type: object shipping_cost: description: Summary of the shipping costs properties: tax_rate: description: Tax rate that was applied on shipping costs as a decimal string readOnly: true type: string total_cost_excl_tax: description: Total shipping costs excluding taxes as a decimal string readOnly: true type: string total_cost_incl_tax: description: Total shipping costs including taxes as a decimal string readOnly: true type: string total_tax: description: Total amount of taxes on shipping as a decimal string readOnly: true type: string readOnly: true type: object total_cost_excl_tax: description: Total costs of the job excluding taxes as a decimal string readOnly: true type: string total_cost_incl_tax: description: Total costs of the job including taxes as a decimal string readOnly: true type: string total_tax: description: Total amount of taxes on the job as a decimal string readOnly: true type: string readOnly: true type: object estimated_shipping_dates: description: The estimated ship and delivery dates for a Print-Job properties: arrival_max: description: The slowest estimated delivery date for a Print-Job in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601)) format readOnly: true type: string arrival_min: description: The fastest estimated delivery date for a Print-Job in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601)) format readOnly: true type: string dispatch_max: description: The slowest estimated ship date for a Print-Job in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601)) format readOnly: true type: string dispatch_min: description: The fastest estimated ship date for a Print-Job in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601)) format readOnly: true type: string readOnly: true type: object external_id: description: Arbitrary string to identify and connect a print job to your systems. Set it to an order number, a purchase order or whatever else works for your particular use case. type: string id: format: int64 readOnly: true type: number line_items: description: The line items of a Print-Job, defining it's Printables and their quantities. The property name 'items' can be used instead. items: description: The line item of a Print-Job, defining it's printable and quantity properties: cover: oneOf: - properties: source_md5_sum: description: A md5 hash of the source file to check it's integrity type: string source_url: description: The url of the source file. type: string required: - source_url type: object - description: The url of the interior source file. type: string writeOnly: true writeOnly: true description: Shorthand of the cover source definition. If used together with 'interior' , it can replace 'printable_normalization', Alternatively to both options, a 'printable_id' of an existing printable can be provided. external_id: description: Arbitrary string to identify and connect a print job to your systems. Set it to an order number, a purchase order or whatever else works for your particular use case type: string id: format: int64 readOnly: true type: number interior: oneOf: - properties: source_md5_sum: description: A md5 hash of the source file to check it's integrity type: string source_url: description: The url of the source file. type: string required: - source_url type: object - description: The url of the interior source file. type: string writeOnly: true writeOnly: true description: Shorthand of the interior source definition. If used together with 'cover' , it can replace 'printable_normalization'. Alternatively to both options, a 'printable_id' of an existing printable can be provided. page_count: description: The page count of the printable format: int32 readOnly: true type: number pod_package_id: description: The id of the PodPackage of the printable of this line item maxLength: 27 type: string printable_id: description: Id of the Printable of of this line item. It can be used instead of 'printable_normalization' / 'interior' / 'cover' format: uuid type: string printable_normalization: description: Can be omitted if a valid 'printable_id' of an existing printable is provided. properties: cover: properties: job_id: description: The id of the normalization job (either a InteriorNormalizationJob or a CoverNormalizationJob) format: int32 type: number normalized_file: description: The resulting normalized file properties: file_id: format: int64 readOnly: true type: number filename: description: Filename of the normalized file readOnly: true type: string readOnly: true type: object source_md5_sum: description: A md5 hash of the source file to check it's integrity type: string source_url: description: The url of the source file. type: string required: - source_url type: object description: Represents the normalization process of the cover source files interior: properties: job_id: description: The id of the normalization job (either a InteriorNormalizationJob or a CoverNormalizationJob) format: int32 type: number normalized_file: description: The resulting normalized file properties: file_id: format: int64 readOnly: true type: number filename: description: Filename of the normalized file readOnly: true type: string readOnly: true type: object source_md5_sum: description: A md5 hash of the source file to check it's integrity type: string source_url: description: The url of the source file. type: string required: - source_url type: object description: Represents the normalization process of the interior source files required: - interior - cover type: object quantity: description: Quantity of printed books for this line item format: int32 type: number status: default: messages: {} name: CREATED description: Status object that contains the actual line item processing status as well as additional status related data properties: messages: description: A map of status related messages / data properties: delay: description: Expected delay in hours for error status' maxLength: 64 readOnly: true type: string error: description: General status error message readOnly: true type: string info: description: General info message on the status readOnly: true type: string printable_normalization: description: A map of printable normalization related messages / data properties: cover: description: Array of messages related to the cover file normalization items: readOnly: true type: string type: array interior: description: Array of messages related to the interior file normalization items: readOnly: true type: string type: array readOnly: true type: object timestamp: description: '[ISO 8601](https://www.w3.org/TR/NOTE-datetime)) timestamp of last status change' maxLength: 64 readOnly: true type: string url: anyOf: - type: string - items: type: string type: array description: Tracking url(s) readOnly: true type: object name: default: CREATED description: The actual processing status of the Print-Job. enum: - CREATED - ACCEPTED - REJECTED - IN_PRODUCTION - ERROR - SHIPPED type: string readOnly: true required: - name type: object title: description: The title of the line item. Should be on the cover. This field will become mandatory on October 1, 2019! maxLength: 255 type: string tracking_id: description: A list of tracking ids for this line item's shipment readOnly: true type: string tracking_urls: description: A list of tracking urls for this line item's shipment. items: type: string readOnly: true type: array required: - id - status - quantity type: object type: array order_id: description: Reference to the order, which this PrintJob has created readOnly: true type: string production_delay: default: 60 description: "Delay before a newly created Print-Job is sent to production. Minimum is 60 minutes, maximum is 2880 minutes (=48 hours). As most cancellation requests occur right after an order has been placed, it makes sense to wait for some time before sending an order to production. Once production has started, orders cannot be canceled anymore.\n" format: int32 maximum: 2880 minimum: 60 type: integer production_due_time: description: Target timestamp of when this job will move into production ([ISO 8601](https://www.w3.org/TR/NOTE-datetime)) format: date-time readOnly: true type: string shipping_address: description: The shipping address of the customer. properties: city: type: string country_code: description: '[ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) country code' maxLength: 2 minLength: 2 type: string email: format: email type: string description: "Shipping carriers require an email address for notifications or handling delivery issues. If no email is given, the default email in the user profile will be used.\n" is_business: default: false description: Only relevant for US addresses. Some US carriers don't deliver to business-addresses on Saturday. type: boolean name: description: Full name of the person, including first and last name. type: string organization: description: Name of an organization. Required if no person name is given. type: string phone_number: description: Shipping carriers require a phone number for handling delivery issues. If no phone number is given, the default in the API user profile will be used. Validation Regex Pattern for phone numbers `^\+?[\d\s\-.\/()]{8,20}$` maxLength: 20 type: string postcode: description: Required for most countries maxLength: 64 type: string state_code: description: 2 or 3 letter state codes (officially called [ISO-3166-2 subdivision codes](https://en.wikipedia.org/wiki/ISO_3166-2)). They are required for some countries (e.g. US, MX, CA, AU) type: string street1: description: First address line type: string street2: description: Second address line type: string title: enum: - MR - MISS - MRS - MS - DR type: string warnings: description: Warnings found during address validation readOnly: true type: array items: properties: type: description: Type of warning type: string readOnly: true code: description: Warning code which describe what was suggested by validation type: string readOnly: true path: description: Describes the validation origin of warning type: string readOnly: true message: description: Warning message with suggested change type: string readOnly: true suggested_address: description: Suggested address returned by shipping address validation readOnly: true type: object properties: country_code: description: Suggested country code type: string readOnly: true state_code: description: Suggested state code type: string readOnly: true postcode: description: Suggested postal code type: string readOnly: true city: description: Suggested city type: string readOnly: true street1: description: Suggested first address line type: string readOnly: true street2: description: Suggested second address line type: string readOnly: true required: - name - street1 - city - country_code - postcode - phone_number - email type: object shipping_level: description: The shipping level that this Print-Job is shipped with enum: - MAIL - PRIORITY_MAIL - GROUND_HD - GROUND_BUS - GROUND - EXPEDITED - EXPRESS type: string tax_country: description: '[ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) country code of the tax country determined for this job' maxLength: 2 readOnly: true type: string required: - id - status - line_items - shipping_address - contact_email - shipping_level type: object example: contact_email: test@test.com external_id: demo-time line_items: - external_id: item-reference-1 printable_normalization: cover: source_url: https://www.dropbox.com/s/7bv6mg2tj0h3l0r/lulu_trade_perfect_template.pdf?dl=1&raw=1 interior: source_url: https://www.dropbox.com/s/r20orb8umqjzav9/lulu_trade_interior_template-32.pdf?dl=1&raw=1 pod_package_id: 0600X0900BWSTDPB060UW444MXX quantity: 30 title: My Book production_delay: 120 shipping_address: city: Lübeck country_code: GB name: Hans Dampf phone_number: 844-212-0689 postcode: PO1 3AX state_code: '' street1: Holstenstr. 48 shipping_level: MAIL example: contact_email: test@test.com external_id: demo-time line_items: - external_id: item-reference-1 printable_id: 11606ab3-9355-46d3-ae90-338db6f5d271 quantity: 30 title: My Book production_delay: 120 shipping_address: city: Lübeck country_code: GB name: Hans Dampf phone_number: 844-212-0689 postcode: PO1 3AX state_code: '' street1: Holstenstr. 48 shipping_level: MAIL responses: 201: content: application/json: schema: description: The job resource that represents a print order properties: contact_email: description: "Email address that should be contacted if questions regarding the Print-Job arise. Lulu recommends to use the email of a person who is responsible for placing the Print-Job like a developer or business owner.\n" format: email type: string costs: description: Summary of the costs of a Print-Job properties: line_item_costs: description: Costs for a Print-Job line item properties: cost_excl_discounts: description: Per unit cost without any discounts applied as a decimal string readOnly: true type: string discounts: description: Discounts applied to this line item items: properties: amount: description: The deducted amount as a decimal string readOnly: true type: string description: description: Description of the discount readOnly: true type: string required: - amount - description type: object readOnly: true type: array quantity: description: The quantity of printables to base the calculations on format: int32 readOnly: true type: number tax_rate: description: The tax rate applied to the line as a decimal string readOnly: true type: string total_cost_excl_discounts: description: The total line price without any discounts applied as a decimal string readOnly: true type: string total_cost_excl_tax: description: The total line price including discounts excluding tax as a decimal string readOnly: true type: string total_cost_incl_tax: description: The total line price including discounts and taxes as a decimal string readOnly: true type: string total_tax: description: The total line tax amount as a decimal string readOnly: true type: string unit_tier_cost: description: Per unit cost with tier discount applied, null for list price (non-tier) customers readOnly: true type: string required: - quantity - cost_excl_discounts - cost_excl_tax - tax_rate - discounts - total_cost_excl_discounts - total_tax - total_cost_excl_tax - total_cost_incl_tax type: object shipping_cost: description: Summary of the shipping costs properties: tax_rate: description: Tax rate that was applied on shipping costs as a decimal string readOnly: true type: string total_cost_excl_tax: description: Total shipping costs excluding taxes as a decimal string readOnly: true type: string total_cost_incl_tax: description: Total shipping costs including taxes as a decimal string readOnly: true type: string total_tax: description: Total amount of taxes on shipping as a decimal string readOnly: true type: string readOnly: true type: object total_cost_excl_tax: description: Total costs of the job excluding taxes as a decimal string readOnly: true type: string total_cost_incl_tax: description: Total costs of the job including taxes as a decimal string readOnly: true type: string total_tax: description: Total amount of taxes on the job as a decimal string readOnly: true type: string readOnly: true type: object estimated_shipping_dates: description: The estimated ship and delivery dates for a Print-Job properties: arrival_max: description: The slowest estimated delivery date for a Print-Job in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601)) format readOnly: true type: string arrival_min: description: The fastest estimated delivery date for a Print-Job in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601)) format readOnly: true type: string dispatch_max: description: The slowest estimated ship date for a Print-Job in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601)) format readOnly: true type: string dispatch_min: description: The fastest estimated ship date for a Print-Job in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601)) format readOnly: true type: string readOnly: true type: object external_id: description: Arbitrary string to identify and connect a print job to your systems. Set it to an order number, a purchase order or whatever else works for your particular use case. type: string id: format: int64 readOnly: true type: number line_items: description: The line items of a Print-Job, defining it's Printables and their quantities. The property name 'items' can be used instead. items: description: The line item of a Print-Job, defining it's printable and quantity properties: cover: oneOf: - properties: source_md5_sum: description: A md5 hash of the source file to check it's integrity type: string source_url: description: The url of the source file. type: string required: - source_url type: object - description: The url of the interior source file. type: string writeOnly: true writeOnly: true description: Shorthand of the cover source definition. If used together with 'interior' , it can replace 'printable_normalization', Alternatively to both options, a 'printable_id' of an existing printable can be provided. external_id: description: Arbitrary string to identify and connect a print job to your systems. Set it to an order number, a purchase order or whatever else works for your particular use case type: string id: format: int64 readOnly: true type: number interior: oneOf: - properties: source_md5_sum: description: A md5 hash of the source file to check it's integrity type: string source_url: description: The url of the source file. type: string required: - source_url type: object - description: The url of the interior source file. type: string writeOnly: true writeOnly: true description: Shorthand of the interior source definition. If used together with 'cover' , it can replace 'printable_normalization'. Alternatively to both options, a 'printable_id' of an existing printable can be provided. page_count: description: The page count of the printable format: int32 readOnly: true type: number pod_package_id: description: The id of the PodPackage of the printable of this line item maxLength: 27 type: string printable_id: description: Id of the Printable of of this line item. It can be used instead of 'printable_normalization' / 'interior' / 'cover' format: uuid type: string printable_normalization: description: Represents the normalization processes of the interior and cover source files. Alternatively, 'interior' and 'cover' can be set as a shorthand for creation or a 'printable_id' of an existing printable can be provided. properties: cover: properties: job_id: description: The id of the normalization job (either a InteriorNormalizationJob or a CoverNormalizationJob) format: int32 type: number normalized_file: description: The resulting normalized file properties: file_id: format: int64 readOnly: true type: number filename: description: Filename of the normalized file readOnly: true type: string readOnly: true type: object source_md5_sum: description: A md5 hash of the source file to check it's integrity type: string source_url: description: The url of the source file. type: string required: - source_url type: object description: Represents the normalization process of the cover source files interior: properties: job_id: description: The id of the normalization job (either a InteriorNormalizationJob or a CoverNormalizationJob) format: int32 type: number normalized_file: description: The resulting normalized file properties: file_id: format: int64 readOnly: true type: number filename: description: Filename of the normalized file readOnly: true type: string readOnly: true type: object source_md5_sum: description: A md5 hash of the source file to check it's integrity type: string source_url: description: The url of the source file. type: string required: - source_url type: object description: Represents the normalization process of the interior source files required: - interior - cover type: object quantity: description: Quantity of printed books for this line item format: int32 type: number status: default: messages: {} name: CREATED description: Status object that contains the actual line item processing status as well as additional status related data properties: messages: description: A map of status related messages / data properties: delay: description: Expected delay in hours for error status' maxLength: 64 readOnly: true type: string error: description: General status error message readOnly: true type: string info: description: General info message on the status readOnly: true type: string printable_normalization: description: A map of printable normalization related messages / data properties: cover: description: Array of messages related to the cover file normalization items: readOnly: true type: string type: array interior: description: Array of messages related to the interior file normalization items: readOnly: true type: string type: array readOnly: true type: object timestamp: description: '[ISO 8601](https://www.w3.org/TR/NOTE-datetime)) timestamp of last status change' maxLength: 64 readOnly: true type: string url: anyOf: - type: string - items: type: string type: array description: Tracking url(s) readOnly: true type: object name: default: CREATED description: The actual processing status of the Print-Job. enum: - CREATED - ACCEPTED - REJECTED - IN_PRODUCTION - ERROR - SHIPPED type: string readOnly: true required: - name type: object title: description: The title of the line item. Should be on the cover. This field will become mandatory on October 1, 2019! maxLength: 255 type: string tracking_id: description: A list of tracking ids for this line item's shipment readOnly: true type: string tracking_urls: description: A list of tracking urls for this line item's shipment. items: type: string readOnly: true type: array required: - id - status - quantity type: object type: array order_id: description: Reference to the order, which this PrintJob has created readOnly: true type: string production_delay: default: 60 description: "Delay before a newly created Print-Job is sent to production. Minimum is 60 minutes, maximum is 2880 minutes (=48 hours). As most cancellation requests occur right after an order has been placed, it makes sense to wait for some time before sending an order to production. Once production has started, orders cannot be canceled anymore.\n" format: int32 maximum: 2880 minimum: 60 type: integer production_due_time: description: Target timestamp of when this job will move into production ([ISO 8601](https://www.w3.org/TR/NOTE-datetime)) format: date-time readOnly: true type: string shipping_address: description: The shipping address of the customer. properties: city: type: string country_code: description: '[ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) country code' maxLength: 2 minLength: 2 type: string email: format: email type: string description: "Shipping carriers require an email address for notifications or handling delivery issues. If no email is given, the default email in the user profile will be used.\n" is_business: default: false description: Only relevant for US addresses. Some US carriers don't deliver to business-addresses on Saturday. type: boolean name: description: Full name of the person, including first and last name. type: string organization: description: Name of an organization. Required if no person name is given. type: string phone_number: description: "Shipping carriers require a phone number for handling delivery issues. If no phone number is given, the default in the API user profile will be used. Validation Regex Pattern for phone numbers `^\\+?[\\d\\s\\-.\\/()]{8,20}$`\n" maxLength: 20 type: string postcode: description: Required for most countries maxLength: 64 type: string state_code: description: 2 or 3 letter state codes (officially called [ISO-3166-2 subdivision codes](https://en.wikipedia.org/wiki/ISO_3166-2)). They are required for some countries (e.g. US, MX, CA, AU) type: string street1: description: First address line type: string street2: description: Second address line type: string title: enum: - MR - MISS - MRS - MS - DR type: string warnings: description: Warnings found during address validation readOnly: true type: array items: properties: type: description: Type of warning type: string readOnly: true code: description: Warning code which describe what was suggested by validation type: string readOnly: true path: description: Describes the validation origin of warning type: string readOnly: true message: description: Warning message with suggested change type: string readOnly: true suggested_address: description: Suggested address returned by shipping address validation readOnly: true type: object properties: country_code: description: Suggested country code type: string readOnly: true state_code: description: Suggested state code type: string readOnly: true postcode: description: Suggested postal code type: string readOnly: true city: description: Suggested city type: string readOnly: true street1: description: Suggested first address line type: string readOnly: true street2: description: Suggested second address line type: string readOnly: true required: - name - street1 - city - country_code - postcode - phone_number - email type: object shipping_level: description: The shipping level that this Print-Job is shipped with enum: - MAIL - PRIORITY_MAIL - GROUND_HD - GROUND_BUS - GROUND - EXPEDITED - EXPRESS type: string tax_country: description: '[ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) country code of the tax country determined for this job' maxLength: 2 readOnly: true type: string required: - id - status - line_items - shipping_address - contact_email - shipping_level type: object example: contact_email: test@test.com costs: line_item_costs: shipping_cost: total_cost_excl_tax: total_cost_incl_tax: total_tax: date_created: '2017-08-07T08:47:26.485456Z' date_modified: '2017-08-07T08:47:26.485490Z' estimated_shipping_dates: arrival_max: '2017-08-12' arrival_min: '2017-08-10' dispatch_max: '2017-08-09' dispatch_min: '2017-08-07' external_id: demo-time id: 1 line_items: - external_id: item-reference-1 id: 1 printable_id: 11606ab3-9355-46d3-ae90-338db6f5d271 printable_normalization: quantity: 20 status: messages: info: Line-item is currently being validated name: CREATED title: My Book production_delay: 120 production_due_time: shipping_address: city: Lübeck country_code: DE is_business: false name: Hans Dampf phone_number: 844-212-0689 postcode: '23552' state_code: '' street1: Holstenstr. 40 street2: '' warnings: type: validation_warning path: external code: REPLACED message: 'street1: Holstenstr. 40 -> Holstenstraße 40' suggested_address: country_code: DE state_code: postcode: 23552 city: Lübeck street1: Holstenstraße 40" street2: shipping_level: MAIL shipping_option_level: MAIL status: changed: '2017-08-07T08:47:26.480493Z' message: Print-job is currently being validated name: CREATED example: contact_email: test@test.com costs: line_item_costs: shipping_cost: total_cost_excl_tax: total_cost_incl_tax: total_tax: date_created: '2017-08-07T08:47:26.485456Z' date_modified: '2017-08-07T08:47:26.485490Z' estimated_shipping_dates: arrival_max: '2017-08-12' arrival_min: '2017-08-10' dispatch_max: '2017-08-09' dispatch_min: '2017-08-07' external_id: demo-time id: 1 line_items: - external_id: item-reference-1 id: 1 printable_id: 11606ab3-9355-46d3-ae90-338db6f5d271 printable_normalization: quantity: 20 status: messages: info: Line-item is currently being validated name: CREATED title: My Book production_delay: 120 production_due_time: shipping_address: city: Lübeck country_code: DE is_business: false name: Hans Dampf phone_number: 844-212-0689 postcode: '23552' state_code: '' street1: Holstenstr. 48 street2: '' shipping_level: MAIL shipping_option_level: MAIL status: changed: '2017-08-07T08:47:26.480493Z' message: Print-job is currently being validated name: CREATED description: Created 400: content: application/json: schema: example: attribute_1: - This field is required. attribute_2: - This field is required. title: Bad Request example: attribute_1: - This field is required. attribute_2: - This field is required. description: Bad Request 401: $ref: '#/components/responses/Unauthorized' 403: $ref: '#/components/responses/Forbidden' security: - oauth2: [] summary: Create a new Print-Job (as Reprint) tags: - Print-Jobs x-code-samples: - lang: Python source: | import requests import json url = "https://api.lulu.com/print-jobs/" payload = json.dumps({ "contact_email": "test@test.com", "external_id": "demo-time", "line_items": [ { "external_id": "item-reference-1", "printable_normalization": { "cover": { "source_url": "https://www.dropbox.com/s/7bv6mg2tj0h3l0r/lulu_trade_perfect_template.pdf?dl=1&raw=1" }, "interior": { "source_url": "https://www.dropbox.com/s/r20orb8umqjzav9/lulu_trade_interior_template-32.pdf?dl=1&raw=1" }, "pod_package_id": "0600X0900BWSTDPB060UW444MXX" }, "quantity": 30, "title": "My Book" } ], "production_delay": 120, "shipping_address": { "city": "Lübeck", "country_code": "GB", "name": "Hans Dampf", "phone_number": "844-212-0689", "postcode": "PO1 3AX", "state_code": "", "street1": "Holstenstr. 48" }, "shipping_level": "MAIL" }) headers = { 'Authorization': 'Check Authentication menu', 'Cache-Control': 'no-cache', 'Content-Type': 'application/json' } response = requests.request("POST", url, headers=headers, data=payload) print(response.text) - lang: Ruby source: | require "uri" require "json" require "net/http" url = URI("https://api.lulu.com/print-jobs/") https = Net::HTTP.new(url.host, url.port) https.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = "Check Authentication menu" request["Cache-Control"] = "no-cache" request["Content-Type"] = "application/json" request.body = JSON.dump({ "contact_email": "test@test.com", "external_id": "demo-time", "line_items": [ { "external_id": "item-reference-1", "printable_normalization": { "cover": { "source_url": "https://www.dropbox.com/s/7bv6mg2tj0h3l0r/lulu_trade_perfect_template.pdf?dl=1&raw=1" }, "interior": { "source_url": "https://www.dropbox.com/s/r20orb8umqjzav9/lulu_trade_interior_template-32.pdf?dl=1&raw=1" }, "pod_package_id": "0600X0900BWSTDPB060UW444MXX" }, "quantity": 30, "title": "My Book" } ], "production_delay": 120, "shipping_address": { "city": "Lübeck", "country_code": "GB", "name": "Hans Dampf", "phone_number": "844-212-0689", "postcode": "PO1 3AX", "state_code": "", "street1": "Holstenstr. 48" }, "shipping_level": "MAIL" }) response = https.request(request) puts response.read_body - lang: Node source: | var request = require('request'); var options = { 'method': 'POST', 'url': 'https://api.lulu.com/print-jobs/', 'headers': { 'Authorization': 'Check Authentication menu', 'Cache-Control': 'no-cache', 'Content-Type': 'application/json' }, body: JSON.stringify({ "contact_email": "test@test.com", "external_id": "demo-time", "line_items": [ { "external_id": "item-reference-1", "printable_normalization": { "cover": { "source_url": "https://www.dropbox.com/s/7bv6mg2tj0h3l0r/lulu_trade_perfect_template.pdf?dl=1&raw=1" }, "interior": { "source_url": "https://www.dropbox.com/s/r20orb8umqjzav9/lulu_trade_interior_template-32.pdf?dl=1&raw=1" }, "pod_package_id": "0600X0900BWSTDPB060UW444MXX" }, "quantity": 30, "title": "My Book" } ], "production_delay": 120, "shipping_address": { "city": "Lübeck", "country_code": "GB", "name": "Hans Dampf", "phone_number": "844-212-0689", "postcode": "PO1 3AX", "state_code": "", "street1": "Holstenstr. 48" }, "shipping_level": "MAIL" }) }; request(options, function (error, response) { if (error) throw new Error(error); console.log(response.body); }); - lang: Java source: | Unirest.setTimeouts(0, 0); HttpResponse<String> response = Unirest.post("https://api.lulu.com/print-jobs/") .header("Authorization", "Check Authentication menu") .header("Cache-Control", "no-cache") .header("Content-Type", "application/json") .body("{\n \"contact_email\": \"test@test.com\",\n \"external_id\": \"demo-time\",\n \"line_items\": [\n {\n \"external_id\": \"item-reference-1\",\n \"printable_normalization\": {\n \"cover\": {\n \"source_url\": \"https://www.dropbox.com/s/7bv6mg2tj0h3l0r/lulu_trade_perfect_template.pdf?dl=1&raw=1\"\n },\n \"interior\": {\n \"source_url\": \"https://www.dropbox.com/s/r20orb8umqjzav9/lulu_trade_interior_template-32.pdf?dl=1&raw=1\"\n },\n \"pod_package_id\": \"0600X0900BWSTDPB060UW444MXX\"\n },\n \"quantity\": 30,\n \"title\": \"My Book\"\n }\n ],\n \"production_delay\": 120,\n \"shipping_address\": {\n \"city\": \"L\\u00fcbeck\",\n \"country_code\": \"GB\",\n \"name\": \"Hans Dampf\",\n \"phone_number\": \"844-212-0689\",\n \"postcode\": \"PO1 3AX\",\n \"state_code\": \"\",\n \"street1\": \"Holstenstr. 48\"\n },\n \"shipping_level\": \"MAIL\"\n}") .asString(); - lang: Javascript source: | var myHeaders = new Headers(); myHeaders.append("Authorization", "Check Authentication menu"); myHeaders.append("Cache-Control", "no-cache"); myHeaders.append("Content-Type", "application/json"); var raw = JSON.stringify({ "contact_email": "test@test.com", "external_id": "demo-time", "line_items": [ { "external_id": "item-reference-1", "printable_normalization": { "cover": { "source_url": "https://www.dropbox.com/s/7bv6mg2tj0h3l0r/lulu_trade_perfect_template.pdf?dl=1&raw=1" }, "interior": { "source_url": "https://www.dropbox.com/s/r20orb8umqjzav9/lulu_trade_interior_template-32.pdf?dl=1&raw=1" }, "pod_package_id": "0600X0900BWSTDPB060UW444MXX" }, "quantity": 30, "title": "My Book" } ], "production_delay": 120, "shipping_address": { "city": "Lübeck", "country_code": "GB", "name": "Hans Dampf", "phone_number": "844-212-0689", "postcode": "PO1 3AX", "state_code": "", "street1": "Holstenstr. 48" }, "shipping_level": "MAIL" }); var requestOptions = { method: 'POST', headers: myHeaders, body: raw, redirect: 'follow' }; fetch("https://api.lulu.com/print-jobs/", requestOptions) .then(response => response.text()) .then(result => console.log(result)) .catch(error => console.log('error', error)); - lang: cURL source: | curl --location 'https://api.lulu.com/print-jobs/' \ --header 'Authorization: Check Authentication menu' \ --header 'Cache-Control: no-cache' \ --header 'Content-Type: application/json' \ --data-raw '{ "contact_email": "test@test.com", "external_id": "demo-time", "line_items": [ { "external_id": "item-reference-1", "printable_normalization": { "cover": { "source_url": "https://www.dropbox.com/s/7bv6mg2tj0h3l0r/lulu_trade_perfect_template.pdf?dl=1&raw=1" }, "interior": { "source_url": "https://www.dropbox.com/s/r20orb8umqjzav9/lulu_trade_interior_template-32.pdf?dl=1&raw=1" }, "pod_package_id": "0600X0900BWSTDPB060UW444MXX" }, "quantity": 30, "title": "My Book" } ], "production_delay": 120, "shipping_address": { "city": "L\u00fcbeck", "country_code": "GB", "name": "Hans Dampf", "phone_number": "844-212-0689", "postcode": "PO1 3AX", "state_code": "", "street1": "Holstenstr. 48" }, "shipping_level": "MAIL" }' /print-jobs/statistics/: get: operationId: Print-Jobs_statistics parameters: - description: 'Result page, default: 1' in: query name: page schema: type: integer - description: The default is 100. in: query name: page_size schema: type: integer - description: Filter by creation timestamp after the given ([ISO 8601](https://www.w3.org/TR/NOTE-datetime)) timestamp. in: query name: created_after required: false schema: type: string - description: Filter by creation timestamp before the given ([ISO 8601](https://www.w3.org/TR/NOTE-datetime)) timestamp. in: query name: created_before required: false schema: type: string - description: Filter by modification timestamp after the given ([ISO 8601](https://www.w3.org/TR/NOTE-datetime)) timestamp. in: query name: modified_after required: false schema: type: string - description: Filter by modification timestamp before the given ([ISO 8601](https://www.w3.org/TR/NOTE-datetime)) timestamp. in: query name: modified_before required: false schema: type: string - description: Filter by status in: query name: status required: false schema: type: string - description: Filter by id in: query name: id required: false schema: type: string - description: Which field to use when ordering the results. in: query name: ordering required: false schema: type: string responses: 200: content: application/json: schema: description: status name and the amount of corresponding print jobs properties: count: description: Amount of printjobs format: int64 readOnly: true type: number status: default: CREATED description: | The actual processing status of the Print-Job. Valid status transitions: * `CREATED` -> `UNPAID`, `REJECTED` `CANCELED`, `PRODUCTION_READY` * `UNPAID` -> `PAYMENT_IN_PROGRESS`, `CANCELED`, `PRODUCTION_DELAYED` * `PAYMENT_IN_PROGRESS` -> `UNPAID`, `PRODUCTION_DELAYED` * `PRODUCTION_DELAYED` -> `PRODUCTION_READY`, `CANCELED` * `PRODUCTION_READY` -> `IN_PRODUCTION`, `PRODUCTION_DELAYED` * `IN_PRODUCTION` -> `SHIPPED`, `ERROR` enum: - CREATED - REJECTED - UNPAID - PAYMENT_IN_PROGRESS - PRODUCTION_READY - PRODUCTION_DELAYED - IN_PRODUCTION - ERROR - SHIPPED - CANCELED type: string example: count: 3 status: PAYMENT_IN_PROGRESS example: count: 3 status: PAYMENT_IN_PROGRESS description: OK 401: $ref: '#/components/responses/Unauthorized' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' security: - oauth2: [] summary: Retrieve the number of Print-Jobs in each status tags: - Print-Jobs x-code-samples: - lang: Python source: | import requests url = "https://api.lulu.com/print-jobs/statistics/" payload = {} headers = { 'Authorization': 'Check Authentication menu', 'Cache-Control': 'no-cache' } response = requests.request("GET", url, headers=headers, data=payload) print(response.text) - lang: Ruby source: | require "uri" require "net/http" url = URI("https://api.lulu.com/print-jobs/statistics/") https = Net::HTTP.new(url.host, url.port) https.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = "Check Authentication menu" request["Cache-Control"] = "no-cache" response = https.request(request) puts response.read_body - lang: Node source: | var request = require('request'); var options = { 'method': 'GET', 'url': 'https://api.lulu.com/print-jobs/statistics/', 'headers': { 'Authorization': 'Check Authentication menu', 'Cache-Control': 'no-cache' } }; request(options, function (error, response) { if (error) throw new Error(error); console.log(response.body); }); - lang: Java source: | Unirest.setTimeouts(0, 0); HttpResponse<String> response = Unirest.get("https://api.lulu.com/print-jobs/statistics/") .header("Authorization", "Check Authentication menu") .header("Cache-Control", "no-cache") .asString(); - lang: Javascript source: | var myHeaders = new Headers(); myHeaders.append("Authorization", "Check Authentication menu"); myHeaders.append("Cache-Control", "no-cache"); var requestOptions = { method: 'GET', headers: myHeaders, redirect: 'follow' }; fetch("https://api.lulu.com/print-jobs/statistics/", requestOptions) .then(response => response.text()) .then(result => console.log(result)) .catch(error => console.log('error', error)); - lang: cURL source: | curl --location 'https://api.lulu.com/print-jobs/statistics/' \ --header 'Authorization: Check Authentication menu' \ --header 'Cache-Control: no-cache' /print-jobs/{id}/: get: description: Retrieve a single Print-Job by id. operationId: Print-Jobs_read parameters: - description: Id of the resource in: path name: id required: true schema: type: string responses: 200: content: application/json: schema: description: The extended version of a Print-Job resource that is returned by the detail endpoint properties: child_job_ids: description: The ids of reprints of this Print-Job. Requires role 'print.print-job-reprint' items: format: int64 type: number readOnly: true type: array items: description: The line items of a Print-Job, defining it's Printables and their quantities. The property name 'line_items' can be used instead. items: description: The extended version of a Print-JobLineItem resource that is returned by the detail endpoint properties: reprint: description: This object contains additional informations in case the job is a reprint of another Print-Job. Require the role 'print.print-job-reprint' properties: defect: description: The categorical reason for the reprint, according to our internal list. maxLength: 100 readOnly: true type: string required: - defect type: object required: - id - status - quantity type: object readOnly: true type: array line_items: description: The line items of a Print-Job, defining it's Printables and their quantities. The property name 'items' can be used instead. items: description: The extended version of a Print-JobLineItem resource that is returned by the detail endpoint properties: reprint: description: This object contains additional information in case the job is a reprint of another Print-Job. Require the role 'print.print-job-reprint' properties: defect: description: The categorical reason for the reprint, according to our internal list. maxLength: 100 readOnly: true type: string required: - defect type: object required: - id - status - quantity type: object readOnly: true type: array parent_job_id: description: If this Print-Job is a reprint, this is the id of the original job. Requires role 'print.print-job-reprint' format: int64 readOnly: true type: number required: - id - status - line_items - shipping_address - contact_email - shipping_level type: object example: child_job_ids: - 2019 contact_email: test@test.com costs: currency: USD line_item_costs: - cost_excl_discounts: '1.48' cost_excl_tax: '0.74' discounts: - amount: '14.80' description: Volume Discount 50% line_item_external_id: item-reference-1 line_item_id: 1 quantity: 20 tax_rate: '0.070000' total_cost_excl_discounts: '29.60' total_cost_excl_tax: '14.80' total_cost_incl_tax: '15.84' total_tax: '1.04' shipping_cost: tax_rate: '0.070000' total_cost_excl_tax: '65.99' total_cost_incl_tax: '70.61' total_tax: '4.62' total_cost_excl_tax: '80.79' total_cost_incl_tax: '86.45' total_discount_amount: '14.80' total_tax: '5.66' date_created: '2017-08-07T08:47:26.485456Z' date_modified: '2017-08-07T08:47:26.485490Z' estimated_shipping_dates: arrival_max: '2017-08-12' arrival_min: '2017-08-10' dispatch_max: '2017-08-09' dispatch_min: '2017-08-07' external_id: demo-time id: 1 line_items: - external_id: item-reference-1 id: 1 printable_id: 48efe280-d2e9-4334-b745-b0540fb628b4 printable_normalization: cover: job_id: 2 normalized_file: file_id: 7 filename: 139056_cover.pdf page_count: 1 source_file: file_id: 6 filename: 139056_cover.pdf source_md5sum: e78512c777e7f5841fe8f1992cefb898 source_url: https://www.dropbox.com/sh/p3zh22vzsaegiri/AADP367j0bTWlt8fCu-_tm2ia/161025/139056_cover.pdf?dl=1 interior: job_id: 2 normalized_file: file_id: 8 filename: thesis2.pdf page_count: 210 source_file: file_id: 5 filename: thesis2.pdf source_md5sum: 7f8af20c296747689756f8e310135d79 source_url: https://www.dropbox.com/sh/p3zh22vzsaegiri/AACOUn3LFKsITDzylh13bQpsa/161025/thesis2.pdf?dl=1 pod_package_id: 0600X0900BWSTDPB060UW444MXX quantity: 20 reprint: cost_center: PRINTER defect: Customer File/Source Defect description: They didn't leave enough margin and it got cut off printer_at_fault: BNB status: messages: {} name: ACCEPTED title: My Book order_id: '1234' parent_job_id: 1921 production_delay: 120 production_due_time: shipping_address: city: Lübeck country_code: DE is_business: false name: Hans Dampf phone_number: 844-212-0689 postcode: '23552' state_code: '' street1: Holstenstr. 40 street2: '' warnings: type: validation_warning path: external code: REPLACED message: 'street1: Holstenstr. 40 -> Holstenstraße 40' suggested_address: country_code: DE state_code: postcode: 23552 city: Lübeck street1: Holstenstraße 40" street2: shipping_level: MAIL shipping_option_level: MAIL status: changed: '2017-08-07T08:48:00.529399Z' message: Print-job was accepted and needs to be paid name: UNPAID tax_country: DE example: child_job_ids: - 2019 contact_email: test@test.com costs: currency: USD line_item_costs: - cost_excl_discounts: '1.48' cost_excl_tax: '0.74' discounts: - amount: '14.80' description: Volume Discount 50% line_item_external_id: item-reference-1 line_item_id: 1 quantity: 20 tax_rate: '0.070000' total_cost_excl_discounts: '29.60' total_cost_excl_tax: '14.80' total_cost_incl_tax: '15.84' total_tax: '1.04' shipping_cost: tax_rate: '0.070000' total_cost_excl_tax: '65.99' total_cost_incl_tax: '70.61' total_tax: '4.62' fulfillment_cost: total_cost_excl_tax: '0.75' total_cost_incl_tax: '0.81' total_tax: '0.06' tax_rate: '0.080000' total_cost_excl_tax: '80.79' total_cost_incl_tax: '86.45' total_discount_amount: '14.80' total_tax: '5.66' fees: - currency: USD fee_type: HANDLING_FEE sku: HANDLING_FEE_6 tax_rate: '0.088750' total_cost_excl_tax: '4.00' total_cost_incl_tax: '4.36' total_tax: '0.36' date_created: '2017-08-07T08:47:26.485456Z' date_modified: '2017-08-07T08:47:26.485490Z' estimated_shipping_dates: arrival_max: '2017-08-12' arrival_min: '2017-08-10' dispatch_max: '2017-08-09' dispatch_min: '2017-08-07' external_id: demo-time id: 1 line_items: - external_id: item-reference-1 id: 1 printable_id: 48efe280-d2e9-4334-b745-b0540fb628b4 printable_normalization: cover: job_id: 2 normalized_file: file_id: 7 filename: 139056_cover.pdf page_count: 1 source_file: file_id: 6 filename: 139056_cover.pdf source_md5sum: e78512c777e7f5841fe8f1992cefb898 source_url: https://www.dropbox.com/sh/p3zh22vzsaegiri/AADP367j0bTWlt8fCu-_tm2ia/161025/139056_cover.pdf?dl=1 interior: job_id: 2 normalized_file: file_id: 8 filename: thesis2.pdf page_count: 210 source_file: file_id: 5 filename: thesis2.pdf source_md5sum: 7f8af20c296747689756f8e310135d79 source_url: https://www.dropbox.com/sh/p3zh22vzsaegiri/AACOUn3LFKsITDzylh13bQpsa/161025/thesis2.pdf?dl=1 pod_package_id: 0600X0900BWSTDPB060UW444MXX quantity: 20 reprint: cost_center: PRINTER defect: Customer File/Source Defect description: They didn't leave enough margin and it got cut off printer_at_fault: BNB status: messages: {} name: ACCEPTED title: My Book order_id: '1234' parent_job_id: 1921 production_delay: 120 production_due_time: shipping_address: city: Lübeck country_code: DE is_business: false name: Hans Dampf phone_number: 844-212-0689 postcode: '23552' state_code: '' street1: Holstenstr. 40 street2: '' warnings: type: validation_warning path: external code: REPLACED message: 'street1: Holstenstr. 40 -> Holstenstraße 40' suggested_address: country_code: DE state_code: postcode: 23552 city: Lübeck street1: Holstenstraße 40" street2: shipping_level: MAIL shipping_option_level: MAIL status: changed: '2017-08-07T08:48:00.529399Z' message: Print-job was accepted and needs to be paid name: UNPAID tax_country: DE description: OK 401: $ref: '#/components/responses/Unauthorized' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' security: - oauth2: [] summary: Retrieve a single Print-Job tags: - Print-Jobs x-code-samples: - lang: Python source: | import requests url = "https://api.lulu.com/print-jobs/{id}/" payload = {} headers = { 'Authorization': 'Check Authentication menu', 'Cache-Control': 'no-cache' } response = requests.request("GET", url, headers=headers, data=payload) print(response.text) - lang: Ruby source: | require "uri" require "net/http" url = URI("https://api.lulu.com/print-jobs/{id}/") https = Net::HTTP.new(url.host, url.port) https.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = "Check Authentication menu" request["Cache-Control"] = "no-cache" response = https.request(request) puts response.read_body - lang: Node source: | var request = require('request'); var options = { 'method': 'GET', 'url': 'https://api.lulu.com/print-jobs/{id}/', 'headers': { 'Authorization': 'Check Authentication menu', 'Cache-Control': 'no-cache' } }; request(options, function (error, response) { if (error) throw new Error(error); console.log(response.body); }); - lang: Java source: | Unirest.setTimeouts(0, 0); HttpResponse<String> response = Unirest.get("https://api.lulu.com/print-jobs/{id}/") .header("Authorization", "Check Authentication menu") .header("Cache-Control", "no-cache") .asString(); - lang: Javascript source: | var myHeaders = new Headers(); myHeaders.append("Authorization", "Check Authentication menu"); myHeaders.append("Cache-Control", "no-cache"); var requestOptions = { method: 'GET', headers: myHeaders, redirect: 'follow' }; fetch("https://api.lulu.com/print-jobs/{id}/", requestOptions) .then(response => response.text()) .then(result => console.log(result)) .catch(error => console.log('error', error)); - lang: cURL source: | curl --location --globoff 'https://api.lulu.com/print-jobs/{id}/' \ --header 'Authorization: Check Authentication menu' \ --header 'Cache-Control: no-cache' /print-jobs/{id}/costs/: get: description: Sub-resource to retrieve only the costs of a Print-Job operationId: Print-Jobs_costs parameters: - description: Id of the resource in: path name: id required: true schema: type: string responses: 200: content: application/json: schema: description: Summary of the costs of a Print-Job properties: line_item_costs: description: List of cost summaries for each line item items: description: Costs for a Print-Job line item properties: line_item_external_id: description: External id of the line item readOnly: true type: string line_item_id: description: ID of the line item of this cost summary format: int64 readOnly: true type: number required: - line_item_id - line_item_external_id type: object readOnly: true type: array shipping_cost: description: Summary of the combined shipping and handling costs properties: tax_rate: description: Tax rate that was applied on shipping and handling costs as a decimal string readOnly: true type: string total_cost_excl_tax: description: Total shipping and handling costs excluding taxes as a decimal string readOnly: true type: string total_cost_incl_tax: description: Total shipping and handling costs including taxes as a decimal string readOnly: true type: string total_tax: description: Total amount of taxes on shipping and handling as a decimal string readOnly: true type: string readOnly: true type: object fulfillment_cost: description: Summary of the fulfillment fee costs type: object readOnly: true properties: total_cost_excl_tax: description: Total fulfillment fee costs excluding taxes as a decimal string type: string readOnly: true total_cost_incl_tax: description: Total fulfillment fee costs including taxes as a decimal string type: string readOnly: true total_tax: description: Total amount of taxes on fulfillment fee as a decimal string type: string readOnly: true tax_rate: description: Tax rate that was applied on fulfillment fee costs as a decimal string total_cost_excl_tax: description: Total costs of the job excluding taxes as a decimal string readOnly: true type: string total_cost_incl_tax: description: Total costs of the job including taxes as a decimal string readOnly: true type: string total_discount_amount: description: The total discount amount as a decimal string readOnly: true type: string total_tax: description: Total amount of taxes on the job as a decimal string readOnly: true type: string currency: description: Currency for the costs readOnly: true type: string fees: description: All fees applied to Print Job readOnly: true type: array items: properties: currency: description: Print Job Fee currency type: string readOnly: true fee_type: description: Print Job Fee type type: string readOnly: true sku: description: Print Job Fee unique sku type: string readOnly: true tax_rate: type: string description: The tax rate applied to the fee as a decimal string readOnly: true total_cost_excl_tax: type: string description: The total fee rate excluding tax as a decimal string readOnly: true total_cost_incl_tax: type: string description: The total fee rate including tax as a decimal string readOnly: true total_tax: type: string description: The total fee rate tax amount as a decimal string readOnly: true readOnly: true required: - shipping_cost - line_item_costs - total_cost_excl_tax - total_cost_incl_tax - total_discount_amount - total_tax - currency type: object example: currency: USD line_item_costs: - cost_excl_discounts: '1.48' cost_excl_tax: '0.74' discounts: - amount: '14.80' description: Volume Discount 50% line_item_external_id: item-reference-1 line_item_id: 1 quantity: 20 tax_rate: '0.070000' total_cost_excl_discounts: '29.60' total_cost_excl_tax: '14.80' total_cost_incl_tax: '15.84' total_tax: '1.04' shipping_cost: tax_rate: '0.070000' total_cost_excl_tax: '65.99' total_cost_incl_tax: '70.61' total_tax: '4.62' total_cost_excl_tax: '80.79' total_cost_incl_tax: '86.45' total_discount_amount: '14.80' total_tax: '5.66' example: currency: USD line_item_costs: - cost_excl_discounts: '1.48' cost_excl_tax: '0.74' discounts: - amount: '14.80' description: Volume Discount 50% line_item_external_id: item-reference-1 line_item_id: 1 quantity: 20 tax_rate: '0.070000' total_cost_excl_discounts: '29.60' total_cost_excl_tax: '14.80' total_cost_incl_tax: '15.84' total_tax: '1.04' shipping_cost: tax_rate: '0.070000' total_cost_excl_tax: '65.99' total_cost_incl_tax: '70.61' total_tax: '4.62' fulfillment_cost: total_cost_excl_tax: '0.75' total_cost_incl_tax: '0.81' total_tax: '0.06' tax_rate: '0.080000' total_cost_excl_tax: '80.79' total_cost_incl_tax: '86.45' total_discount_amount: '14.80' total_tax: '5.66' fees: - currency: USD fee_type: HANDLING_FEE sku: HANDLING_FEE_6 tax_rate: '0.088750' total_cost_excl_tax: '4.00' total_cost_incl_tax: '4.36' total_tax: '0.36' description: OK 401: $ref: '#/components/responses/Unauthorized' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' security: - oauth2: [] summary: Retrieve Print-Job Costs tags: - Print-Jobs x-code-samples: - lang: Python source: | import requests url = "https://api.lulu.com/print-jobs/{id}/costs/" payload = {} headers = { 'Authorization': 'Check Authentication menu', 'Cache-Control': 'no-cache' } response = requests.request("GET", url, headers=headers, data=payload) print(response.text) - lang: Ruby source: | require "uri" require "net/http" url = URI("https://api.lulu.com/print-jobs/{id}/costs/") https = Net::HTTP.new(url.host, url.port) https.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = "Check Authentication menu" request["Cache-Control"] = "no-cache" response = https.request(request) puts response.read_body - lang: Node source: | var request = require('request'); var options = { 'method': 'GET', 'url': 'https://api.lulu.com/print-jobs/{id}/costs/', 'headers': { 'Authorization': 'Check Authentication menu', 'Cache-Control': 'no-cache' } }; request(options, function (error, response) { if (error) throw new Error(error); console.log(response.body); }); - lang: Java source: | Unirest.setTimeouts(0, 0); HttpResponse<String> response = Unirest.get("https://api.lulu.com/print-jobs/{id}/costs/") .header("Authorization", "Check Authentication menu") .header("Cache-Control", "no-cache") .asString(); - lang: Javascript source: | var myHeaders = new Headers(); myHeaders.append("Authorization", "Check Authentication menu"); myHeaders.append("Cache-Control", "no-cache"); var requestOptions = { method: 'GET', headers: myHeaders, redirect: 'follow' }; fetch("https://api.lulu.com/print-jobs/{id}/costs/", requestOptions) .then(response => response.text()) .then(result => console.log(result)) .catch(error => console.log('error', error)); - lang: cURL source: | curl --location --globoff 'https://api.lulu.com/print-jobs/{id}/costs/' \ --header 'Authorization: Check Authentication menu' \ --header 'Cache-Control: no-cache' /print-jobs/{id}/status/: get: description: Sub-resource that represents the status of a Print-Job operationId: Print-Jobs_status_read parameters: - description: Id of the resource in: path name: id required: true schema: type: string responses: 200: content: application/json: schema: default: changed: '[creation timestamp]' name: CREATED description: Status object that contains the actual PrintJob processing status as well as some additional status related data properties: changed: default: '[status update timestamp]' description: '[ISO 8601](https://www.w3.org/TR/NOTE-datetime)) Timestamp of the latest status change' format: date-time readOnly: true type: string message: description: Status related message readOnly: true type: string name: default: CREATED description: | The actual processing status of the Print-Job. Valid status transitions: * `CREATED` -> `UNPAID`, `REJECTED` `CANCELED`, `PRODUCTION_READY` * `UNPAID` -> `PAYMENT_IN_PROGRESS`, `CANCELED`, `PRODUCTION_DELAYED` * `PAYMENT_IN_PROGRESS` -> `UNPAID`, `PRODUCTION_DELAYED` * `PRODUCTION_DELAYED` -> `PRODUCTION_READY`, `CANCELED` * `PRODUCTION_READY` -> `IN_PRODUCTION`, `PRODUCTION_DELAYED` * `IN_PRODUCTION` -> `SHIPPED`, `ERROR` enum: - CREATED - REJECTED - UNPAID - PAYMENT_IN_PROGRESS - PRODUCTION_READY - PRODUCTION_DELAYED - IN_PRODUCTION - ERROR - SHIPPED - CANCELED type: string required: - name - changed type: object example: changed: '2017-08-07T08:47:26.480493Z' message: Print-job is currently being validated name: CREATED example: changed: '2017-08-07T08:47:26.480493Z' message: Print-job is currently being validated name: CREATED description: OK 401: $ref: '#/components/responses/Unauthorized' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' security: - oauth2: [] summary: Retrieve Print-Job Status tags: - Print-Jobs x-code-samples: - lang: Python source: | import requests url = "https://api.lulu.com/print-jobs/{id}/status/" payload = {} headers = { 'Authorization': 'Check Authentication menu', 'Cache-Control': 'no-cache' } response = requests.request("GET", url, headers=headers, data=payload) print(response.text) - lang: Ruby source: | require "uri" require "net/http" url = URI("https://api.lulu.com/print-jobs/{id}/status/") https = Net::HTTP.new(url.host, url.port) https.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = "Check Authentication menu" request["Cache-Control"] = "no-cache" response = https.request(request) puts response.read_body - lang: Node source: | var request = require('request'); var options = { 'method': 'GET', 'url': 'https://api.lulu.com/print-jobs/{id}/status/', 'headers': { 'Authorization': 'Check Authentication menu', 'Cache-Control': 'no-cache' } }; request(options, function (error, response) { if (error) throw new Error(error); console.log(response.body); }); - lang: Java source: | Unirest.setTimeouts(0, 0); HttpResponse<String> response = Unirest.get("https://api.lulu.com/print-jobs/{id}/status/") .header("Authorization", "Check Authentication menu") .header("Cache-Control", "no-cache") .asString(); - lang: Javascript source: | var myHeaders = new Headers(); myHeaders.append("Authorization", "Check Authentication menu"); myHeaders.append("Cache-Control", "no-cache"); var requestOptions = { method: 'GET', headers: myHeaders, redirect: 'follow' }; fetch("https://api.lulu.com/print-jobs/{id}/status/", requestOptions) .then(response => response.text()) .then(result => console.log(result)) .catch(error => console.log('error', error)); - lang: cURL source: | curl --location --globoff 'https://api.lulu.com/print-jobs/{id}/status/' \ --header 'Authorization: Check Authentication menu' \ --header 'Cache-Control: no-cache' put: description: Cancel a single Print-Job by id. operationId: Print-Jobs_status_cancel parameters: - description: Id of the resource in: path name: id required: true schema: type: string requestBody: content: application/json: schema: properties: name: type: string description: Status to change to enum: [CANCELED] example: name: CANCELED responses: 200: content: application/json: schema: default: changed: '[creation timestamp]' name: CREATED description: Status object that contains the actual PrintJob processing status as well as some additional status related data properties: changed: default: '[status update timestamp]' description: '[ISO 8601](https://www.w3.org/TR/NOTE-datetime)) Timestamp of the latest status change' format: date-time readOnly: true type: string message: description: Status related message readOnly: true type: string name: default: CREATED description: | The actual processing status of the Print-Job. Valid status transitions: * `CREATED` -> `UNPAID`, `REJECTED` `CANCELED`, `PRODUCTION_READY` * `UNPAID` -> `PAYMENT_IN_PROGRESS`, `CANCELED`, `PRODUCTION_DELAYED` * `PAYMENT_IN_PROGRESS` -> `UNPAID`, `PRODUCTION_DELAYED` * `PRODUCTION_DELAYED` -> `PRODUCTION_READY`, `CANCELED` * `PRODUCTION_READY` -> `IN_PRODUCTION`, `PRODUCTION_DELAYED` * `IN_PRODUCTION` -> `SHIPPED`, `ERROR` enum: - CREATED - REJECTED - UNPAID - PAYMENT_IN_PROGRESS - PRODUCTION_READY - PRODUCTION_DELAYED - IN_PRODUCTION - ERROR - SHIPPED - CANCELED type: string required: - name - changed type: object example: changed: '2017-08-07T08:47:26.480493Z' message: Print-job was canceled name: CANCELED example: changed: '2017-08-07T08:47:26.480493Z' message: Print-job was canceled name: CANCELED description: OK 400: content: application/json: schema: example: [Invalid transition from PRODUCTION_READY to CANCELED requested] description: Bad Request 401: $ref: '#/components/responses/Unauthorized' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' security: - oauth2: [] summary: Cancel Print-Job tags: - Print-Jobs x-code-samples: - lang: Python source: | import requests import json url = "https://api.lulu.com/print-jobs/{id}/status/" payload = json.dumps({ "name": "CANCELED" }) headers = { 'Authorization': 'Check Authentication menu', 'Cache-Control': 'no-cache', 'Content-Type': 'application/json' } response = requests.request("POST", url, headers=headers, data=payload) print(response.text) - lang: Ruby source: | require "uri" require "json" require "net/http" url = URI("https://api.lulu.com/print-jobs/{id}/status/") https = Net::HTTP.new(url.host, url.port) https.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = "Check Authentication menu" request["Cache-Control"] = "no-cache" request["Content-Type"] = "application/json" request.body = JSON.dump({ "name": "CANCELED" }) response = https.request(request) puts response.read_body - lang: Node source: | var request = require('request'); var options = { 'method': 'POST', 'url': 'https://api.lulu.com/print-jobs/{id}/status/', 'headers': { 'Authorization': 'Check Authentication menu', 'Cache-Control': 'no-cache', 'Content-Type': 'application/json' }, body: JSON.stringify({ "name": "CANCELED" }) }; request(options, function (error, response) { if (error) throw new Error(error); console.log(response.body); }); - lang: Java source: | Unirest.setTimeouts(0, 0); HttpResponse<String> response = Unirest.post("https://api.lulu.com/print-jobs/{id}/status/") .header("Authorization", "Check Authentication menu") .header("Cache-Control", "no-cache") .header("Content-Type", "application/json") .body("{\n \"name\": \"CANCELED\"\n}") .asString(); - lang: Javascript source: | var myHeaders = new Headers(); myHeaders.append("Authorization", "Check Authentication menu"); myHeaders.append("Cache-Control", "no-cache"); myHeaders.append("Content-Type", "application/json"); var raw = JSON.stringify({ "name": "CANCELED" }); var requestOptions = { method: 'POST', headers: myHeaders, body: raw, redirect: 'follow' }; fetch("https://api.lulu.com/print-jobs/{id}/status/", requestOptions) .then(response => response.text()) .then(result => console.log(result)) .catch(error => console.log('error', error)); - lang: cURL source: | curl --location --globoff 'https://api.lulu.com/print-jobs/{id}/status/' \ --header 'Authorization: Check Authentication menu' \ --header 'Cache-Control: no-cache' \ --header 'Content-Type: application/json' \ --data '{ "name": "CANCELED" }' /shipping-options/: post: security: - {} # public, no authorization required - oauth2: - print-fulfillment.shipping-option summary: Retrieve List of Shipping Options description: | When integrating the Print API with your own shop, you might want to give customers an option to select among different shipping levels. This endpoint allows you to request available shipping methods (including cost) with minimal input data: * `country` * `page_count` * `quantity` * `pod_package_id` * `currency` only required if you don't want USD A valid `state_code` must be included in the shipping address to receive accurate shipping information. <details close> <summary>Countries that require valid state code (ISO 3166-1 alpha-2 code in parentheses)</summary> * United Arab Emirates (AE) * American Samoa (AS) * Australia (AU) * Brazil (BR) * Canada (CA) * China (CN) * Colombia (CO) * Costa Rica (CR) * Cayman Islands (KY) * Spain (ES) * Micronesia (FM) * Hong Kong (HK) * Honduras (HN) * Indonesia (ID) * India (IN) * Iraq (IQ) * Italy (IT) * Jamaica (JM) * Japan (JP) * Saint Kitts and Nevis (KN) * Korea (KR) * Mexico (MX) * Marshall Islands (MH) * Northern Mariana Islands (MP) * Nauru (NR) * Palau (PW) * Papua New Guinea (PG) * French Polynesia (PF) * Russian Federation (RU) * El Salvador (SV) * Somalia (SO) * Taiwan (TW) * United States Minor Outlying Islands (UM) * United States (US) * Venezuela (VE) * Virgin Islands, U.S. (VI) </details> You can further restrict shipping options that support post box delivery by adding `is_postbox=true` to your shipping address data. tags: - Shipping Options operationId: retrieve-shipping-options requestBody: content: application/json: schema: type: object properties: currency: description: Currency to base cost calculations on, defaults to USD. Available currencies are AUD, CAD, EUR, GBP, and USD. type: string example: USD line_items: description: The line items that should be calculated type: array items: properties: page_count: description: The page count of the book type: integer example: 200 pod_package_id: description: The id of the PodPackage of the book type: string example: 0550X0850FCPREPB080CW444GXX quantity: description: The quantity of books to base the calculations on type: number example: 1 required: - quantity - pod_package_id - page_count shipping_address: description: The shipping address for which shipping options will be found type: object properties: country: description: '[ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) country code' maxLength: 2 minLength: 2 type: string city: type: string is_business: default: false description: Only relevant for US addresses. Some US carriers don't deliver to business-addresses on Saturday. type: boolean is_postbox: default: false type: boolean name: description: Full name of the person, including first and last name. type: string organization: description: Name of an organization. Required if no person name is given. type: string phone_number: description: 'Validation Regex Pattern: `^\+?[\d\s\-.\/()]{8,20}$`' maxLength: 20 type: string postcode: maxLength: 64 type: string state: description: 2 or 3 letter state codes (officially called [ISO-3166-2 subdivision codes](https://en.wikipedia.org/wiki/ISO_3166-2)). type: string street1: description: First address line type: string street2: description: Second address line type: string required: - country example: currency: USD line_items: - page_count: 32 pod_package_id: 0600X0900BWSTDPB060UW444MXX quantity: 1 - page_count: 324 pod_package_id: 0850X1100FCSTDPB060UW444MXX quantity: 2 shipping_address: city: Washington country: US postcode: '20540' state_code: DC street1: 101 Independence Ave SE required: - line_items - shipping_address responses: 200: content: application/json: schema: type: array items: description: A shipping option defines a concrete shipping configuration that an order can be shipped with properties: business_only: default: false description: Delivery only on working days readOnly: true type: boolean cost_excl_tax: description: The shipping cost excluding taxes as a decimal string. This attribute will only be set on the detail endpoint representation, and only if the query parameters 'quantity' and 'currency' are provided readOnly: true type: string currency: description: Currency of `cost_excl_tax` type: string home_only: default: false description: Delivery also on non working days readOnly: true type: boolean id: format: int64 readOnly: true type: number level: default: MAIL enum: - MAIL - PRIORITY_MAIL - GROUND_HD - GROUND_BUS - GROUND - EXPEDITED - EXPRESS readOnly: true type: string max_delivery_date: description: Latest estimated delivery date in ([ISO 8601](https://en.wikipedia.org/wiki/ISO_8601)) format. When no `pod_package_id` is provided in the request, the estimate is based on product types with the longest estimated production time (usually hardcover books). readOnly: true type: string max_dispatch_date: description: Latest estimated dispatch (handover to carrier) date in ([ISO 8601](https://en.wikipedia.org/wiki/ISO_8601)) format. When no `pod_package_id` is provided in the request, the estimate is based on product types with the longest estimated production time (usually hardcover books). readOnly: true type: string min_delivery_date: description: Earliest estimated delivery date in ([ISO 8601](https://en.wikipedia.org/wiki/ISO_8601)) format. When no `pod_package_id` is provided in the request, the estimate is based on product types with the shortest estimated production time (usually non-hardcover books). readOnly: true type: string min_dispatch_date: description: Earliest estimated dispatch (handover to carrier) date in ([ISO 8601](https://en.wikipedia.org/wiki/ISO_8601)) format. When no `pod_package_id` is provided in the request, the estimate is based on product types with the shortest estimated production time (usually non-hardcover books). readOnly: true type: string postbox_ok: default: false description: Support of delivery to postboxes readOnly: true type: boolean total_days_max: description: Highest estimate of total business days from start of production to delivery. When no `pod_package_id` is provided in the request, the estimate is based on product types with the longest estimated production time (usually hardcover books). format: int32 readOnly: true type: number total_days_min: description: Lowest estimate of total business days from start of production to delivery. When no `pod_package_id` is provided in the request, the estimate is based on product types with the shortest estimated production time (usually non-hardcover books). format: int32 readOnly: true type: number traceable: default: false description: If this shipping provides the possibility to create a tracking link readOnly: true type: boolean transit_time: default: 0 description: Average transit time in days format: int32 readOnly: true type: number required: - id - level - postbox_ok - home_only - business_only - traceable - transit_time - shipping_buffer - min_delivery_date - max_delivery_date type: object example: business_only: false cost_excl_tax: currency: EUR home_only: false id: 21 level: EXPRESS max_delivery_date: '2018-02-01' max_dispatch_date: '2018-01-28' min_delivery_date: '2018-01-29' min_dispatch_date: '2018-01-25' postbox_ok: false shipping_buffer: 0 total_days_max: 8 total_days_min: 6 traceable: true transit_time: 4 description: OK 401: $ref: '#/components/responses/Unauthorized' 403: $ref: '#/components/responses/Forbidden' x-code-samples: - lang: Python source: | import requests import json url = "https://api.sandbox.lulu.com/shipping-options/" payload = json.dumps({ "currency": "USD", "line_items": [ { "page_count": 32, "pod_package_id": "0600X0900BWSTDPB060UW444MXX", "quantity": 1 }, { "page_count": 324, "pod_package_id": "0850X1100FCSTDPB060UW444MXX", "quantity": 2 } ], "shipping_address": { "city": "Washington", "country": "US", "postcode": "20540", "state_code": "DC", "street1": "101 Independence Ave SE" } }) headers = { 'Authorization': 'Check Authentication menu', 'Cache-Control': 'no-cache', 'Content-Type': 'application/json' } response = requests.request("POST", url, headers=headers, data=payload) print(response.text) - lang: Ruby source: | require "uri" require "json" require "net/http" url = URI("https://api.sandbox.lulu.com/shipping-options/") https = Net::HTTP.new(url.host, url.port) https.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = "Check Authentication menu" request["Cache-Control"] = "no-cache" request["Content-Type"] = "application/json" request.body = JSON.dump({ "currency": "USD", "line_items": [ { "page_count": 32, "pod_package_id": "0600X0900BWSTDPB060UW444MXX", "quantity": 1 }, { "page_count": 324, "pod_package_id": "0850X1100FCSTDPB060UW444MXX", "quantity": 2 } ], "shipping_address": { "city": "Washington", "country": "US", "postcode": "20540", "state_code": "DC", "street1": "101 Independence Ave SE" } }) response = https.request(request) puts response.read_body - lang: Node source: | var request = require('request'); var options = { 'method': 'POST', 'url': 'https://api.sandbox.lulu.com/shipping-options/', 'headers': { 'Authorization': 'Check Authentication menu', 'Cache-Control': 'no-cache', 'Content-Type': 'application/json' }, body: JSON.stringify({ "currency": "USD", "line_items": [ { "page_count": 32, "pod_package_id": "0600X0900BWSTDPB060UW444MXX", "quantity": 1 }, { "page_count": 324, "pod_package_id": "0850X1100FCSTDPB060UW444MXX", "quantity": 2 } ], "shipping_address": { "city": "Washington", "country": "US", "postcode": "20540", "state_code": "DC", "street1": "101 Independence Ave SE" } }) }; request(options, function (error, response) { if (error) throw new Error(error); console.log(response.body); }); - lang: Java source: | Unirest.setTimeouts(0, 0); HttpResponse<String> response = Unirest.post("https://api.sandbox.lulu.com/shipping-options/") .header("Authorization", "Check Authentication menu") .header("Cache-Control", "no-cache") .header("Content-Type", "application/json") .body("{\n \"currency\": \"USD\",\n \"line_items\": [\n {\n \"page_count\": 32,\n \"pod_package_id\": \"0600X0900BWSTDPB060UW444MXX\",\n \"quantity\": 1\n },\n {\n \"page_count\": 324,\n \"pod_package_id\": \"0850X1100FCSTDPB060UW444MXX\",\n \"quantity\": 2\n }\n ],\n \"shipping_address\": {\n \"city\": \"Washington\",\n \"country\": \"US\",\n \"postcode\": \"20540\",\n \"state_code\": \"DC\",\n \"street1\": \"101 Independence Ave SE\"\n }\n}") .asString(); - lang: Javascript source: | var myHeaders = new Headers(); myHeaders.append("Authorization", "Check Authentication menu"); myHeaders.append("Cache-Control", "no-cache"); myHeaders.append("Content-Type", "application/json"); var raw = JSON.stringify({ "currency": "USD", "line_items": [ { "page_count": 32, "pod_package_id": "0600X0900BWSTDPB060UW444MXX", "quantity": 1 }, { "page_count": 324, "pod_package_id": "0850X1100FCSTDPB060UW444MXX", "quantity": 2 } ], "shipping_address": { "city": "Washington", "country": "US", "postcode": "20540", "state_code": "DC", "street1": "101 Independence Ave SE" } }); var requestOptions = { method: 'POST', headers: myHeaders, body: raw, redirect: 'follow' }; fetch("https://api.sandbox.lulu.com/shipping-options/", requestOptions) .then(response => response.text()) .then(result => console.log(result)) .catch(error => console.log('error', error)); - lang: cURL source: | curl --location 'https://api.sandbox.lulu.com/shipping-options/' \ --header 'Authorization: Check Authentication menu' \ --header 'Cache-Control: no-cache' \ --header 'Content-Type: application/json' \ --data '{ "currency": "USD", "line_items": [ { "page_count": 32, "pod_package_id": "0600X0900BWSTDPB060UW444MXX", "quantity": 1 }, { "page_count": 324, "pod_package_id": "0850X1100FCSTDPB060UW444MXX", "quantity": 2 } ], "shipping_address": { "city": "Washington", "country": "US", "postcode": "20540", "state_code": "DC", "street1": "101 Independence Ave SE" } }' /webhooks/: post: security: - oauth2: [] summary: Subscribe to webhooks description: | Subscribe to Print API webhooks by passing a list of topics that you want to subscribe to and the URL where webhooks should be sent. tags: - Webhooks operationId: subscribe-webhooks requestBody: content: application/json: schema: type: object properties: topics: description: List of webhook topics type: array items: type: string enum: - PRINT_JOB_STATUS_CHANGED example: [PRINT_JOB_STATUS_CHANGED] url: description: URL where webhook should be sent type: string example: https://www.webhooks-consumer.com/ example: topics: [PRINT_JOB_STATUS_CHANGED] url: https://www.webhooks-consumer.com/ required: - topics - url responses: 201: content: application/json: schema: type: object properties: id: description: Webhook ID readOnly: true format: uuid type: string is_active: description: Indicates if webhook is active readOnly: false type: boolean topics: description: List of subscribed topics type: array readOnly: false items: type: string enum: - PRINT_JOB_STATUS_CHANGED url: description: Webhook URL readOnly: false type: string required: - id - is_active - topics - url example: id: f370d09b-912a-4667-9890-ed9bd0c32166 is_active: true topics: [PRINT_JOB_STATUS_CHANGED] url: https://www.webhooks-consumer.com/ description: OK 400: content: application/json: schema: example: url: - Enter a valid URL. topics: - No matching enum type. title: Bad Request example: url: - Enter a valid URL. topics: - No matching enum type. description: Bad Request 401: $ref: '#/components/responses/Unauthorized' 403: $ref: '#/components/responses/Forbidden' x-code-samples: - lang: Python source: | import requests import json url = "https://api.lulu.com/webhooks/" payload = json.dumps({ "topics": [ "PRINT_JOB_STATUS_CHANGED" ], "url": "https://www.webhooks-consumer.com/" }) headers = { 'Authorization': 'Check Authentication menu', 'Cache-Control': 'no-cache', 'Content-Type': 'application/json' } response = requests.request("POST", url, headers=headers, data=payload) print(response.text) - lang: Ruby source: | require "uri" require "json" require "net/http" url = URI("https://api.lulu.com/webhooks/") https = Net::HTTP.new(url.host, url.port) https.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = "Check Authentication menu" request["Cache-Control"] = "no-cache" request["Content-Type"] = "application/json" request.body = JSON.dump({ "topics": [ "PRINT_JOB_STATUS_CHANGED" ], "url": "https://www.webhooks-consumer.com/" }) response = https.request(request) puts response.read_body - lang: Node source: | var request = require('request'); var options = { 'method': 'POST', 'url': 'https://api.lulu.com/webhooks/', 'headers': { 'Authorization': 'Check Authentication menu', 'Cache-Control': 'no-cache', 'Content-Type': 'application/json' }, body: JSON.stringify({ "topics": [ "PRINT_JOB_STATUS_CHANGED" ], "url": "https://www.webhooks-consumer.com/" }) }; request(options, function (error, response) { if (error) throw new Error(error); console.log(response.body); }); - lang: Java source: | Unirest.setTimeouts(0, 0); HttpResponse<String> response = Unirest.post("https://api.lulu.com/webhooks/") .header("Authorization", "Check Authentication menu") .header("Cache-Control", "no-cache") .header("Content-Type", "application/json") .body("{\n \"topics\": [\"PRINT_JOB_STATUS_CHANGED\"],\n \"url\": \"https://www.webhooks-consumer.com/\"\n}") .asString(); - lang: Javascript source: | var myHeaders = new Headers(); myHeaders.append("Authorization", "Check Authentication menu"); myHeaders.append("Cache-Control", "no-cache"); myHeaders.append("Content-Type", "application/json"); var raw = JSON.stringify({ "topics": [ "PRINT_JOB_STATUS_CHANGED" ], "url": "https://www.webhooks-consumer.com/" }); var requestOptions = { method: 'POST', headers: myHeaders, body: raw, redirect: 'follow' }; fetch("https://api.lulu.com/webhooks/", requestOptions) .then(response => response.text()) .then(result => console.log(result)) .catch(error => console.log('error', error)); - lang: cURL source: | curl --location 'https://api.lulu.com/webhooks/' \ --header 'Authorization: Check Authentication menu' \ --header 'Cache-Control: no-cache' \ --header 'Content-Type: application/json' \ --data '{ "topics": ["PRINT_JOB_STATUS_CHANGED"], "url": "https://www.webhooks-consumer.com/" }' get: security: - oauth2: [] summary: Retrieve list of webhooks description: | Retrieve a list of all owned webhooks. tags: - Webhooks operationId: retrieve-webhooks responses: 200: content: application/json: schema: type: object properties: count: example: 3 type: integer next: example: https://api.lulu.com/resources/?page=3&page_size=1 type: string previous: example: https://api.lulu.com/resources/?page=1&page_size=1 type: string results: type: array items: type: object properties: id: description: Webhook ID readOnly: true format: uuid type: string is_active: description: Indicates if webhook is active readOnly: false type: boolean topics: description: List of subscribed topics type: array readOnly: false items: type: string enum: - PRINT_JOB_STATUS_CHANGED url: description: Webhook URL readOnly: false type: string required: - id - is_active - topics - url example: id: f370d09b-912a-4667-9890-ed9bd0c32166 is_active: true topics: [PRINT_JOB_STATUS_CHANGED] url: https://www.webhooks-consumer.com/ required: - results - count description: OK 401: $ref: '#/components/responses/Unauthorized' 403: $ref: '#/components/responses/Forbidden' x-code-samples: - lang: Python source: | import requests url = "https://api.lulu.com/webhooks/" payload = {} headers = { 'Authorization': 'Check Authentication menu', 'Cache-Control': 'no-cache' } response = requests.request("GET", url, headers=headers, data=payload) print(response.text) - lang: Ruby source: | require "uri" require "net/http" url = URI("https://api.lulu.com/webhooks/") https = Net::HTTP.new(url.host, url.port) https.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = "Check Authentication menu" request["Cache-Control"] = "no-cache" response = https.request(request) puts response.read_body - lang: Node source: | var request = require('request'); var options = { 'method': 'GET', 'url': 'https://api.lulu.com/webhooks/', 'headers': { 'Authorization': 'Check Authentication menu', 'Cache-Control': 'no-cache' } }; request(options, function (error, response) { if (error) throw new Error(error); console.log(response.body); }); - lang: Java source: | Unirest.setTimeouts(0, 0); HttpResponse<String> response = Unirest.get("https://api.lulu.com/webhooks/") .header("Authorization", "Check Authentication menu") .header("Cache-Control", "no-cache") .asString(); - lang: Javascript source: | var myHeaders = new Headers(); myHeaders.append("Authorization", "Check Authentication menu"); myHeaders.append("Cache-Control", "no-cache"); var requestOptions = { method: 'GET', headers: myHeaders, redirect: 'follow' }; fetch("https://api.lulu.com/webhooks/", requestOptions) .then(response => response.text()) .then(result => console.log(result)) .catch(error => console.log('error', error)); - lang: cURL source: | curl --location 'https://api.lulu.com/webhooks/' \ --header 'Authorization: Check Authentication menu' \ --header 'Cache-Control: no-cache' /webhooks/{id}/: get: security: - oauth2: [] summary: Retrieve single webhook tags: - Webhooks operationId: retrieve-webhook parameters: - description: Id of the resource in: path name: id required: true schema: type: string responses: 200: content: application/json: schema: type: object properties: id: description: Webhook ID readOnly: true format: uuid type: string is_active: description: Indicates if webhook is active readOnly: false type: boolean topics: description: List of subscribed topics type: array readOnly: false items: type: string enum: - PRINT_JOB_STATUS_CHANGED url: description: Webhook URL readOnly: false type: string required: - id - is_active - topics - url example: id: f370d09b-912a-4667-9890-ed9bd0c32166 is_active: true topics: [PRINT_JOB_STATUS_CHANGED] url: https://www.webhooks-consumer.com/ description: OK 401: $ref: '#/components/responses/Unauthorized' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' x-code-samples: - lang: Python source: | import requests url = "https://api.lulu.com/webhooks/{id}/" payload = {} headers = { 'Authorization': 'Check Authentication menu', 'Cache-Control': 'no-cache' } response = requests.request("GET", url, headers=headers, data=payload) print(response.text) - lang: Ruby source: | require "uri" require "net/http" url = URI("https://api.lulu.com/webhooks/{id}/") https = Net::HTTP.new(url.host, url.port) https.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = "Check Authentication menu" request["Cache-Control"] = "no-cache" response = https.request(request) puts response.read_body - lang: Node source: | var request = require('request'); var options = { 'method': 'GET', 'url': 'https://api.lulu.com/webhooks/{id}/', 'headers': { 'Authorization': 'Check Authentication menu', 'Cache-Control': 'no-cache' } }; request(options, function (error, response) { if (error) throw new Error(error); console.log(response.body); }); - lang: Java source: | Unirest.setTimeouts(0, 0); HttpResponse<String> response = Unirest.get("https://api.lulu.com/webhooks/{id}/") .header("Authorization", "Check Authentication menu") .header("Cache-Control", "no-cache") .asString(); - lang: Javascript source: | var myHeaders = new Headers(); myHeaders.append("Authorization", "Check Authentication menu"); myHeaders.append("Cache-Control", "no-cache"); var requestOptions = { method: 'GET', headers: myHeaders, redirect: 'follow' }; fetch("https://api.lulu.com/webhooks/{id}/", requestOptions) .then(response => response.text()) .then(result => console.log(result)) .catch(error => console.log('error', error)); - lang: cURL source: | curl --location --globoff 'https://api.lulu.com/webhooks/{id}/' \ --header 'Authorization: Check Authentication menu' \ --header 'Cache-Control: no-cache' patch: security: - oauth2: [] summary: Update webhook description: | Update owned webhook data: URL, list of subscribed topics. You can also activate or deactivate it. tags: - Webhooks operationId: update-webhook parameters: - description: Id of the resource in: path name: id required: true schema: type: string requestBody: content: application/json: schema: type: object properties: topics: description: List of webhook topics type: array items: type: string enum: - PRINT_JOB_STATUS_CHANGED example: [PRINT_JOB_STATUS_CHANGED] url: description: URL where webhook should be sent type: string example: https://www.webhooks-consumer.com/updated/ is_active: description: Activate or deactivate webhook type: boolean example: true example: url: https://www.webhooks-consumer.com/updated/ responses: 200: content: application/json: schema: type: object properties: id: description: Webhook ID readOnly: true format: uuid type: string is_active: description: Indicates if webhook is active readOnly: false type: boolean topics: description: List of subscribed topics type: array readOnly: false items: type: string enum: - PRINT_JOB_STATUS_CHANGED url: description: Webhook URL readOnly: false type: string required: - id - is_active - topics - url example: id: f370d09b-912a-4667-9890-ed9bd0c32166 is_active: true topics: [PRINT_JOB_STATUS_CHANGED] url: https://www.webhooks-consumer.com/updated/ description: OK 400: content: application/json: schema: example: url: - Enter a valid URL. topics: - No matching enum type. title: Bad Request example: url: - Enter a valid URL. topics: - No matching enum type. description: Bad Request 401: $ref: '#/components/responses/Unauthorized' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' x-code-samples: - lang: Python source: | import requests import json url = "https://api.lulu.com/webhooks/{id}/" payload = json.dumps({ "url": "https://www.webhooks-consumer.com/updated/" }) headers = { 'Authorization': 'Check Authentication menu', 'Cache-Control': 'no-cache', 'Content-Type': 'application/json' } response = requests.request("PATCH", url, headers=headers, data=payload) print(response.text) - lang: Ruby source: | require "uri" require "json" require "net/http" url = URI("https://api.lulu.com/webhooks/{id}/") https = Net::HTTP.new(url.host, url.port) https.use_ssl = true request = Net::HTTP::Patch.new(url) request["Authorization"] = "Check Authentication menu" request["Cache-Control"] = "no-cache" request["Content-Type"] = "application/json" request.body = JSON.dump({ "url": "https://www.webhooks-consumer.com/updated/" }) response = https.request(request) puts response.read_body - lang: Node source: | var request = require('request'); var options = { 'method': 'PATCH', 'url': 'https://api.lulu.com/webhooks/{id}/', 'headers': { 'Authorization': 'Check Authentication menu', 'Cache-Control': 'no-cache', 'Content-Type': 'application/json' }, body: JSON.stringify({ "url": "https://www.webhooks-consumer.com/updated/" }) }; request(options, function (error, response) { if (error) throw new Error(error); console.log(response.body); }); - lang: Java source: | Unirest.setTimeouts(0, 0); HttpResponse<String> response = Unirest.patch("https://api.lulu.com/webhooks/{id}/") .header("Authorization", "Check Authentication menu") .header("Cache-Control", "no-cache") .header("Content-Type", "application/json") .body("{\n \"url\": \"https://www.webhooks-consumer.com/updated/\"\n}") .asString(); - lang: Javascript source: | var myHeaders = new Headers(); myHeaders.append("Authorization", "Check Authentication menu"); myHeaders.append("Cache-Control", "no-cache"); myHeaders.append("Content-Type", "application/json"); var raw = JSON.stringify({ "url": "https://www.webhooks-consumer.com/updated/" }); var requestOptions = { method: 'PATCH', headers: myHeaders, body: raw, redirect: 'follow' }; fetch("https://api.lulu.com/webhooks/{id}/", requestOptions) .then(response => response.text()) .then(result => console.log(result)) .catch(error => console.log('error', error)); - lang: cURL source: | curl --location --globoff --request PATCH 'https://api.lulu.com/webhooks/{id}/' \ --header 'Authorization: Check Authentication menu' \ --header 'Cache-Control: no-cache' \ --header 'Content-Type: application/json' \ --data '{ "url": "https://www.webhooks-consumer.com/updated/" }' delete: security: - oauth2: [] summary: Delete webhook tags: - Webhooks operationId: delete-webhook parameters: - description: Id of the resource in: path name: id required: true schema: type: string responses: 204: description: No Content 401: $ref: '#/components/responses/Unauthorized' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' x-code-samples: - lang: Python source: | import requests url = "https://api.lulu.com/webhooks/{id}/" payload = {} headers = { 'Authorization': 'Check Authentication menu', 'Cache-Control': 'no-cache' } response = requests.request("DELETE", url, headers=headers, data=payload) print(response.text) - lang: Ruby source: | require "uri" require "net/http" url = URI("https://api.lulu.com/webhooks/{id}/") https = Net::HTTP.new(url.host, url.port) https.use_ssl = true request = Net::HTTP::Delete.new(url) request["Authorization"] = "Check Authentication menu" request["Cache-Control"] = "no-cache" response = https.request(request) puts response.read_body - lang: Node source: | var request = require('request'); var options = { 'method': 'DELETE', 'url': 'https://api.lulu.com/webhooks/{id}/', 'headers': { 'Authorization': 'Check Authentication menu', 'Cache-Control': 'no-cache' } }; request(options, function (error, response) { if (error) throw new Error(error); console.log(response.body); }); - lang: Java source: | Unirest.setTimeouts(0, 0); HttpResponse<String> response = Unirest.delete("https://api.lulu.com/webhooks/{id}/") .header("Authorization", "Check Authentication menu") .header("Cache-Control", "no-cache") .asString(); - lang: Javascript source: | var myHeaders = new Headers(); myHeaders.append("Authorization", "Check Authentication menu"); myHeaders.append("Cache-Control", "no-cache"); var requestOptions = { method: 'DELETE', headers: myHeaders, redirect: 'follow' }; fetch("https://api.lulu.com/webhooks/{id}/", requestOptions) .then(response => response.text()) .then(result => console.log(result)) .catch(error => console.log('error', error)); - lang: cURL source: | curl --location --globoff --request DELETE 'https://api.lulu.com/webhooks/{id}/' \ --header 'Authorization: Check Authentication menu' \ --header 'Cache-Control: no-cache' /webhooks/{id}/test-submission/{topic}/: post: security: - oauth2: [] summary: Test webhook topic submission description: Sends payload with selected topic test data to webhook URL. tags: - Webhooks operationId: test-webhook-submission parameters: - description: Id of the resource in: path name: id required: true schema: type: string - description: Topic to test in: path name: topic required: true schema: type: string responses: 200: content: application/json: schema: type: string example: Test webhook submission queued description: OK 400: content: application/json: schema: example: ["Invalid topic. Subscribed topics are: ['PRINT_JOB_STATUS_CHANGED']."] title: Bad Request example: ["Invalid topic. Subscribed topics are: ['PRINT_JOB_STATUS_CHANGED']."] description: Bad Request 401: $ref: '#/components/responses/Unauthorized' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' x-code-samples: - lang: Python source: | import requests url = "https://api.lulu.com/webhooks/{id}/test-submission/{topic}/" payload = {} headers = { 'Authorization': 'Check Authentication menu', 'Cache-Control': 'no-cache' } response = requests.request("POST", url, headers=headers, data=payload) print(response.text) - lang: Ruby source: | require "uri" require "net/http" url = URI("https://api.lulu.com/webhooks/{id}/test-submission/{topic}/") https = Net::HTTP.new(url.host, url.port) https.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = "Check Authentication menu" request["Cache-Control"] = "no-cache" response = https.request(request) puts response.read_body - lang: Node source: | var request = require('request'); var options = { 'method': 'POST', 'url': 'https://api.lulu.com/webhooks/{id}/test-submission/{topic}/', 'headers': { 'Authorization': 'Check Authentication menu', 'Cache-Control': 'no-cache' } }; request(options, function (error, response) { if (error) throw new Error(error); console.log(response.body); }); - lang: Java source: | Unirest.setTimeouts(0, 0); HttpResponse<String> response = Unirest.post("https://api.lulu.com/webhooks/{id}/test-submission/{topic}/") .header("Authorization", "Check Authentication menu") .header("Cache-Control", "no-cache") .asString(); - lang: Javascript source: | var myHeaders = new Headers(); myHeaders.append("Authorization", "Check Authentication menu"); myHeaders.append("Cache-Control", "no-cache"); var requestOptions = { method: 'POST', headers: myHeaders, redirect: 'follow' }; fetch("https://api.lulu.com/webhooks/{id}/test-submission/{topic}/", requestOptions) .then(response => response.text()) .then(result => console.log(result)) .catch(error => console.log('error', error)); - lang: cURL source: | curl --location --globoff --request POST 'https://api.lulu.com/webhooks/{id}/test-submission/{topic}/' \ --header 'Authorization: Check Authentication menu' \ --header 'Cache-Control: no-cache' /webhook-submissions/: get: security: - oauth2: [] summary: Retrieve list of webhook submissions parameters: - description: 'Result page, default: 1' in: query name: page schema: type: integer - description: The default is 100. in: query name: page_size schema: type: integer - description: Filter by creation timestamp after the given ([ISO 8601](https://www.w3.org/TR/NOTE-datetime)) timestamp. in: query name: created_after required: false schema: type: string - description: Filter by creation timestamp before the given ([ISO 8601](https://www.w3.org/TR/NOTE-datetime)) timestamp. in: query name: created_before required: false schema: type: string - description: Filter by is_success name: is_success in: query required: false schema: type: boolean - description: Filter by submission response code in: query name: response_code required: false schema: type: string - description: Filter by webhook ID in: query name: webhook_id required: false schema: format: uuid type: string description: Retrieve a list of all submissions of owned webhooks. tags: - Webhooks operationId: retrieve-webhook-submissions responses: 200: content: application/json: schema: type: object properties: count: example: 3 type: integer next: example: https://api.lulu.com/resources/?page=3&page_size=1 type: string previous: example: https://api.lulu.com/resources/?page=1&page_size=1 type: string results: type: array items: type: object properties: date_created: type: string readOnly: true description: '[ISO 8601](https://www.w3.org/TR/NOTE-datetime) creation timestamp' format: date-time example: 2023-05-31T10:00:00.414000Z date_modified: type: string readOnly: true description: '[ISO 8601](https://www.w3.org/TR/NOTE-datetime) modification timestamp' format: date-time example: 2023-05-31T10:00:00.414000Z payload: type: object readOnly: true description: Payload sent in webhook submission body example: {} topic: type: string enum: - PRINT_JOB_STATUS_CHANGED readOnly: true description: Submission topic example: PRINT_JOB_STATUS_CHANGED is_success: type: boolean readOnly: true description: Indicates if submission succeeded or not example: true response_code: type: number readOnly: true description: Response code of submission example: 200 attempts: type: number readOnly: true description: Count of submission attempts example: 1 webhook: type: object readOnly: true description: Related webhook data properties: id: description: Webhook ID readOnly: true format: uuid type: string is_active: description: Indicates if webhook is active readOnly: false type: boolean topics: description: List of subscribed topics type: array readOnly: false items: type: string enum: - PRINT_JOB_STATUS_CHANGED url: description: Webhook URL readOnly: false type: string required: - id - is_active - topics - url example: {} required: - date_created - date_modified - payload - topic - is_success - attempts - webhook example: date_created: '2023-05-31T10:00:00.414Z' date_modified: '2023-05-31T10:00:00.414Z' payload: data: {} topic: PRINT_JOB_STATUS_CHANGED topic: PRINT_JOB_STATUS_CHANGED is_success: true response_code: 200 attempts: 1 webhook: id: f370d09b-912a-4667-9890-ed9bd0c32166 is_active: true topics: [PRINT_JOB_STATUS_CHANGED] url: https://www.webhooks-consumer.com/ required: - results - count description: OK 401: $ref: '#/components/responses/Unauthorized' 403: $ref: '#/components/responses/Forbidden' x-code-samples: - lang: Python source: | import requests url = "https://api.lulu.com/webhook-submissions/" payload = {} headers = { 'Authorization': 'Check Authentication menu', 'Cache-Control': 'no-cache' } response = requests.request("GET", url, headers=headers, data=payload) print(response.text) - lang: Ruby source: | require "uri" require "net/http" url = URI("https://api.lulu.com/webhook-submissions/") https = Net::HTTP.new(url.host, url.port) https.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = "Check Authentication menu" request["Cache-Control"] = "no-cache" response = https.request(request) puts response.read_body - lang: Node source: | var request = require('request'); var options = { 'method': 'GET', 'url': 'https://api.lulu.com/webhook-submissions/', 'headers': { 'Authorization': 'Check Authentication menu', 'Cache-Control': 'no-cache' } }; request(options, function (error, response) { if (error) throw new Error(error); console.log(response.body); }); - lang: Java source: | Unirest.setTimeouts(0, 0); HttpResponse<String> response = Unirest.get("https://api.lulu.com/webhook-submissions/") .header("Authorization", "Check Authentication menu") .header("Cache-Control", "no-cache") .asString(); - lang: Javascript source: | var myHeaders = new Headers(); myHeaders.append("Authorization", "Check Authentication menu"); myHeaders.append("Cache-Control", "no-cache"); var requestOptions = { method: 'GET', headers: myHeaders, redirect: 'follow' }; fetch("https://api.lulu.com/webhook-submissions/", requestOptions) .then(response => response.text()) .then(result => console.log(result)) .catch(error => console.log('error', error)); - lang: cURL source: | curl --location 'https://api.lulu.com/webhook-submissions/' \ --header 'Authorization: Check Authentication menu' \ --header 'Cache-Control: no-cache' /validate-interior/: post: summary: Validate interior file description: This endpoint allows you to validate interior file security: - oauth2: [] tags: - Files validation operationId: Validate-Interior_create requestBody: content: application/json: schema: type: object properties: source_url: description: Public url of the interior source file type: string pod_package_id: description: POD Package ID of the book. Required to run extended validation. type: string required: - source_url example: source_url: https://www.dropbox.com/sh/p3zh22vzsaegiri/AACOUn3LFKsITDzylh13bQpsa/161025/thesis2.pdf?dl=1 responses: 201: description: Created content: application/json: schema: type: object properties: id: type: integer readOnly: true source_url: description: The url of the source file. type: string readOnly: true page_count: description: Detected page count of the file. type: string readOnly: true errors: description: List of errors detected in the file. type: array readOnly: true items: type: string status: description: Status of source file type: string enum: - VALIDATING - VALIDATED - ERROR readOnly: true valid_pod_package_ids: description: List of detected valid POD package IDs for source file. type: array items: type: string readOnly: true required: - id - source_url example: id: 1 source_url: https://www.dropbox.com/sh/p3zh22vzsaegiri/AACOUn3LFKsITDzylh13bQpsa/161025/thesis2.pdf?dl=1 page_count: 210 errors: status: VALIDATING valid_pod_package_ids: 400: $ref: '#/components/responses/BadRequest' 401: $ref: '#/components/responses/Unauthorized' 403: $ref: '#/components/responses/Forbidden' x-code-samples: - lang: Python source: | import requests import json url = "https://api.lulu.com/validate-interior/" payload = json.dumps({ "source_url": "https://www.dropbox.com/sh/p3zh22vzsaegiri/AACOUn3LFKsITDzylh13bQpsa/161025/thesis2.pdf?dl=1" }) headers = { 'Authorization': 'Check Authentication menu', 'Cache-Control': 'no-cache', 'Content-Type': 'application/json' } response = requests.request("POST", url, headers=headers, data=payload) print(response.text) - lang: Ruby source: | require "uri" require "json" require "net/http" url = URI("https://api.lulu.com/validate-interior/") https = Net::HTTP.new(url.host, url.port) https.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = "Check Authentication menu" request["Cache-Control"] = "no-cache" request["Content-Type"] = "application/json" request.body = JSON.dump({ "source_url": "https://www.dropbox.com/sh/p3zh22vzsaegiri/AACOUn3LFKsITDzylh13bQpsa/161025/thesis2.pdf?dl=1" }) response = https.request(request) puts response.read_body - lang: Node source: | var request = require('request'); var options = { 'method': 'POST', 'url': 'https://api.lulu.com/validate-interior/', 'headers': { 'Authorization': 'Check Authentication menu', 'Cache-Control': 'no-cache', 'Content-Type': 'application/json' }, body: JSON.stringify({ "source_url": "https://www.dropbox.com/sh/p3zh22vzsaegiri/AACOUn3LFKsITDzylh13bQpsa/161025/thesis2.pdf?dl=1" }) }; request(options, function (error, response) { if (error) throw new Error(error); console.log(response.body); }); - lang: Java source: | Unirest.setTimeouts(0, 0); HttpResponse<String> response = Unirest.post("https://api.lulu.com/validate-interior/") .header("Authorization", "Check Authentication menu") .header("Cache-Control", "no-cache") .header("Content-Type", "application/json") .body("{\n \"source_url\": \"https://www.dropbox.com/sh/p3zh22vzsaegiri/AACOUn3LFKsITDzylh13bQpsa/161025/thesis2.pdf?dl=1\"\n}") .asString(); - lang: Javascript source: | var myHeaders = new Headers(); myHeaders.append("Authorization", "Check Authentication menu"); myHeaders.append("Cache-Control", "no-cache"); myHeaders.append("Content-Type", "application/json"); var raw = JSON.stringify({ "source_url": "https://www.dropbox.com/sh/p3zh22vzsaegiri/AACOUn3LFKsITDzylh13bQpsa/161025/thesis2.pdf?dl=1" }); var requestOptions = { method: 'POST', headers: myHeaders, body: raw, redirect: 'follow' }; fetch("https://api.lulu.com/validate-interior/", requestOptions) .then(response => response.text()) .then(result => console.log(result)) .catch(error => console.log('error', error)); - lang: cURL source: | curl --location 'https://api.lulu.com/validate-interior/' \ --header 'Authorization: Check Authentication menu' \ --header 'Cache-Control: no-cache' \ --header 'Content-Type: application/json' \ --data '{ "source_url": "https://www.dropbox.com/sh/p3zh22vzsaegiri/AACOUn3LFKsITDzylh13bQpsa/161025/thesis2.pdf?dl=1" }' /validate-interior/{id}/: get: summary: Retrieve a single file validation record description: Retrieve a single file validation record parameters: - description: Id of the resource in: path name: id required: true schema: type: integer example: 1 security: - oauth2: [] tags: - Files validation operationId: Validate-Interior_read responses: 200: description: OK content: application/json: schema: type: object properties: id: type: integer readOnly: true source_url: description: The url of the source file. type: string readOnly: true page_count: description: Detected page count of the file. type: string readOnly: true errors: description: List of errors detected in the file. type: array readOnly: true items: type: string status: description: Status of source file type: string enum: - VALIDATING - VALIDATED - ERROR readOnly: true valid_pod_package_ids: description: List of detected valid POD package IDs for source file. type: array items: type: string readOnly: true required: - id - source_url example: id: 1 source_url: https://www.dropbox.com/sh/p3zh22vzsaegiri/AACOUn3LFKsITDzylh13bQpsa/161025/thesis2.pdf?dl=1 page_count: 210 errors: status: VALIDATING valid_pod_package_ids: 401: $ref: '#/components/responses/Unauthorized' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' x-code-samples: - lang: Python source: | import requests url = "https://api.lulu.com/validate-interior/{id}/" payload = {} headers = { 'Authorization': 'Check Authentication menu', 'Cache-Control': 'no-cache' } response = requests.request("GET", url, headers=headers, data=payload) print(response.text) - lang: Ruby source: | require "uri" require "net/http" url = URI("https://api.lulu.com/validate-interior/{id}/") https = Net::HTTP.new(url.host, url.port) https.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = "Check Authentication menu" request["Cache-Control"] = "no-cache" response = https.request(request) puts response.read_body - lang: Node source: | var request = require('request'); var options = { 'method': 'GET', 'url': 'https://api.lulu.com/validate-interior/{id}/', 'headers': { 'Authorization': 'Check Authentication menu', 'Cache-Control': 'no-cache' } }; request(options, function (error, response) { if (error) throw new Error(error); console.log(response.body); }); - lang: Java source: | Unirest.setTimeouts(0, 0); HttpResponse<String> response = Unirest.get("https://api.lulu.com/validate-interior/{id}/") .header("Authorization", "Check Authentication menu") .header("Cache-Control", "no-cache") .asString(); - lang: Javascript source: | var myHeaders = new Headers(); myHeaders.append("Authorization", "Check Authentication menu"); myHeaders.append("Cache-Control", "no-cache"); var requestOptions = { method: 'GET', headers: myHeaders, redirect: 'follow' }; fetch("https://api.lulu.com/validate-interior/{id}/", requestOptions) .then(response => response.text()) .then(result => console.log(result)) .catch(error => console.log('error', error)); - lang: cURL source: | curl --location --globoff 'https://api.lulu.com/validate-interior/{id}/' \ --header 'Authorization: Check Authentication menu' \ --header 'Cache-Control: no-cache' /cover-dimensions/: post: summary: Calculate cover dimensions description: This endpoint allows you to calculate required cover dimensions basing on interior data. security: - oauth2: [] tags: - Files validation operationId: Cover-Dimensions_create requestBody: content: application/json: schema: type: object properties: pod_package_id: description: POD Package ID of the book. type: string interior_page_count: type: integer unit: description: Requested unit of cover dimensions. Defaults to print points. type: string enum: - pt - mm - inch required: - interior_page_count - pod_package_id example: pod_package_id: 0600X0900BWSTDPB060UW444MXX interior_page_count: 210 responses: 201: description: Created content: application/json: schema: type: object properties: width: type: string height: type: string unit: type: string enum: - pt - mm - inch required: - width - height - unit example: width: '920.000' height: '666.000' unit: pt 400: $ref: '#/components/responses/BadRequest' 401: $ref: '#/components/responses/Unauthorized' 403: $ref: '#/components/responses/Forbidden' x-code-samples: - lang: Python source: | import requests import json url = "https://api.lulu.com/cover-dimensions/" payload = json.dumps({ "pod_package_id": "0600X0900BWSTDPB060UW444MXX", "interior_page_count": 210 }) headers = { 'Authorization': 'Check Authentication menu', 'Cache-Control': 'no-cache', 'Content-Type': 'application/json' } response = requests.request("POST", url, headers=headers, data=payload) print(response.text) - lang: Ruby source: | require "uri" require "json" require "net/http" url = URI("https://api.lulu.com/cover-dimensions/") https = Net::HTTP.new(url.host, url.port) https.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = "Check Authentication menu" request["Cache-Control"] = "no-cache" request["Content-Type"] = "application/json" request.body = JSON.dump({ "pod_package_id": "0600X0900BWSTDPB060UW444MXX", "interior_page_count": 210 }) response = https.request(request) puts response.read_body - lang: Node source: | var request = require('request'); var options = { 'method': 'POST', 'url': 'https://api.lulu.com/cover-dimensions/', 'headers': { 'Authorization': 'Check Authentication menu', 'Cache-Control': 'no-cache', 'Content-Type': 'application/json' }, body: JSON.stringify({ "pod_package_id": "0600X0900BWSTDPB060UW444MXX", "interior_page_count": 210 }) }; request(options, function (error, response) { if (error) throw new Error(error); console.log(response.body); }); - lang: Java source: | Unirest.setTimeouts(0, 0); HttpResponse<String> response = Unirest.post("https://api.lulu.com/cover-dimensions/") .header("Authorization", "Check Authentication menu") .header("Cache-Control", "no-cache") .header("Content-Type", "application/json") .body("{\n \"page_count\": 210,\n \"pod_package_id\": \"0600X0900BWSTDPB060UW444MXX\"\n}").asString(); - lang: Javascript source: | var myHeaders = new Headers(); myHeaders.append("Authorization", "Check Authentication menu"); myHeaders.append("Cache-Control", "no-cache"); myHeaders.append("Content-Type", "application/json"); var raw = JSON.stringify({ "pod_package_id": "0600X0900BWSTDPB060UW444MXX", "interior_page_count": 210 }); var requestOptions = { method: 'POST', headers: myHeaders, body: raw, redirect: 'follow' }; fetch("https://api.lulu.com/cover-dimensions/", requestOptions) .then(response => response.text()) .then(result => console.log(result)) .catch(error => console.log('error', error)); - lang: cURL source: | curl --location 'https://api.lulu.com/cover-dimensions/' \ --header 'Authorization: Check Authentication menu' \ --header 'Cache-Control: no-cache' \ --header 'Content-Type: application/json' \ --data '{ "pod_package_id": "0600X0900BWSTDPB060UW444MXX", "interior_page_count": 210 }' /validate-cover/: post: summary: Validate cover file description: This endpoint allows you to validate cover file security: - oauth2: [] tags: - Files validation operationId: Validate-Cover_create requestBody: content: application/json: schema: type: object properties: source_url: description: Public url of the cover source file type: string pod_package_id: description: POD Package ID of the book. type: string interior_page_count: type: integer required: - source_url - pod_package_id - interior_page_count example: source_url: https://www.dropbox.com/sh/p3zh22vzsaegiri/AADP367j0bTWlt8fCu-_tm2ia/161025/139056_cover.pdf?dl=1 pod_package_id: 0600X0900BWSTDPB060UW444MXX interior_page_count: 210 responses: 201: description: Created content: application/json: schema: type: object properties: id: type: integer readOnly: true source_url: description: The url of the source file. type: string readOnly: true errors: description: List of errors detected in the file. type: array readOnly: true items: type: string status: description: Status of source file type: string enum: - NORMALIZING - NORMALIZED - ERROR readOnly: true required: - id - source_url example: id: 1 source_url: https://www.dropbox.com/sh/p3zh22vzsaegiri/AADP367j0bTWlt8fCu-_tm2ia/161025/139056_cover.pdf?dl=1 page_count: 210 errors: status: NORMALIZING 400: $ref: '#/components/responses/BadRequest' 401: $ref: '#/components/responses/Unauthorized' 403: $ref: '#/components/responses/Forbidden' x-code-samples: - lang: Python source: | import requests import json url = "https://api.lulu.com/validate-cover/" payload = json.dumps({ "source_url": "https://www.dropbox.com/sh/p3zh22vzsaegiri/AADP367j0bTWlt8fCu-_tm2ia/161025/139056_cover.pdf?dl=1", "pod_package_id": "0600X0900BWSTDPB060UW444MXX", "interior_page_count": 210 }) headers = { 'Authorization': 'Check Authentication menu', 'Cache-Control': 'no-cache', 'Content-Type': 'application/json' } response = requests.request("POST", url, headers=headers, data=payload) print(response.text) - lang: Ruby source: | require "uri" require "json" require "net/http" url = URI("https://api.lulu.com/validate-cover/") https = Net::HTTP.new(url.host, url.port) https.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = "Check Authentication menu" request["Cache-Control"] = "no-cache" request["Content-Type"] = "application/json" request.body = JSON.dump({ "source_url": "https://www.dropbox.com/sh/p3zh22vzsaegiri/AADP367j0bTWlt8fCu-_tm2ia/161025/139056_cover.pdf?dl=1", "pod_package_id": "0600X0900BWSTDPB060UW444MXX", "interior_page_count": 210 }) response = https.request(request) puts response.read_body - lang: Node source: | var request = require('request'); var options = { 'method': 'POST', 'url': 'https://api.lulu.com/validate-cover/', 'headers': { 'Authorization': 'Check Authentication menu', 'Cache-Control': 'no-cache', 'Content-Type': 'application/json' }, body: JSON.stringify({ "source_url": "https://www.dropbox.com/sh/p3zh22vzsaegiri/AADP367j0bTWlt8fCu-_tm2ia/161025/139056_cover.pdf?dl=1", "pod_package_id": "0600X0900BWSTDPB060UW444MXX", "interior_page_count": 210 }) }; request(options, function (error, response) { if (error) throw new Error(error); console.log(response.body); }); - lang: Java source: | Unirest.setTimeouts(0, 0); HttpResponse<String> response = Unirest.post("https://api.lulu.com/validate-cover/") .header("Authorization", "Check Authentication menu") .header("Cache-Control", "no-cache") .header("Content-Type", "application/json") .body("{\n \"source_url\": \"https://www.dropbox.com/sh/p3zh22vzsaegiri/AADP367j0bTWlt8fCu-_tm2ia/161025/139056_cover.pdf?dl=1\",\n \"page_count\": 210,\n \"pod_package_id\": \"0600X0900BWSTDPB060UW444MXX\"\n}").asString(); .asString(); - lang: Javascript source: | var myHeaders = new Headers(); myHeaders.append("Authorization", "Check Authentication menu"); myHeaders.append("Cache-Control", "no-cache"); myHeaders.append("Content-Type", "application/json"); var raw = JSON.stringify({ "source_url": "https://www.dropbox.com/sh/p3zh22vzsaegiri/AADP367j0bTWlt8fCu-_tm2ia/161025/139056_cover.pdf?dl=1", "pod_package_id": "0600X0900BWSTDPB060UW444MXX", "interior_page_count": 210 }); var requestOptions = { method: 'POST', headers: myHeaders, body: raw, redirect: 'follow' }; fetch("https://api.lulu.com/validate-cover/", requestOptions) .then(response => response.text()) .then(result => console.log(result)) .catch(error => console.log('error', error)); - lang: cURL source: | curl --location 'https://api.lulu.com/validate-cover/' \ --header 'Authorization: Check Authentication menu' \ --header 'Cache-Control: no-cache' \ --header 'Content-Type: application/json' \ --data '{ "source_url": "https://www.dropbox.com/sh/p3zh22vzsaegiri/AADP367j0bTWlt8fCu-_tm2ia/161025/139056_cover.pdf?dl=1", "pod_package_id": "0600X0900BWSTDPB060UW444MXX", "interior_page_count": 210 }' /validate-cover/{id}/: get: summary: Retrieve a single cover validation record description: Retrieve a single cover validation record parameters: - description: Id of the resource in: path name: id required: true schema: type: integer example: 1 security: - oauth2: [] tags: - Files validation operationId: Validate-Cover_read responses: 200: description: OK content: application/json: schema: type: object properties: id: type: integer readOnly: true source_url: description: The url of the source file. type: string readOnly: true errors: description: List of errors detected in the file. type: array readOnly: true items: type: string status: description: Status of source file type: string enum: - NORMALIZING - NORMALIZED - ERROR readOnly: true required: - id - source_url example: id: 1 source_url: https://www.dropbox.com/sh/p3zh22vzsaegiri/AADP367j0bTWlt8fCu-_tm2ia/161025/139056_cover.pdf?dl=1 page_count: 210 errors: status: NORMALIZING 401: $ref: '#/components/responses/Unauthorized' 403: $ref: '#/components/responses/Forbidden' 404: $ref: '#/components/responses/NotFound' x-code-samples: - lang: Python source: | import requests url = "https://api.lulu.com/validate-cover/{id}/" payload = {} headers = { 'Authorization': 'Check Authentication menu', 'Cache-Control': 'no-cache' } response = requests.request("GET", url, headers=headers, data=payload) print(response.text) - lang: Ruby source: | require "uri" require "net/http" url = URI("https://api.lulu.com/validate-cover/{id}/") https = Net::HTTP.new(url.host, url.port) https.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = "Check Authentication menu" request["Cache-Control"] = "no-cache" response = https.request(request) puts response.read_body - lang: Node source: | var request = require('request'); var options = { 'method': 'GET', 'url': 'https://api.lulu.com/validate-cover/{id}/', 'headers': { 'Authorization': 'Check Authentication menu', 'Cache-Control': 'no-cache' } }; request(options, function (error, response) { if (error) throw new Error(error); console.log(response.body); }); - lang: Java source: | Unirest.setTimeouts(0, 0); HttpResponse<String> response = Unirest.get("https://api.lulu.com/validate-cover/{id}/") .header("Authorization", "Check Authentication menu") .header("Cache-Control", "no-cache") .asString(); - lang: Javascript source: | var myHeaders = new Headers(); myHeaders.append("Authorization", "Check Authentication menu"); myHeaders.append("Cache-Control", "no-cache"); var requestOptions = { method: 'GET', headers: myHeaders, redirect: 'follow' }; fetch("https://api.lulu.com/validate-cover/{id}/", requestOptions) .then(response => response.text()) .then(result => console.log(result)) .catch(error => console.log('error', error)); - lang: cURL source: | curl --location --globoff 'https://api.lulu.com/validate-cover/{id}/' \ --header 'Authorization: Check Authentication menu' \ --header 'Cache-Control: no-cache' components: responses: BadRequest: description: Bad Request content: application/json: schema: example: attribute_1: - This field is required. attribute_2: - This field is required. title: Bad Request example: attribute_1: - This field is required. attribute_2: - This field is required. Unauthorized: description: Unauthorized content: application/json: schema: example: detail: Authentication credentials were not provided. properties: detail: type: string required: - detail title: Unauthorized example: detail: Authentication credentials were not provided. Forbidden: description: Forbidden content: application/json: schema: example: detail: You do not have permission to perform this action. properties: detail: type: string required: - detail title: Forbidden example: detail: You do not have permission to perform this action. NotFound: description: Not Found content: application/json: schema: example: detail: Not found. properties: detail: type: string required: - detail title: Not Found example: detail: Not found. securitySchemes: oauth2: description: | Get access to data while protecting your account credentials. OAuth2 is also a safer and more secure way to give you access. flows: clientCredentials: scopes: {} tokenUrl: https://api.lulu.com/auth/realms/glasstree/protocol/openid-connect/token implicit: authorizationUrl: https://api.lulu.com/auth/realms/glasstree/protocol/openid-connect/auth?nonce=jwt_login scopes: {} password: scopes: {} tokenUrl: https://api.lulu.com/auth/realms/glasstree/protocol/openid-connect/token type: oauth2 tags: [] security: - oauth2: []

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/devlimelabs/lulu-print-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server