import Shoply from "@shoplygg/node";
const shoply = new Shoply({ apiKey: process.env.SHOPLY_API_KEY });
const result = await shoply.tickets.reply("TICKET_ID", {
message: "...",
});<?php
require 'vendor/autoload.php';
$shoply = new Shoply\Client(['apiKey' => getenv('SHOPLY_API_KEY')]);
$result = $shoply->tickets->reply('TICKET_ID', [
'message' => '...',
]);
import shoply
client = shoply.Client() # reads SHOPLY_API_KEY
result = client.tickets.reply("TICKET_ID", message="...")
curl --request POST \
--url https://api.shoply.gg/v1/stores/{storeId}/support-tickets/{ticketId}/reply \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"message": "<string>",
"resolve": false
}
'package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.shoply.gg/v1/stores/{storeId}/support-tickets/{ticketId}/reply"
payload := strings.NewReader("{\n \"message\": \"<string>\",\n \"resolve\": false\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(string(body))
}HttpResponse<String> response = Unirest.post("https://api.shoply.gg/v1/stores/{storeId}/support-tickets/{ticketId}/reply")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"message\": \"<string>\",\n \"resolve\": false\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.shoply.gg/v1/stores/{storeId}/support-tickets/{ticketId}/reply")
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 \"message\": \"<string>\",\n \"resolve\": false\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"message": null,
"code": null,
"data": {
"id": "8e243e4e-58e7-4d63-a9c3-ef057672a8fd",
"email": "grace@example.com",
"customerId": null,
"orderId": "bc44febe-0f25-4076-92eb-03a5045a57e7",
"subject": "Key says it is already in use",
"status": "answered",
"messages": 2,
"pictures": 0,
"lastMessageAt": "2026-10-22T16:20:19Z",
"lastFrom": "store",
"lastLine": "Sorry about that. Open your order in the customer panel and press Reset Key, then try it again.",
"unread": false,
"firstReplyAt": "2026-10-22T16:20:19Z",
"answeredAt": "2026-10-22T16:20:19Z",
"resolvedAt": null,
"resolvedBy": null,
"createdAt": "2026-10-22T16:20:19Z",
"updatedAt": "2026-10-22T16:20:19Z",
"conversation": [
{
"id": "cc08e8db-7064-4c32-9883-fe156fbe07f1",
"from": "buyer",
"body": "I bought Northwind Pro this morning and the key says it is already in use.",
"html": "<p>I bought Northwind Pro this morning and the key says it is already in use.</p>",
"pictures": [],
"createdAt": "2026-10-22T16:20:19Z"
},
{
"id": "fb5187b3-26e9-4f1a-bfba-265d93cb8a51",
"from": "store",
"body": "Sorry about that. Open your order in the customer panel and press Reset Key, then try it again.",
"html": "<p>Sorry about that. Open your order in the customer panel and press Reset Key, then try it again.</p>",
"pictures": [],
"createdAt": "2026-10-22T16:20:19Z"
}
],
"canReopenUntil": null,
"limits": {
"body": 500,
"subject": 100,
"picturesPerMessage": 3,
"picturesPerTicket": 25,
"pictureBytes": 5242880
},
"customer": {
"id": null,
"email": "grace@example.com",
"tags": []
},
"order": {
"id": "bc44febe-0f25-4076-92eb-03a5045a57e7",
"status": "completed",
"amount": "$9.99"
},
"orders": [
{
"id": "e9ae5h0p1ye-cd7fded3be6-1006662",
"status": "cancelled",
"amount": "$9.99",
"products": [
"Northwind Pro"
],
"createdAt": "2026-10-22T16:20:19Z"
},
{
"id": "bc44febe-0f25-4076-92eb-03a5045a57e7",
"status": "completed",
"amount": "$9.99",
"products": [
"Northwind Pro"
],
"createdAt": "2026-10-22T16:20:19Z"
}
],
"on": true
}
}{
"success": false,
"message": "<string>",
"code": "<string>",
"data": null,
"errors": {}
}{
"success": false,
"message": "<string>",
"code": "<string>",
"data": null,
"errors": {}
}{
"success": false,
"message": "<string>",
"code": "<string>",
"data": null,
"errors": {}
}{
"success": false,
"message": "<string>",
"code": "<string>",
"data": null,
"errors": {}
}{
"success": false,
"message": "<string>",
"code": "<string>",
"data": null,
"errors": {}
}Reply to a support ticket
Writes on the ticket as the store, which the buyer reads in their customer panel and is emailed (at most once a ticket in 15 minutes; what is written meanwhile follows when they are over). A reply to a resolved ticket opens it again, unless resolve is true. Refused with tickets_off while the store takes no tickets, since the buyer could not read it. Answers the ticket as Get a support ticket does.
Needs the tickets.write permission (Answer Support Tickets).
import Shoply from "@shoplygg/node";
const shoply = new Shoply({ apiKey: process.env.SHOPLY_API_KEY });
const result = await shoply.tickets.reply("TICKET_ID", {
message: "...",
});<?php
require 'vendor/autoload.php';
$shoply = new Shoply\Client(['apiKey' => getenv('SHOPLY_API_KEY')]);
$result = $shoply->tickets->reply('TICKET_ID', [
'message' => '...',
]);
import shoply
client = shoply.Client() # reads SHOPLY_API_KEY
result = client.tickets.reply("TICKET_ID", message="...")
curl --request POST \
--url https://api.shoply.gg/v1/stores/{storeId}/support-tickets/{ticketId}/reply \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"message": "<string>",
"resolve": false
}
'package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.shoply.gg/v1/stores/{storeId}/support-tickets/{ticketId}/reply"
payload := strings.NewReader("{\n \"message\": \"<string>\",\n \"resolve\": false\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(string(body))
}HttpResponse<String> response = Unirest.post("https://api.shoply.gg/v1/stores/{storeId}/support-tickets/{ticketId}/reply")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"message\": \"<string>\",\n \"resolve\": false\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.shoply.gg/v1/stores/{storeId}/support-tickets/{ticketId}/reply")
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 \"message\": \"<string>\",\n \"resolve\": false\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"message": null,
"code": null,
"data": {
"id": "8e243e4e-58e7-4d63-a9c3-ef057672a8fd",
"email": "grace@example.com",
"customerId": null,
"orderId": "bc44febe-0f25-4076-92eb-03a5045a57e7",
"subject": "Key says it is already in use",
"status": "answered",
"messages": 2,
"pictures": 0,
"lastMessageAt": "2026-10-22T16:20:19Z",
"lastFrom": "store",
"lastLine": "Sorry about that. Open your order in the customer panel and press Reset Key, then try it again.",
"unread": false,
"firstReplyAt": "2026-10-22T16:20:19Z",
"answeredAt": "2026-10-22T16:20:19Z",
"resolvedAt": null,
"resolvedBy": null,
"createdAt": "2026-10-22T16:20:19Z",
"updatedAt": "2026-10-22T16:20:19Z",
"conversation": [
{
"id": "cc08e8db-7064-4c32-9883-fe156fbe07f1",
"from": "buyer",
"body": "I bought Northwind Pro this morning and the key says it is already in use.",
"html": "<p>I bought Northwind Pro this morning and the key says it is already in use.</p>",
"pictures": [],
"createdAt": "2026-10-22T16:20:19Z"
},
{
"id": "fb5187b3-26e9-4f1a-bfba-265d93cb8a51",
"from": "store",
"body": "Sorry about that. Open your order in the customer panel and press Reset Key, then try it again.",
"html": "<p>Sorry about that. Open your order in the customer panel and press Reset Key, then try it again.</p>",
"pictures": [],
"createdAt": "2026-10-22T16:20:19Z"
}
],
"canReopenUntil": null,
"limits": {
"body": 500,
"subject": 100,
"picturesPerMessage": 3,
"picturesPerTicket": 25,
"pictureBytes": 5242880
},
"customer": {
"id": null,
"email": "grace@example.com",
"tags": []
},
"order": {
"id": "bc44febe-0f25-4076-92eb-03a5045a57e7",
"status": "completed",
"amount": "$9.99"
},
"orders": [
{
"id": "e9ae5h0p1ye-cd7fded3be6-1006662",
"status": "cancelled",
"amount": "$9.99",
"products": [
"Northwind Pro"
],
"createdAt": "2026-10-22T16:20:19Z"
},
{
"id": "bc44febe-0f25-4076-92eb-03a5045a57e7",
"status": "completed",
"amount": "$9.99",
"products": [
"Northwind Pro"
],
"createdAt": "2026-10-22T16:20:19Z"
}
],
"on": true
}
}{
"success": false,
"message": "<string>",
"code": "<string>",
"data": null,
"errors": {}
}{
"success": false,
"message": "<string>",
"code": "<string>",
"data": null,
"errors": {}
}{
"success": false,
"message": "<string>",
"code": "<string>",
"data": null,
"errors": {}
}{
"success": false,
"message": "<string>",
"code": "<string>",
"data": null,
"errors": {}
}{
"success": false,
"message": "<string>",
"code": "<string>",
"data": null,
"errors": {}
}Authorizations
A secret API key, made under Developers in the dashboard: Authorization: Bearer shoply_sk_...
Headers
A word of your own for this one change, up to 180 letters, digits, dots, dashes, underscores and colons. Sent again with the same key, the request is not carried out twice: the first answer comes back, with Idempotent-Replay: true.
Path Parameters
The store's ID. A key reaches the store it was made in: GET /key answers which.
The ticket, by its ID.

