Create Case
curl --request POST \
--url https://api.zinc.com/cases \
--header 'Authorization: <api-key>' \
--header 'Content-Type: multipart/form-data' \
--form order_id=3c90c3cc-0d44-4b50-8888-8dd25736052a \
--form body= \
--form return_request_id=3c90c3cc-0d44-4b50-8888-8dd25736052aimport requests
url = "https://api.zinc.com/cases"
payload = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"order_id\"\r\n\r\n3c90c3cc-0d44-4b50-8888-8dd25736052a\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"body\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"return_request_id\"\r\n\r\n3c90c3cc-0d44-4b50-8888-8dd25736052a\r\n-----011000010111000001101001--"
headers = {
"Authorization": "<api-key>",
"Content-Type": "multipart/form-data"
}
response = requests.post(url, data=payload, headers=headers)
print(response.text)const form = new FormData();
form.append('order_id', '3c90c3cc-0d44-4b50-8888-8dd25736052a');
form.append('body', '');
form.append('return_request_id', '3c90c3cc-0d44-4b50-8888-8dd25736052a');
const options = {method: 'POST', headers: {Authorization: '<api-key>'}};
options.body = form;
fetch('https://api.zinc.com/cases', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.zinc.com/cases",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"order_id\"\r\n\r\n3c90c3cc-0d44-4b50-8888-8dd25736052a\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"body\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"return_request_id\"\r\n\r\n3c90c3cc-0d44-4b50-8888-8dd25736052a\r\n-----011000010111000001101001--",
CURLOPT_HTTPHEADER => [
"Authorization: <api-key>",
"Content-Type: multipart/form-data"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.zinc.com/cases"
payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"order_id\"\r\n\r\n3c90c3cc-0d44-4b50-8888-8dd25736052a\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"body\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"return_request_id\"\r\n\r\n3c90c3cc-0d44-4b50-8888-8dd25736052a\r\n-----011000010111000001101001--")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "<api-key>")
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.zinc.com/cases")
.header("Authorization", "<api-key>")
.body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"order_id\"\r\n\r\n3c90c3cc-0d44-4b50-8888-8dd25736052a\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"body\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"return_request_id\"\r\n\r\n3c90c3cc-0d44-4b50-8888-8dd25736052a\r\n-----011000010111000001101001--")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.zinc.com/cases")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = '<api-key>'
request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"order_id\"\r\n\r\n3c90c3cc-0d44-4b50-8888-8dd25736052a\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"body\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"return_request_id\"\r\n\r\n3c90c3cc-0d44-4b50-8888-8dd25736052a\r\n-----011000010111000001101001--"
response = http.request(request)
puts response.read_body{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"order_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"reason": "not_received",
"status": "open",
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z",
"return_request_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"credited_amount": 0,
"opened_by_name": "<string>",
"closed_at": "2023-11-07T05:31:56Z",
"messages": []
}{
"error": {
"code": "unauthorized",
"message": "<string>",
"details": {}
}
}{
"error": {
"code": "unauthorized",
"message": "<string>",
"details": {}
}
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>"
}
]
}Cases
Create Case
Open a support case on a Zinc order, with an optional message and attachments.
POST
/
cases
Create Case
curl --request POST \
--url https://api.zinc.com/cases \
--header 'Authorization: <api-key>' \
--header 'Content-Type: multipart/form-data' \
--form order_id=3c90c3cc-0d44-4b50-8888-8dd25736052a \
--form body= \
--form return_request_id=3c90c3cc-0d44-4b50-8888-8dd25736052aimport requests
url = "https://api.zinc.com/cases"
payload = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"order_id\"\r\n\r\n3c90c3cc-0d44-4b50-8888-8dd25736052a\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"body\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"return_request_id\"\r\n\r\n3c90c3cc-0d44-4b50-8888-8dd25736052a\r\n-----011000010111000001101001--"
headers = {
"Authorization": "<api-key>",
"Content-Type": "multipart/form-data"
}
response = requests.post(url, data=payload, headers=headers)
print(response.text)const form = new FormData();
form.append('order_id', '3c90c3cc-0d44-4b50-8888-8dd25736052a');
form.append('body', '');
form.append('return_request_id', '3c90c3cc-0d44-4b50-8888-8dd25736052a');
const options = {method: 'POST', headers: {Authorization: '<api-key>'}};
options.body = form;
fetch('https://api.zinc.com/cases', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.zinc.com/cases",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"order_id\"\r\n\r\n3c90c3cc-0d44-4b50-8888-8dd25736052a\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"body\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"return_request_id\"\r\n\r\n3c90c3cc-0d44-4b50-8888-8dd25736052a\r\n-----011000010111000001101001--",
CURLOPT_HTTPHEADER => [
"Authorization: <api-key>",
"Content-Type: multipart/form-data"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.zinc.com/cases"
payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"order_id\"\r\n\r\n3c90c3cc-0d44-4b50-8888-8dd25736052a\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"body\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"return_request_id\"\r\n\r\n3c90c3cc-0d44-4b50-8888-8dd25736052a\r\n-----011000010111000001101001--")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "<api-key>")
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.zinc.com/cases")
.header("Authorization", "<api-key>")
.body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"order_id\"\r\n\r\n3c90c3cc-0d44-4b50-8888-8dd25736052a\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"body\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"return_request_id\"\r\n\r\n3c90c3cc-0d44-4b50-8888-8dd25736052a\r\n-----011000010111000001101001--")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.zinc.com/cases")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = '<api-key>'
request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"order_id\"\r\n\r\n3c90c3cc-0d44-4b50-8888-8dd25736052a\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"body\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"return_request_id\"\r\n\r\n3c90c3cc-0d44-4b50-8888-8dd25736052a\r\n-----011000010111000001101001--"
response = http.request(request)
puts response.read_body{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"order_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"reason": "not_received",
"status": "open",
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z",
"return_request_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"credited_amount": 0,
"opened_by_name": "<string>",
"closed_at": "2023-11-07T05:31:56Z",
"messages": []
}{
"error": {
"code": "unauthorized",
"message": "<string>",
"details": {}
}
}{
"error": {
"code": "unauthorized",
"message": "<string>",
"details": {}
}
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>"
}
]
}Open a support case when you need Zinc’s help with an order: a package that never arrived, a damaged item, a billing question. Zinc support replies on the case, and the whole conversation stays on it. Follow it with Get Case or the case webhooks.
The request is a multipart form, not JSON, so photos and PDFs can be attached in the same call:
curl -X POST "https://api.zinc.com/cases" \
-H "Authorization: Bearer <your_api_key>" \
-F "order_id=550e8400-e29b-41d4-a716-446655440000" \
-F "reason=damaged_or_wrong_item" \
-F "body=The mug arrived cracked. Photo attached." \
-F "files=@cracked-mug.jpg"
Request
- order_id: the order the case is about. Any order your team can see works.
- reason: one of the reasons below.
- body: your message, up to 5,000 characters. It can be empty if you attach at least one file.
- return_request_id (optional): links the case to a return request on the same order. Required when
reasonisreturn. - files (optional): up to 5 attachments, 25 MB each, as JPEG, PNG, WebP, HEIC or PDF. Repeat the
filesfield once per file.
Reasons
The reason routes the case to the right people. It doesn’t trigger anything automatically: adamaged_or_wrong_item case doesn’t file a return, and a cancellation case doesn’t cancel the order. To start a return, use Create Return Request.
| Reason | When to use |
|---|---|
not_received | The order, or a package on it, never arrived |
missing_item | A package arrived, but an item from it is missing |
late | The order is past its estimated delivery date and hasn’t arrived |
damaged_or_wrong_item | An item arrived damaged, or a different item came instead |
cancellation | A question about a cancellation, or a request to cancel |
address_change | The shipping address needs to change |
return | A question about an existing return request. Pass its return_request_id |
billing | A charge, credit or wallet question about the order |
other | Anything else. Explain in body |
When a case can be opened
- The order is
order_placed,cancelledorcancelled_by_retailer. Otherwise the call fails with400,code: "case_not_allowed"anddetails.reason: "order_status". - The order is inside the case window: 30 days after the latest delivery or estimated delivery date across its packages, or 90 days after the order was created when it has no tracking yet. Past the window, the call fails with
400,code: "case_not_allowed"anddetails.reason: "window_closed". - The order has no other open case. An order has at most one case that isn’t
closed. A second one fails with409, anddetails.case_idnames the open case, so reply on that one with Post Case Message instead:
{
"code": "already_exists",
"message": "There is already an open case on this order",
"details": {
"resource": "SupportCase",
"identifier": "550e8400-e29b-41d4-a716-446655440000",
"conflict": "case_already_open",
"case_id": "3f2c9a8e-1b4d-4e6f-9a7b-2c8d5e1f0a3b"
}
}
Other errors
A failed request saves nothing: no case, message or file.| Status | code | Cause |
|---|---|---|
404 | not_found | No order with that ID, or it belongs to another team |
413 | A file is over 25 MB | |
415 | A file isn’t JPEG, PNG, WebP, HEIC or PDF | |
422 | validation_error | No message and no files, a message over 5,000 characters, more than 5 files, reason=return without return_request_id, or a return_request_id from a different order |
Response
The new case withstatus: "open" and your message as the first entry in messages. See Get Case for the full shape.Authorizations
Zinc API key (Bearer zn_...)
Headers
Body
multipart/form-data
What a support case is about. Routing and reporting only — no reason triggers automation.
Available options:
not_received, missing_item, late, damaged_or_wrong_item, cancellation, address_change, return, billing, other Response
Successful Response
What a support case is about. Routing and reporting only — no reason triggers automation.
Available options:
not_received, missing_item, late, damaged_or_wrong_item, cancellation, address_change, return, billing, other open — waiting on Zinc. waiting_on_customer — Zinc replied and is waiting on you. on_hold — waiting on the retailer or carrier. closed — resolved; replying reopens it within the case window.
Available options:
open, waiting_on_customer, on_hold, closed Total wallet credit issued from this case, in cents (net of reversals).
Who opened the case: a teammate's name, or Zinc support when Zinc reached out. (The case.created webhook's opened_by is the side instead: customer or zinc.)
Show child attributes
Show child attributes

