Sign inSign up

alhafoudh/escpos-printer-rest-api

By alhafoudh

•Updated 7 months ago

A lightweight REST API that sends raw ESC/POS data to thermal printers over TCP

Image
Networking
Internet of things
Developer tools
0

165

alhafoudh/escpos-printer-rest-api repository overview

⁠ESC/POS Printer REST API

A lightweight REST API that sends raw ESC/POS data to thermal printers over TCP. Accepts base64-encoded ESC/POS binary data via HTTP and forwards it to a network printer on port 9100.

Built with Ruby, Sinatra, and Puma. Ships as a minimal Alpine-based Docker image.

⁠Features

  • Simple REST API — POST /print with base64-encoded ESC/POS data
  • CORS enabled — call from any browser or frontend app
  • Thread-safe — mutex-serialized printing prevents garbled output from concurrent requests
  • API key authentication — optional Bearer token auth, disabled when no key is configured
  • Health check — GET /health endpoint for container orchestration
  • Configurable — printer host/port via environment variables or per-request

⁠Quick Start

services:
  escpos-printer-api:
    image: escpos-printer-rest-api
    build: .
    ports:
      - "4567:4567"
    environment:
      - PRINTER_HOST=192.168.2.7   # IP of your thermal printer
      - PRINTER_PORT=9100           # default ESC/POS port
      # - API_KEY=your-secret-key   # uncomment to enable authentication
    restart: unless-stopped
docker compose up -d
⁠Docker Run
docker build -t escpos-printer-api .

docker run -d \
  --name escpos-printer-api \
  -p 4567:4567 \
  -e PRINTER_HOST=192.168.2.7 \
  -e PRINTER_PORT=9100 \
  escpos-printer-api
⁠Without Docker
bundle install
bundle exec puma -C puma.rb

⁠Environment Variables

VariableDefaultDescription
PRINTER_HOST192.168.2.7Default printer IP/hostname. Can be overridden per request.
PRINTER_PORT9100Default printer TCP port. Can be overridden per request.
API_KEY(unset)Bearer token for authentication. When unset, all requests are allowed.

⁠API Reference

⁠GET /health

Health check endpoint. Returns 200 OK with:

{"status": "ok"}
⁠POST /print

Send ESC/POS data to the printer.

Headers:

HeaderRequiredDescription
Content-TypeYesMust be application/json
AuthorizationOnly if API_KEY is setBearer <your-api-key>

Request body:

FieldTypeRequiredDescription
datastringYesBase64-encoded ESC/POS binary data
hoststringNoPrinter IP/hostname (overrides PRINTER_HOST)
portintegerNoPrinter TCP port (overrides PRINTER_PORT)

Example request:

curl -X POST http://localhost:4567/print \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer your-secret-key" \
  -d '{
    "data": "G0AbYTEbIRFURVNUIFJFQ0VJUFQKGyEA",
    "host": "192.168.2.7",
    "port": 9100
  }'

Responses:

StatusBodyDescription
200{"status": "ok", "bytes": 42}Data sent to printer successfully
400{"error": "Missing required field: ..."}Missing data field
400{"error": "Invalid JSON"}Malformed JSON body
401{"error": "Unauthorized"}Missing or invalid Bearer token
502{"error": "Printer connection failed: ..."}Cannot reach printer

⁠Usage Examples

⁠Python
import base64
import requests

# Raw ESC/POS: initialize + "Hello World\n" + partial cut
escpos_data = b'\x1b\x40Hello World\n\x1d\x56\x01'
b64_data = base64.b64encode(escpos_data).decode()

requests.post("http://localhost:4567/print", json={
    "data": b64_data
}, headers={
    "Authorization": "Bearer your-secret-key"
})
⁠JavaScript / Node.js
const data = Buffer.from('\x1b\x40Hello World\n\x1d\x56\x01').toString('base64');

fetch('http://localhost:4567/print', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer your-secret-key',
  },
  body: JSON.stringify({ data }),
});
⁠Ruby with escpos gem
require "escpos"
require "http"
require "json"

printer = Escpos::Printer.new
printer << Escpos::Helpers.center(Escpos::Helpers.big("HELLO"))
printer << "\n"
printer << Escpos::Helpers.bold("Bold text")
printer << "\n"
printer << Escpos::Helpers.partial_cut

HTTP
  .auth("Bearer your-secret-key")
  .post("http://localhost:4567/print", json: {
    data: printer.to_base64
  })
⁠curl with raw ESC/POS
# Encode raw bytes to base64 and print
echo -ne '\x1b\x40Hello from curl\n\x1d\x56\x01' | base64 | \
  xargs -I{} curl -X POST http://localhost:4567/print \
    -H "Content-Type: application/json" \
    -d '{"data": "{}"}'

⁠Test Script

A test script is included that prints a sample receipt with various ESC/POS features (text styles, alignment, barcodes, etc.):

# Install the escpos gem inline and send a test receipt
PRINTER_HOST=192.168.2.7 API_KEY=your-secret-key ruby test_print.rb

⁠Architecture

Client                    REST API                  Printer
  |                          |                         |
  |  POST /print             |                         |
  |  { "data": "base64..." } |                         |
  |------------------------->|                         |
  |                          |  TCP :9100              |
  |                          |  (mutex-serialized)     |
  |                          |------------------------>|
  |                          |                         |  🖨️ prints
  |  200 {"status": "ok"}   |                         |
  |<-------------------------|                         |

⁠License

MIT

Tag summary

Content type

Image

Digest

sha256:43167ef5b…

Size

50.7 MB

Last updated

7 months ago

docker pull alhafoudh/escpos-printer-rest-api:af78321d3e8e2d558ab85e3faec4402f47b3c4f3