LabPrints

LabPrints connector

Version 0.1.0, effective 2026-10-21. Changelog

The LabPrints connector lets an AI assistant order prints for a person. The assistant sends photos and a brief; LabPrints makes a proof for the person to review; the person approves a proof and pays on a checkout page. Nothing is printed or charged until they do.

Getting started

  1. Get an API key. Keys are issued by hand for now; there is no signup form. Email privacy@labprints.com with the address you want the key tied to. A key is either a test key or a production key.
  2. Add the connector to your assistant as a custom MCP connector: server URL https://api.labprints.com/mcp (streamable HTTP), authentication by API key sent as a bearer token in the Authorization header. Never put the key in a URL.
  3. Ask the assistant to call get_service_info to confirm the connection. It reports the live version and whether your key is in test mode.

The connector is not yet listed in any assistant's connector directory.

A test key runs the whole flow with sample proofs; see Test mode.

Payment. Prices are quoted before shipping and sales tax. After approving a proof, the customer pays, and chooses shipping, through Stripe Checkout on labprints.com; the connector never takes payment details. Orders are printed by professional print partners.

Test mode

A test key runs the whole flow, so you can try the connector without making an order.

Products

Flip Pad

A notepad printed with 1 to 4 of your photos across its pages.

No options to choose.

No text fields.

The customer chooses shipping on the checkout page, which shows each choice's price. Delivery times are estimates, not promises.

ShippingEstimate
Standard Shipping5 - 7 Business Days
Second Day2 Business Days
Next Business DayNo estimate given

Fold

An accordion-fold brag book with up to 10 of your photos, front and back.

Options:

No text fields.

The customer chooses shipping on the checkout page, which shows each choice's price. Delivery times are estimates, not promises.

ShippingEstimate
Standard Shipping5 - 7 Business Days
Second Day2 Business Days
Next Business DayNo estimate given

Tools

There are 8 tools. Each is classified as a read (retrieves without changing anything), a write (creates or changes data, or acts for the user) or a sensitive write (consequential, and approved by the user every time).

get_service_info

Read. Changes nothing. Repeating the same call has the same effect as making it once.

Describe what the LabPrints connector offers right now: its version, each tool and how it is classified (read, write or sensitive write), the products and whether each is available, how payment works, what data it handles and how long it keeps it, the rate limits, and whether your API key is in test mode. Changes nothing.

Inputs

No inputs.

Returns

FieldTypeNotes
versionstring
effective_datestring
toolsarray
tools[].namestring
tools[].classificationone of read, write, sensitive_write
productsarray
products[].product_idstring
products[].namestring
products[].statusone of available, unavailable
intake_methodsarray
payment_modealways "stripe_checkout"
data_handledarray
retention_daysobject
retention_days.photosinteger
retention_days.proof_imagesinteger
retention_days.contact_detailsinteger
retention_days.order_detailsinteger
retention_days.test_ordersinteger
retention_days.order_recordsinteger
retention_days.account_contactinteger
retention_days.logsinteger
rate_limitsobject
rate_limits.per_key_per_minuteinteger
rate_limits.per_ip_per_secondinteger
rate_limits.per_ip_burstinteger
test_modeboolean
docs_urlstring
changelog_urlstring

list_products

Read. Changes nothing. Repeating the same call has the same effect as making it once.

List the print products you can order through LabPrints, with each one's price (before shipping and sales tax), proof turnaround and availability. Changes nothing. Call get_product_spec for everything needed to start an order.

Inputs

No inputs.

Returns

FieldTypeNotes
productsarray
products[].product_idstring
products[].namestring
products[].short_descriptionstring
products[].priceobjectThe list price, before shipping and sales tax, which the checkout page adds.
products[].price.amount_centsinteger
products[].price.currencyalways "USD"
products[].proof_turnaround_business_daysobject
products[].proof_turnaround_business_days.mininteger
products[].proof_turnaround_business_days.maxinteger
products[].statusone of available, unavailable

get_product_spec

Read. Changes nothing. Repeating the same call has the same effect as making it once.

Get everything needed to start an order for one product: how many photos it takes and in what formats, the options to choose, any text fields and their limits, the price (before shipping and sales tax), the proof turnaround, and where it ships with the shipping choices and their delivery estimates. Also returns the length limits for the other text you send (instructions, photo captions and links, contact email), and the largest photo accepted. Changes nothing.

Inputs

FieldTypeRequiredNotes
product_idstringyesAn id from list_products.

Returns

FieldTypeNotes
productobject
product.product_idstring
product.namestring
product.short_descriptionstring
product.statusone of available, unavailable
product.priceobjectThe list price, before shipping and sales tax, which the checkout page adds.
product.price.amount_centsinteger
product.price.currencyalways "USD"
product.photosobject
product.photos.min_countinteger
product.photos.max_countinteger
product.photos.formatsarray
product.photos.low_resolution_warning_dpiintegerPhotos below this resolution at their printed size are accepted, but may print soft; tell the user.
product.optionsarray
product.options[].keystring
product.options[].labelstring
product.options[].choicesarray
product.options[].choices[].valuestring
product.options[].choices[].labelstring
product.options[].defaultstring or nullnull means the order must choose a value.
product.text_fieldsarray
product.text_fields[].keystring
product.text_fields[].labelstring
product.text_fields[].requiredboolean
product.text_fields[].max_lengthintegerIn Unicode code points after NFC normalisation (some emoji count as several).
product.text_fields[].max_linesinteger or nullnull means no line limit.
product.proof_turnaround_business_daysobject
product.proof_turnaround_business_days.mininteger
product.proof_turnaround_business_days.maxinteger
product.ships_toarrayISO 3166-1 country codes.
product.shipping_optionsarrayThe customer chooses one on the checkout page, which shows its price.
product.shipping_options[].labelstring
product.shipping_options[].estimatestring or nullDelivery estimate, as the checkout shows it; null when the checkout shows none.
field_limitsobject
field_limits.instructions_max_lengthintegerIn Unicode code points after NFC normalisation (some emoji count as several).
field_limits.photo_caption_max_lengthintegerIn Unicode code points after NFC normalisation (some emoji count as several).
field_limits.photo_url_max_lengthintegerIn Unicode code points after NFC normalisation (some emoji count as several).
field_limits.email_max_lengthintegerIn Unicode code points after NFC normalisation (some emoji count as several).
max_photo_bytesinteger

create_order

Write. Changes data or acts for the user. Not idempotent: repeating the call can have a new effect. Reaches beyond LabPrints (downloads the user's photo links or opens a checkout).

Start an order: send photos (as links the LabPrints server can download) and a brief, and LabPrints makes a proof for the user to review. This does not place the order: nothing is printed or charged until the customer approves a proof and pays on the checkout page that approve_order links to. Downloads each photo and stores it with the order. Returns the order_id, the price (before shipping and sales tax) and when the proof is expected; then call get_proof. Not idempotent: when retrying, send the same idempotency_key so a retry cannot create a second order. In test mode, a sample proof is ready within seconds.

Inputs

FieldTypeRequiredNotes
product_idstringyesAn id from list_products.
photosarrayyesThe photos to choose from. get_product_spec gives the minimum and maximum count.
photos[].urlstringyesAn https link the LabPrints server can download the photo from.
photos[].captionstringnoOptional note about this photo for the person building the proof.
photos[].priorityone of high, normal, lownoHow much the user wants this photo used. It reaches the person building the proof as a note; it doesn't choose photos automatically.
optionsobjectnoOption key to chosen value, from get_product_spec.
textobjectnoText field key to the text to print, from get_product_spec. Leave it out if the product has no text fields.
instructionsstringnoThe user's brief, in their words: what matters, what to avoid, the occasion.
contactobjectyes
contact.emailstringyesWhere LabPrints sends word about the proof and the order. The shipping address is entered at checkout.
idempotency_keystringnoAny unique string of up to 64 letters, digits, '-' or '_'. Reuse it only to retry this same order.

Returns

FieldTypeNotes
order_idstringThe order_id that create_order returned.
statusone of proofing, proof_ready, revising, awaiting_payment, paid, in_production, shipped, cancelled
proof_etaobject or nullWhen the next proof is expected; null if none is being made.
proof_eta.earlieststring
proof_eta.lateststring
price_quoteobjectThe list price, before shipping and sales tax, which the checkout page adds.
price_quote.amount_centsinteger
price_quote.currencyalways "USD"
next_stepstring

get_proof

Read. Changes nothing. Repeating the same call has the same effect as making it once.

Get the proof for an order: an image of each part of the product (a Fold has a front and a back), and the details an approval would cover (product, options, text and price). Show the user every image and those details before asking them to approve. In test mode the images are samples, and each label says so. Image links may expire within minutes; call again for fresh ones. Returns the latest version unless you pass an earlier one. Changes nothing.

Inputs

FieldTypeRequiredNotes
order_idstringyesThe order_id that create_order returned.
versionintegerno

Returns

FieldTypeNotes
order_idstringThe order_id that create_order returned.
versioninteger
created_atstring
statusone of proofing, proof_ready, revising, awaiting_payment, paid, in_production, shipped, cancelled
samplebooleanTrue in test mode: the images are samples, not a proof of this order.
approval_requiredbooleanTrue while this proof is waiting for the user's approval; false once it is approved, superseded or cancelled.
pagesarray
pages[].labelstringWhat the image shows, for example "Fold, front". In test mode it starts "Sample proof (test mode): ".
pages[].image_urlstring
order_summaryobject
order_summary.product_idstring
order_summary.product_namestring
order_summary.optionsobject
order_summary.textobject
order_summary.priceobjectThe list price, before shipping and sales tax, which the checkout page adds.
order_summary.price.amount_centsinteger
order_summary.price.currencyalways "USD"

request_proof_changes

Write. Changes data or acts for the user. Not idempotent: repeating the call can have a new effect.

Ask for a revised proof, in the user's words: for example a different cover photo. Optionally list photos to leave out or to favour. The current proof can no longer be approved; call get_proof when the new version is ready. Places no order and charges nothing.

Inputs

FieldTypeRequiredNotes
order_idstringyesThe order_id that create_order returned.
instructionsstringyesWhat to change, in the user's words.
exclude_photosarraynoPositions in the photos list sent to create_order; 1 is the first photo. They reach the person building the proof as a note, not as an automatic choice.
prefer_photosarraynoPositions in the photos list sent to create_order; 1 is the first photo. They reach the person building the proof as a note, not as an automatic choice.

Returns

FieldTypeNotes
order_idstringThe order_id that create_order returned.
statusalways "revising"
proof_etaobject
proof_eta.earlieststring
proof_eta.lateststring
version_expectedinteger

approve_order

Sensitive write. Consequential: the assistant must get the user's approval every time. Repeating the same call has the same effect as making it once. Reaches beyond LabPrints (downloads the user's photo links or opens a checkout).

Record that the user approves one proof version, lock it, and get the link to its LabPrints checkout page; the order then awaits payment. The order is placed only when the customer pays on that page, which adds shipping and sales tax to the price; this call charges nothing. Then, if you can, open checkout_url in your own browser and complete payment there, with the customer confirming it; otherwise give the link to the customer. Call it only after the user has seen that exact proof version, including its price, and has explicitly told you to go ahead; ask every time. Requires the current proof_version and confirm: true. Fails if a newer proof exists or anything the user saw has changed; then show the new proof and ask again. Calling it again for the same version returns the same link while the order awaits payment; once a live order is paid or cancelled, status says so and there is no link. In test mode, pay on that page with Stripe test card 4242 4242 4242 4242, any future expiry, any CVC: nothing is charged, and the order shows paid.

Inputs

FieldTypeRequiredNotes
order_idstringyesThe order_id that create_order returned.
proof_versionintegeryesThe version the user saw and approved.
confirmalways trueyesMust be true: the user explicitly approved this proof.

Returns

FieldTypeNotes
order_idstringThe order_id that create_order returned.
statusone of proofing, proof_ready, revising, awaiting_payment, paid, in_production, shipped, cancelled
approved_versioninteger
priceobjectThe list price, before shipping and sales tax, which the checkout page adds.
price.amount_centsinteger
price.currencyalways "USD"
checkout_urlstring or nullOpen this link in your own browser and complete payment there if you can, with the customer confirming; otherwise give it to the customer. Shipping is chosen on that page. In test mode, pay there with Stripe test card 4242 4242 4242 4242, any future expiry, any CVC; nothing is charged. null once a live order is no longer waiting for payment.

order_status

Read. Changes nothing. Repeating the same call has the same effect as making it once.

Check where an order is (proofing, proof ready, revising, awaiting payment, paid, in production, shipped or cancelled), with the time of each step, the current proof version, and tracking once it has shipped. Changes nothing.

Inputs

FieldTypeRequiredNotes
order_idstringyesThe order_id that create_order returned.

Returns

FieldTypeNotes
order_idstringThe order_id that create_order returned.
statusone of proofing, proof_ready, revising, awaiting_payment, paid, in_production, shipped, cancelled
proof_versioninteger or nullnull until the first proof is ready.
timestampsarrayEach status the order has entered, oldest first.
timestamps[].statusone of proofing, proof_ready, revising, awaiting_payment, paid, in_production, shipped, cancelled
timestamps[].atstring
timestamps[].proof_versionintegerSet on proof_ready.
trackingobject
tracking.carrierstring
tracking.tracking_numberstring
tracking.urlstring

Limits on text

Lengths count Unicode characters after normalisation. get_product_spec reports the same numbers.

FieldLimit (characters)
instructions_max_length1500
photo_caption_max_length150
photo_url_max_length2048
email_max_length60

Order statuses

StatusMeaning
proofingThe order was received and the first proof is being made.
proof_readyA proof is waiting for the user's review.
revisingChanges were requested and the next proof version is being made.
awaiting_paymentA proof version was approved and locked; its checkout page is waiting for payment.
paidThe customer paid on the checkout page: the order is placed. In test mode, payment is made with a Stripe test card, and nothing is charged.
in_productionThe order is being printed.
shippedThe order has shipped; tracking is available.
cancelledThe order was cancelled.

Errors

A failed call returns {code, message, how_to_fix}; the code is stable. The service reports stripe_checkout as its payment mode.

CodeMeaning
unauthorizedThe API key is missing, wrong or revoked.
rate_limitedToo many requests; wait and retry.
production_access_on_requestThis is a production key, and production access is available on request; use a test key meanwhile.
invalid_inputThe arguments do not match the tool's input schema.
product_not_foundThere is no product with that id.
product_unavailableThe product exists but cannot be ordered right now.
option_invalidAn option, or its value, is not one the product offers.
text_invalidA text field is too long or has characters the product cannot print.
too_few_photosFewer photos than the product's minimum.
too_many_photosMore photos than the product's maximum.
photo_url_not_allowedA photo link is not an https link to a public address.
photo_unreachableA photo link could not be downloaded.
photo_invalidA photo is the wrong type, too large, or too small.
email_invalidThe contact email is not a valid address.
order_not_foundThere is no such order for this API key.
order_cap_reachedThis API key has reached its order limit.
idempotency_conflictThe idempotency_key was already used for a different order.
invalid_order_stateThe order's state does not allow this call.
proof_not_readyThe proof is not ready yet; try again after the expected time.
proof_version_not_foundThat proof version does not exist.
proof_version_staleA newer proof exists than the version sent; show the user the new one.
proof_changedSomething the user saw has changed since that version; show the user the new proof.
confirmation_requiredapprove_order was called without confirm: true.
internal_errorA fault on our side; retry later.
service_unavailableThe service is down or restarting (HTTP 503).
timeoutThe request took too long (HTTP 504).
request_too_largeThe request body is too large (HTTP 413).
not_foundNo such path; the connector is served only at /mcp (HTTP 404).

Rate limits

Over the limit, a call fails with rate_limited (HTTP 429).

Data handling

What the connector handles:

Photo links are used once to download the photo and are not stored.

The connector's own copies are deleted on this schedule. Proofs and LabPrints' own order records are kept under the LabPrints privacy policy; Stripe keeps payment records under its own.

DataKept forCounted from
customer photos45 daysthe photos are received, whatever the order's state
proof images made for the order45 daysthe proof image is uploaded
the contact email45 daysthe order is created
the order's brief, photo captions and preferences, options, change requests, and a keyed fingerprint of the request and its idempotency key (for safe retries)45 daysthe order is created (deleted with the photos)
everything for a test-mode order: its photos, any proof images and its record14 daysthe order is created
the connector's order records: ids, product, status and timestamps365 daysthe order is created
an API key holder's contact email30 daysthe account is closed
service logs30 daysthe log line is written

Roadmap

Planned, not available:

Contact

privacy@labprints.com