Create a product
curl --request POST \
--url https://merchant-api-prod.anyway.sh/v1/product \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: <idempotency-key>' \
--header 'X-API-Key: <api-key>' \
--data '
{
"name": "<string>",
"currency": "<string>",
"description": "<string>",
"pricing": "<string>",
"minAmount": 123,
"maxAmount": 123,
"pricingName": "<string>",
"billingIntervalCount": 123,
"status": "PUBLISHED"
}
'import requests
url = "https://merchant-api-prod.anyway.sh/v1/product"
payload = {
"name": "<string>",
"currency": "<string>",
"description": "<string>",
"pricing": "<string>",
"minAmount": 123,
"maxAmount": 123,
"pricingName": "<string>",
"billingIntervalCount": 123,
"status": "PUBLISHED"
}
headers = {
"Idempotency-Key": "<idempotency-key>",
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'Idempotency-Key': '<idempotency-key>',
'X-API-Key': '<api-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: '<string>',
currency: '<string>',
description: '<string>',
pricing: '<string>',
minAmount: 123,
maxAmount: 123,
pricingName: '<string>',
billingIntervalCount: 123,
status: 'PUBLISHED'
})
};
fetch('https://merchant-api-prod.anyway.sh/v1/product', 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://merchant-api-prod.anyway.sh/v1/product",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'name' => '<string>',
'currency' => '<string>',
'description' => '<string>',
'pricing' => '<string>',
'minAmount' => 123,
'maxAmount' => 123,
'pricingName' => '<string>',
'billingIntervalCount' => 123,
'status' => 'PUBLISHED'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"Idempotency-Key: <idempotency-key>",
"X-API-Key: <api-key>"
],
]);
$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://merchant-api-prod.anyway.sh/v1/product"
payload := strings.NewReader("{\n \"name\": \"<string>\",\n \"currency\": \"<string>\",\n \"description\": \"<string>\",\n \"pricing\": \"<string>\",\n \"minAmount\": 123,\n \"maxAmount\": 123,\n \"pricingName\": \"<string>\",\n \"billingIntervalCount\": 123,\n \"status\": \"PUBLISHED\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Idempotency-Key", "<idempotency-key>")
req.Header.Add("X-API-Key", "<api-key>")
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://merchant-api-prod.anyway.sh/v1/product")
.header("Idempotency-Key", "<idempotency-key>")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"<string>\",\n \"currency\": \"<string>\",\n \"description\": \"<string>\",\n \"pricing\": \"<string>\",\n \"minAmount\": 123,\n \"maxAmount\": 123,\n \"pricingName\": \"<string>\",\n \"billingIntervalCount\": 123,\n \"status\": \"PUBLISHED\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://merchant-api-prod.anyway.sh/v1/product")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Idempotency-Key"] = '<idempotency-key>'
request["X-API-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"<string>\",\n \"currency\": \"<string>\",\n \"description\": \"<string>\",\n \"pricing\": \"<string>\",\n \"minAmount\": 123,\n \"maxAmount\": 123,\n \"pricingName\": \"<string>\",\n \"billingIntervalCount\": 123,\n \"status\": \"PUBLISHED\"\n}"
response = http.request(request)
puts response.read_body{
"data": {
"createdAt": "<string>",
"description": "<string>",
"id": "<string>",
"name": "<string>",
"orgId": "<string>",
"paymentLinks": [
{
"amount": 123,
"createdAt": "<string>",
"currency": "<string>",
"flexibleAmount": true,
"isActive": true,
"name": "<string>",
"paymentLinkUrl": "<string>",
"pricingId": "<string>",
"pricingType": "<string>",
"provider": "<string>",
"title": "<string>",
"description": "<string>",
"minAmount": 123,
"maxAmount": 123,
"successUrl": "<string>"
}
],
"productId": "<string>",
"status": "<string>",
"updatedAt": "<string>",
"pricing": {
"pricingId": "<string>",
"currency": "<string>",
"pricing": 123,
"minAmount": 123,
"maxAmount": 123,
"pricingType": "SUBSCRIPTION",
"billingInterval": "DAY",
"billingIntervalCount": 123,
"pricingName": "<string>"
}
},
"error": {
"code": "<string>",
"message": "<string>"
},
"message": "<string>",
"success": true
}{
"data": "<unknown>",
"error": {
"code": "<string>",
"message": "<string>"
},
"message": "<string>",
"success": true
}{
"data": "<unknown>",
"error": {
"code": "<string>",
"message": "<string>"
},
"message": "<string>",
"success": true
}{
"data": "<unknown>",
"error": {
"code": "<string>",
"message": "<string>"
},
"message": "<string>",
"success": true
}{
"data": "<unknown>",
"error": {
"code": "<string>",
"message": "<string>"
},
"message": "<string>",
"success": true
}{
"data": "<unknown>",
"error": {
"code": "<string>",
"message": "<string>"
},
"message": "<string>",
"success": true
}Merchant API endpoints
Create a product
Create one product with one price.
POST
/
v1
/
product
Create a product
curl --request POST \
--url https://merchant-api-prod.anyway.sh/v1/product \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: <idempotency-key>' \
--header 'X-API-Key: <api-key>' \
--data '
{
"name": "<string>",
"currency": "<string>",
"description": "<string>",
"pricing": "<string>",
"minAmount": 123,
"maxAmount": 123,
"pricingName": "<string>",
"billingIntervalCount": 123,
"status": "PUBLISHED"
}
'import requests
url = "https://merchant-api-prod.anyway.sh/v1/product"
payload = {
"name": "<string>",
"currency": "<string>",
"description": "<string>",
"pricing": "<string>",
"minAmount": 123,
"maxAmount": 123,
"pricingName": "<string>",
"billingIntervalCount": 123,
"status": "PUBLISHED"
}
headers = {
"Idempotency-Key": "<idempotency-key>",
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'Idempotency-Key': '<idempotency-key>',
'X-API-Key': '<api-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: '<string>',
currency: '<string>',
description: '<string>',
pricing: '<string>',
minAmount: 123,
maxAmount: 123,
pricingName: '<string>',
billingIntervalCount: 123,
status: 'PUBLISHED'
})
};
fetch('https://merchant-api-prod.anyway.sh/v1/product', 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://merchant-api-prod.anyway.sh/v1/product",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'name' => '<string>',
'currency' => '<string>',
'description' => '<string>',
'pricing' => '<string>',
'minAmount' => 123,
'maxAmount' => 123,
'pricingName' => '<string>',
'billingIntervalCount' => 123,
'status' => 'PUBLISHED'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"Idempotency-Key: <idempotency-key>",
"X-API-Key: <api-key>"
],
]);
$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://merchant-api-prod.anyway.sh/v1/product"
payload := strings.NewReader("{\n \"name\": \"<string>\",\n \"currency\": \"<string>\",\n \"description\": \"<string>\",\n \"pricing\": \"<string>\",\n \"minAmount\": 123,\n \"maxAmount\": 123,\n \"pricingName\": \"<string>\",\n \"billingIntervalCount\": 123,\n \"status\": \"PUBLISHED\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Idempotency-Key", "<idempotency-key>")
req.Header.Add("X-API-Key", "<api-key>")
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://merchant-api-prod.anyway.sh/v1/product")
.header("Idempotency-Key", "<idempotency-key>")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"<string>\",\n \"currency\": \"<string>\",\n \"description\": \"<string>\",\n \"pricing\": \"<string>\",\n \"minAmount\": 123,\n \"maxAmount\": 123,\n \"pricingName\": \"<string>\",\n \"billingIntervalCount\": 123,\n \"status\": \"PUBLISHED\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://merchant-api-prod.anyway.sh/v1/product")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Idempotency-Key"] = '<idempotency-key>'
request["X-API-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"<string>\",\n \"currency\": \"<string>\",\n \"description\": \"<string>\",\n \"pricing\": \"<string>\",\n \"minAmount\": 123,\n \"maxAmount\": 123,\n \"pricingName\": \"<string>\",\n \"billingIntervalCount\": 123,\n \"status\": \"PUBLISHED\"\n}"
response = http.request(request)
puts response.read_body{
"data": {
"createdAt": "<string>",
"description": "<string>",
"id": "<string>",
"name": "<string>",
"orgId": "<string>",
"paymentLinks": [
{
"amount": 123,
"createdAt": "<string>",
"currency": "<string>",
"flexibleAmount": true,
"isActive": true,
"name": "<string>",
"paymentLinkUrl": "<string>",
"pricingId": "<string>",
"pricingType": "<string>",
"provider": "<string>",
"title": "<string>",
"description": "<string>",
"minAmount": 123,
"maxAmount": 123,
"successUrl": "<string>"
}
],
"productId": "<string>",
"status": "<string>",
"updatedAt": "<string>",
"pricing": {
"pricingId": "<string>",
"currency": "<string>",
"pricing": 123,
"minAmount": 123,
"maxAmount": 123,
"pricingType": "SUBSCRIPTION",
"billingInterval": "DAY",
"billingIntervalCount": 123,
"pricingName": "<string>"
}
},
"error": {
"code": "<string>",
"message": "<string>"
},
"message": "<string>",
"success": true
}{
"data": "<unknown>",
"error": {
"code": "<string>",
"message": "<string>"
},
"message": "<string>",
"success": true
}{
"data": "<unknown>",
"error": {
"code": "<string>",
"message": "<string>"
},
"message": "<string>",
"success": true
}{
"data": "<unknown>",
"error": {
"code": "<string>",
"message": "<string>"
},
"message": "<string>",
"success": true
}{
"data": "<unknown>",
"error": {
"code": "<string>",
"message": "<string>"
},
"message": "<string>",
"success": true
}{
"data": "<unknown>",
"error": {
"code": "<string>",
"message": "<string>"
},
"message": "<string>",
"success": true
}Authenticate with an API key that belongs to the target organization and has Full access or the
products:products:write permission. Only the Owner and Admin roles can grant it.
- Takes the same inputs as creating a product in the dashboard: one product with one price.
- Unlike the dashboard, it doesn’t create a payment link. To get a shareable URL, create a payment link for the product, or sell the price with a checkout session (see below).
- Send a unique
Idempotency-Keyheader (required; 1–255 ASCII characters from0x21to0x7E, no spaces), the same rule as checkout sessions. The same key with the same body returns the product created the first time (201) and creates nothing new. The same key with a different body returns409. If the product created with that key was later deleted, a retry also returns409; send a new key. pricingTypeisONE_TIMEorSUBSCRIPTION.pricingis a string in major units, such as"19.99". Omitpricingfor a flexible “pay what you want” price; this works forONE_TIMEonly, andminAmountandmaxAmountare then optional.- A
SUBSCRIPTIONprice needsbillingInterval(DAY,MONTHorYEAR).billingIntervalCountis optional and defaults to1. statusisPUBLISHED(default),DRAFTorARCHIVED. ADRAFTproduct can’t be published or archived later. To keep a product off sale for now, create it asARCHIVEDand publish it when ready.- Unknown fields are rejected with
400. - To sell a fixed price, pass the returned
pricing.pricingIdaspricingIdto Create a checkout session. Checkout sessions can’t sell a flexible amount; for that, create a payment link.
| Status | Code | Meaning |
|---|---|---|
400 | Validation failed: bad currency, a subscription without an interval, a flexible subscription, an amount of 0 or less, an unknown field, or a missing or invalid Idempotency-Key. | |
401 | The API key is missing or invalid. | |
403 | INSUFFICIENT_SCOPE | The key lacks products:products:write. |
409 | PRODUCT_CONFLICT | The Idempotency-Key was already used with a different body, or the product it created was deleted. |
413 | PAYLOAD_TOO_LARGE | The request body is larger than 64 KB. |
Authorizations
Merchant API key (format: ak_BASE64)
Headers
Unique creation request key: 1-255 ASCII characters in the range 0x21-0x7E (no spaces or control characters)
Required string length:
1 - 255Body
application/json
Product and price
Product name
Available options:
SUBSCRIPTION, ONE_TIME Currency code, for example USD
Price in major units, for example "19.99". Omit for a flexible (pay what you want) price, which is ONE_TIME only.
Optional minimum for a flexible price (ONE_TIME only)
Optional maximum for a flexible price (ONE_TIME only)
Name of the price
Available options:
DAY, MONTH, YEAR Number of intervals between charges (SUBSCRIPTION). Defaults to 1.
Available options:
PUBLISHED, DRAFT, ARCHIVED