> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.runpayments.io/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.runpayments.io/_mcp/server.

# Print a receipt

POST https://javelin.runpayments.io/api/terminal/{device_id}/print-receipt
Content-Type: application/json

Prints or reprints a receipt for a past transaction. Connects a terminal session automatically if none is active.
The transaction must belong to the authenticated merchant and be the most recent transaction within its order.
The merchant is resolved from `trans_id`, and the print uses that merchant's existing terminal session if one is active.

Returns the terminal vendor's print response, passed through unmodified.

Only Clover Flex and Clover Mini can print. All other terminals return `400 Not supported` here. `printer: false` is a permanent hardware limitation, so check
`capabilities.printer` from [List terminals](/reference/terminal-api/terminals/list-terminals) before offering a reprint in your UI.

### 400 error messages

| Message                                                             | Cause                                          |
| ------------------------------------------------------------------- | ---------------------------------------------- |
| `Field trans_id is required`                                        | Missing or invalid parameter.                  |
| `Not supported`                                                     | The terminal has no printer.                   |
| `No transaction found for the given trans_id`                       | No matching transaction for this merchant.     |
| `No order_id found for the given transaction`                       | The transaction exists but has no order.       |
| `trans_id is not for the most recent transaction within this order` | The transaction isn't the latest in its order. |
| `Terminal is unavailable.`                                          | The terminal is offline or busy.               |
| `Terminal in merchant mode. Launch customer mode and try again.`    | The terminal is in the wrong mode.             |
| `Interaction was cancelled.`                                        | Cancelled at the terminal.                     |

Some terminal vendor errors also return `400` with the vendor's own message. Match on the messages above, but expect others.

Reference: https://docs.runpayments.io/reference/terminal-api/receipt/print-receipt

## Authentication

- `Authorization` header (bearer token, required) — Use a Payments API key as the bearer token: `Authorization: Bearer <api_key>`. Get a fresh key from [Refresh API Keys](/reference/authentication/refresh-api-keys).

## Request

### Path parameters

- `device_id` (string, required) — Hardware Serial Number (HSN) of the terminal, provided by your Integration Delivery lead.

### Query parameters

- `mid` (string, optional) — Merchant ID. Required when your bearer token is an ISV token acting on behalf of a merchant. If the `mid` can't be resolved to an authorized account, the request returns `400`.

### Body (application/json)

This endpoint expects an object.

- `trans_id` (string, required) — Transaction to print. Must belong to the authenticated merchant and be the most recent transaction within its order.
- `delay` (string, optional) — Delay before printing.
- `extra_receipt` (boolean, optional) — Print an additional copy.

## Response

### 200

Terminal vendor print response, passed through unmodified.

- `map from string to any`

## Errors

### 400 Bad Request Error

The receipt couldn't be printed. See the table above for possible messages.

- `error` (string, optional) — Error message.

### 401 Unauthorized Error

Authentication failed. Bearer token rejections return `{"errors": ["Access denied"]}` and set the `WWW-Authenticate` header. Upstream terminal authentication failures return `{"error": "Failed CardPointe terminal authentication"}` and don't set the header.

- `PrintReceiptRequestUnauthorizedError`

### 403 Forbidden Error

This `device_id` isn't associated with the calling merchant.

- `error` (string, optional) — Error message.

### 404 Not Found Error

Terminal not found on this account.

- `error` (string, optional) — Error message.

### 409 Conflict Error

Terminal already connected.

- `error` (string, optional) — Error message.

### 429 Too Many Requests Error

Rate limit exceeded. All Terminal API endpoints share a per-credential rate limit.

- `any`

### 500 Internal Server Error

Upstream service timed out.

- `error` (string, optional) — Error message.

### 503 Service Unavailable Error

Service temporarily unavailable.

- `error` (string, optional) — Error message.

## Types

### ErrorsResponse

- `errors` (list of string, optional) — Error messages.

### ErrorResponse

- `error` (string, optional) — Error message.

## Examples

**Request**

```json
{
  "trans_id": "987654321"
}
```

**Response**

```json
{}
```

**SDK Code**

```python
import requests

url = "https://javelin.runpayments.io/api/terminal/HSN123456789/print-receipt"

payload = { "trans_id": "987654321" }
headers = {
    "Authorization": "Bearer <token>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

```javascript
const url = 'https://javelin.runpayments.io/api/terminal/HSN123456789/print-receipt';
const options = {
  method: 'POST',
  headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
  body: '{"trans_id":"987654321"}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://javelin.runpayments.io/api/terminal/HSN123456789/print-receipt"

	payload := strings.NewReader("{\n  \"trans_id\": \"987654321\"\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Authorization", "Bearer <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby
require 'uri'
require 'net/http'

url = URI("https://javelin.runpayments.io/api/terminal/HSN123456789/print-receipt")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"trans_id\": \"987654321\"\n}"

response = http.request(request)
puts response.read_body
```

```java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://javelin.runpayments.io/api/terminal/HSN123456789/print-receipt")
  .header("Authorization", "Bearer <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"trans_id\": \"987654321\"\n}")
  .asString();
```

```php
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://javelin.runpayments.io/api/terminal/HSN123456789/print-receipt', [
  'body' => '{
  "trans_id": "987654321"
}',
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

```csharp
using RestSharp;

var client = new RestClient("https://javelin.runpayments.io/api/terminal/HSN123456789/print-receipt");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"trans_id\": \"987654321\"\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift
import Foundation

let headers = [
  "Authorization": "Bearer <token>",
  "Content-Type": "application/json"
]
let parameters = ["trans_id": "987654321"] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://javelin.runpayments.io/api/terminal/HSN123456789/print-receipt")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```