Print content on a reader
Print content on a reader's embedded printer.
With Stripe Terminal, you can print custom content—such as receipts, tickets, or other documents—directly on a reader’s embedded printer. This feature is only available for the Verifone V660p reader, which is equipped with an embedded thermal printer capable of printing in black and white.
Generating print content
Your integration is responsible for generating the content to print as an image file. Images are the only format that we support for printing. After you have an image, convert it to the native image representation for your integration type (for example, an image file for server-driven or a Bitmap for Android).
Content guidelines
For best results, we recommend images that are:
- At most 384 pixels wide
- Black and white (no color)
- Designed so that the thinnest part of any character or line is at least 2 pixels wide, to make sure printing is clear and legible
Note
You’re legally responsible for any content submitted to Stripe for printing using readers, and must make sure your receipts comply with applicable law. You’re prohibited from printing receipts containing materials that (i) infringe on the rights of any third party, (ii) violate applicable law, or (iii) contain objectionable, offensive, deceptive, inaccurate, or harmful content.
Printing content
To print content on a reader, call the print_content endpoint. Send a multipart/form-data body with your PNG or JPEG image file. The uploaded file must not exceed 100 KB.
curl https://files.stripe.com/v1/terminal/readers/tmr_FDOt2wlRZEdpd7/print_content \ -u "sk_test_Hrs6SAopgFPF0bZXSN3f6ELN:" \ -F type=image \ -F "image=@/path/to/a/image.png"
Note
This endpoint lives on the files. subdomain instead of api..
Handle the print result
The print_content endpoint responds with an updated Reader object when the print command successfully sends to the reader. See the following example response:
{ "id": "tmr_FDOt2wlRZEdpd7", "object": "terminal.reader", "action": { "failure_code": null, "failure_message": null, "print_content": { "image": { "created_at": 1748971913, "filename": "image.png", "size": 15864, "type": "png" }, "type": "image" }, "status": "in_progress", "type": "print_content" }, "device_sw_version": "2.37.2.0", "device_type": "verifone_v660p", "ip_address": "0.0.0.0", "label": "Blue Rabbit", "last_seen_at": 1695166525506, "livemode": false, "location": "tml_FDOtHwxAAdIJOh", "metadata": {}, "serial_number": "452-406-028", "status": "online" }
The action object shows that a print_ action is in_. The print_ object contains information about the image being printed.
The endpoint immediately responds to a validation error (for example, file too large or unsupported format) with a 400 status code and a body, such as the following:
{ "error": { "message": "The file you uploaded was too large. Please upload a file smaller than 100 KB", "param": "image", "request_log_url": "https://dashboard.stripe.com/...", "type": "invalid_request_error" } }
Webhook events
When the print operation completes (either successfully or with an error), Stripe sends a request to your webhook endpoint.
Stripe sends two webhook events to notify your back end of the print command’s result:
terminal.: The print command succeeded.reader. action_ succeeded terminal.: The print command failed. For example, the printer ran out of paper or jammed during printing.reader. action_ failed
The webhook payload contains an event object where data. is an updated Reader object.
The terminal. reader. action_ succeeded event
For a terminal. event, the data object looks like the following:
{ "object": { "id": "tmr_FDOt2wlRZEdpd7", "object": "terminal.reader", "action": { "failure_code": null, "failure_message": null, "print_content": { "image": { "created_at": 1748971913, "filename": "image.png", "size": 15864, "type": "png" }, "type": "image" }, "status": "succeeded", "type": "print_content" }, "device_deploy_group": "", "device_sw_version": "2.34.0.0", "device_type": "verifone_v660p", "ip_address": "10.244.38.93", "label": "test", "livemode": false, "location": "tml_GEPlmAJnZUoXI6", "metadata": {}, "serial_number": "452-406-028", "software": null, "status": "online" }, "previous_attributes": null }
The action. is set to succeeded. The action. and action. are both null in this case.
The terminal. reader. action_ failed event
For a terminal. event, the data object looks like the following:
{ "object": { "id": "tmr_FDOt2wlRZEdpd7", "object": "terminal.reader", "action": { "failure_code": "reason_out_of_paper", "failure_message": "The printer is out of paper.", "print_content": { "image": { "created_at": 1748971913, "filename": "image.png", "size": 15864, "type": "png" }, "type": "image" }, "status": "failed", "type": "print_content" }, "device_deploy_group": "", "device_sw_version": "2.34.0.0", "device_type": "verifone_v660p", "ip_address": "10.244.35.107", "label": "test", "livemode": false, "location": "tml_GEPlmAJnZUoXI6", "metadata": {}, "serial_number": "452-406-028", "software": null, "status": "online" }, "previous_attributes": null }
The action. is set to failed. The failure_ field contains the reason for the failure, and the failure_ field contains a human readable message describing the failure.
The possible values for the failure_ field are:
| Error Description | Failure Code |
|---|---|
| The printer is currently printing. | reason_ |
| The printer paper roll is jammed. | reason_ |
| The printer is out of paper. | reason_ |
| The printer’s cover or head assembly is open. | reason_ |
| The reader doesn’t have an embedded printer. | reason_ |
| The reader has an embedded printer, but it’s currently unavailable. | reason_ |
| The reader’s battery is too low to print. Charge the reader and try again. | reason_ |
| General failure to print (catch all for any other error). | reason_ |
If the reader doesn’t support printing, the print_content request immediately returns a printer_ error. Because the request doesn’t create an action, Stripe doesn’t send a terminal. event.