curl -X PATCH "https://api.alura.io/v1/workspace/listings/1834720561" \
-H "Authorization: Bearer $ALURA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 5f0c8e2a-4b1d-4c3e-9a7f-2b5d6e8f0a1c" \
-d '{"title":"Personalized ceramic mug, 11 oz"}'const res = await fetch('https://api.alura.io/v1/workspace/listings/1834720561', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.ALURA_API_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': '5f0c8e2a-4b1d-4c3e-9a7f-2b5d6e8f0a1c',
},
body: JSON.stringify({
"title": "Personalized ceramic mug, 11 oz"
}),
});
console.log(await res.json());import json
import os
import urllib.request
request = urllib.request.Request(
"https://api.alura.io/v1/workspace/listings/1834720561",
method="PATCH",
data=json.dumps({
"title": "Personalized ceramic mug, 11 oz"
}).encode(),
headers={
"Authorization": f"Bearer {os.environ['ALURA_API_KEY']}",
"Content-Type": "application/json",
"Idempotency-Key": "5f0c8e2a-4b1d-4c3e-9a7f-2b5d6e8f0a1c",
},
)
with urllib.request.urlopen(request) as response:
print(json.load(response)){
"object": "workspace.listing",
"id": "1834720561",
"shop_id": "22841907",
"title": "Personalized ceramic mug, 11 oz",
"description": "A personalized name mug printed with the name you choose. 11oz white ceramic, dishwasher and microwave safe. Made to order in 1-3 days and shipped in a protective box, ready to gift for birthdays, holidays and thank-yous.",
"url": "https://www.etsy.com/listing/1834720561",
"state": "active",
"price": {
"amount": "18.50",
"currency": "USD",
"usd": "18.50"
},
"quantity": 37,
"skus": [
"MUG-NAME-11"
],
"tags": [
"personalized mug",
"name mug",
"custom mug",
"coffee mug",
"gift for her",
"birthday gift",
"ceramic mug",
"teacher gift",
"mom gift",
"custom name",
"christmas gift",
"office mug",
"tea mug"
],
"materials": [
"ceramic"
],
"category": {
"id": "1062"
},
"section": {
"id": "3301"
},
"shipping_profile_id": "4401",
"return_policy_id": "4501",
"processing_profile_id": null,
"production_partner_ids": null,
"who_made": "i_did",
"when_made": "made_to_order",
"is_supply": false,
"should_auto_renew": true,
"updated_at": "2026-10-17T12:00:00.000Z",
"as_of": "2026-10-17T12:00:00.000Z",
"change": {
"id": "chn_01JMOCK0000000000000000000",
"status": "succeeded",
"applied_fields": [
"title"
],
"failed_fields": []
},
"notices": []
}{
"object": "workspace.change",
"id": "<string>",
"shop_id": "<string>",
"target": {
"type": "<string>",
"id": "<string>"
},
"source": "<string>",
"actor": {
"type": "<string>",
"id": "<string>"
},
"write_id": "<string>",
"outcome": "<string>",
"fields": [
{
"field": "<string>",
"before": "<unknown>",
"after": "<unknown>",
"unrecorded": [
"before"
],
"omitted": [
"before"
]
}
],
"applied_fields": [
"<string>"
],
"failed_fields": [
{
"field": "<string>",
"code": "<string>"
}
],
"before_source": "<string>",
"before_as_of": "<string>",
"revertable": true,
"not_revertable_reason": "<string>",
"created_at": "<string>",
"as_of": "<string>"
}{
"type": "https://docs.alura.io/errors/invalid_request",
"title": "Invalid request",
"status": 400,
"code": "invalid_request",
"detail": "Invalid request",
"suggestion": "Fix the request as the detail says, then send it again.",
"retryable": false,
"request_id": "req_01JQ5W3H8M2N4P6R8T0V2X4Z6B"
}{
"type": "https://docs.alura.io/errors/unauthorized",
"title": "Unauthorized",
"status": 401,
"code": "unauthorized",
"detail": "Unauthorized",
"suggestion": "Send a valid API key as `Authorization: Bearer alura_sk_...`.",
"retryable": false,
"request_id": "req_01JQ5W3H8M2N4P6R8T0V2X4Z6B"
}{
"type": "https://docs.alura.io/errors/credits_exhausted",
"title": "API credits exhausted",
"status": 402,
"code": "credits_exhausted",
"detail": "API credits exhausted",
"suggestion": "Upgrade the plan or wait for the monthly reset.",
"retryable": false,
"request_id": "req_01JQ5W3H8M2N4P6R8T0V2X4Z6B"
}{
"type": "https://docs.alura.io/errors/plan_required",
"title": "Plan required",
"status": 403,
"code": "plan_required",
"detail": "Plan required",
"suggestion": "Upgrade the workspace plan to use this operation.",
"retryable": false,
"request_id": "req_01JQ5W3H8M2N4P6R8T0V2X4Z6B"
}{
"type": "https://docs.alura.io/errors/not_found",
"title": "Not found",
"status": 404,
"code": "not_found",
"detail": "Not found",
"suggestion": "Check the ID, or search for it first.",
"retryable": false,
"request_id": "req_01JQ5W3H8M2N4P6R8T0V2X4Z6B"
}{
"type": "https://docs.alura.io/errors/method_not_allowed",
"title": "Method not allowed",
"status": 405,
"code": "method_not_allowed",
"detail": "Method not allowed",
"suggestion": "Use one of the methods in the Allow header.",
"retryable": false,
"request_id": "req_01JQ5W3H8M2N4P6R8T0V2X4Z6B"
}{
"type": "https://docs.alura.io/errors/conflict",
"title": "Conflict",
"status": 409,
"code": "conflict",
"detail": "Conflict",
"suggestion": "Reload the resource and retry with its current state.",
"retryable": false,
"request_id": "req_01JQ5W3H8M2N4P6R8T0V2X4Z6B"
}{
"type": "https://docs.alura.io/errors/rate_limited",
"title": "Rate limited",
"status": 429,
"code": "rate_limited",
"detail": "Rate limited",
"suggestion": "Wait for Retry-After, then retry.",
"retryable": true,
"request_id": "req_01JQ5W3H8M2N4P6R8T0V2X4Z6B"
}{
"type": "https://docs.alura.io/errors/internal_error",
"title": "Internal error",
"status": 500,
"code": "internal_error",
"detail": "Internal error",
"suggestion": "Retry; if it keeps failing, report the request_id.",
"retryable": true,
"request_id": "req_01JQ5W3H8M2N4P6R8T0V2X4Z6B"
}{
"type": "https://docs.alura.io/errors/credits_unavailable",
"title": "API credits unavailable",
"status": 503,
"code": "credits_unavailable",
"detail": "API credits unavailable",
"suggestion": "Retry shortly.",
"retryable": true,
"request_id": "req_01JQ5W3H8M2N4P6R8T0V2X4Z6B"
}Update a listing
Changes one listing of your connected Etsy shops on Etsy: title, description, tags (the whole list, or tags_add/tags_remove against the tags it has on Etsy right now), materials, category, maker fields, section, shipping profile, return policy, processing profile, production partners, auto-renew, state: "inactive", and the price, quantity and SKU of every offering. Every field you send is sent to Etsy, even one equal to Alura’s copy; fields you leave out are untouched; an unknown field is 400. null clears only section_id and return_policy_id. A listing with variations is 409 listing_has_variations for price, quantity and processing profile unless apply_to: "all_variants" (never for SKU). A listing in a running A/B test is 409 listing_in_ab_test. adjust_price and adjust_quantity need an Idempotency-Key. tags_add and tags_remove are applied to the tags Etsy holds when the write runs, read just before the change; Etsy has no conditional update, so a tag another tool writes to Etsy in that moment can be lost, and the change records any difference between the tags sent and those Etsy kept. Answers 200 with the listing as Etsy returned it and its change, or 202 with the change while Etsy is still answering; dry_run=true shows what it would send. Needs the listings:write scope and the Listing optimization workspace permission. Costs 1 API credit when the change lands on Etsy, nothing when it fails; dry_run is free.
Cost: 1 API credit per write.
curl -X PATCH "https://api.alura.io/v1/workspace/listings/1834720561" \
-H "Authorization: Bearer $ALURA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 5f0c8e2a-4b1d-4c3e-9a7f-2b5d6e8f0a1c" \
-d '{"title":"Personalized ceramic mug, 11 oz"}'const res = await fetch('https://api.alura.io/v1/workspace/listings/1834720561', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.ALURA_API_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': '5f0c8e2a-4b1d-4c3e-9a7f-2b5d6e8f0a1c',
},
body: JSON.stringify({
"title": "Personalized ceramic mug, 11 oz"
}),
});
console.log(await res.json());import json
import os
import urllib.request
request = urllib.request.Request(
"https://api.alura.io/v1/workspace/listings/1834720561",
method="PATCH",
data=json.dumps({
"title": "Personalized ceramic mug, 11 oz"
}).encode(),
headers={
"Authorization": f"Bearer {os.environ['ALURA_API_KEY']}",
"Content-Type": "application/json",
"Idempotency-Key": "5f0c8e2a-4b1d-4c3e-9a7f-2b5d6e8f0a1c",
},
)
with urllib.request.urlopen(request) as response:
print(json.load(response)){
"object": "workspace.listing",
"id": "1834720561",
"shop_id": "22841907",
"title": "Personalized ceramic mug, 11 oz",
"description": "A personalized name mug printed with the name you choose. 11oz white ceramic, dishwasher and microwave safe. Made to order in 1-3 days and shipped in a protective box, ready to gift for birthdays, holidays and thank-yous.",
"url": "https://www.etsy.com/listing/1834720561",
"state": "active",
"price": {
"amount": "18.50",
"currency": "USD",
"usd": "18.50"
},
"quantity": 37,
"skus": [
"MUG-NAME-11"
],
"tags": [
"personalized mug",
"name mug",
"custom mug",
"coffee mug",
"gift for her",
"birthday gift",
"ceramic mug",
"teacher gift",
"mom gift",
"custom name",
"christmas gift",
"office mug",
"tea mug"
],
"materials": [
"ceramic"
],
"category": {
"id": "1062"
},
"section": {
"id": "3301"
},
"shipping_profile_id": "4401",
"return_policy_id": "4501",
"processing_profile_id": null,
"production_partner_ids": null,
"who_made": "i_did",
"when_made": "made_to_order",
"is_supply": false,
"should_auto_renew": true,
"updated_at": "2026-10-17T12:00:00.000Z",
"as_of": "2026-10-17T12:00:00.000Z",
"change": {
"id": "chn_01JMOCK0000000000000000000",
"status": "succeeded",
"applied_fields": [
"title"
],
"failed_fields": []
},
"notices": []
}{
"object": "workspace.change",
"id": "<string>",
"shop_id": "<string>",
"target": {
"type": "<string>",
"id": "<string>"
},
"source": "<string>",
"actor": {
"type": "<string>",
"id": "<string>"
},
"write_id": "<string>",
"outcome": "<string>",
"fields": [
{
"field": "<string>",
"before": "<unknown>",
"after": "<unknown>",
"unrecorded": [
"before"
],
"omitted": [
"before"
]
}
],
"applied_fields": [
"<string>"
],
"failed_fields": [
{
"field": "<string>",
"code": "<string>"
}
],
"before_source": "<string>",
"before_as_of": "<string>",
"revertable": true,
"not_revertable_reason": "<string>",
"created_at": "<string>",
"as_of": "<string>"
}{
"type": "https://docs.alura.io/errors/invalid_request",
"title": "Invalid request",
"status": 400,
"code": "invalid_request",
"detail": "Invalid request",
"suggestion": "Fix the request as the detail says, then send it again.",
"retryable": false,
"request_id": "req_01JQ5W3H8M2N4P6R8T0V2X4Z6B"
}{
"type": "https://docs.alura.io/errors/unauthorized",
"title": "Unauthorized",
"status": 401,
"code": "unauthorized",
"detail": "Unauthorized",
"suggestion": "Send a valid API key as `Authorization: Bearer alura_sk_...`.",
"retryable": false,
"request_id": "req_01JQ5W3H8M2N4P6R8T0V2X4Z6B"
}{
"type": "https://docs.alura.io/errors/credits_exhausted",
"title": "API credits exhausted",
"status": 402,
"code": "credits_exhausted",
"detail": "API credits exhausted",
"suggestion": "Upgrade the plan or wait for the monthly reset.",
"retryable": false,
"request_id": "req_01JQ5W3H8M2N4P6R8T0V2X4Z6B"
}{
"type": "https://docs.alura.io/errors/plan_required",
"title": "Plan required",
"status": 403,
"code": "plan_required",
"detail": "Plan required",
"suggestion": "Upgrade the workspace plan to use this operation.",
"retryable": false,
"request_id": "req_01JQ5W3H8M2N4P6R8T0V2X4Z6B"
}{
"type": "https://docs.alura.io/errors/not_found",
"title": "Not found",
"status": 404,
"code": "not_found",
"detail": "Not found",
"suggestion": "Check the ID, or search for it first.",
"retryable": false,
"request_id": "req_01JQ5W3H8M2N4P6R8T0V2X4Z6B"
}{
"type": "https://docs.alura.io/errors/method_not_allowed",
"title": "Method not allowed",
"status": 405,
"code": "method_not_allowed",
"detail": "Method not allowed",
"suggestion": "Use one of the methods in the Allow header.",
"retryable": false,
"request_id": "req_01JQ5W3H8M2N4P6R8T0V2X4Z6B"
}{
"type": "https://docs.alura.io/errors/conflict",
"title": "Conflict",
"status": 409,
"code": "conflict",
"detail": "Conflict",
"suggestion": "Reload the resource and retry with its current state.",
"retryable": false,
"request_id": "req_01JQ5W3H8M2N4P6R8T0V2X4Z6B"
}{
"type": "https://docs.alura.io/errors/rate_limited",
"title": "Rate limited",
"status": 429,
"code": "rate_limited",
"detail": "Rate limited",
"suggestion": "Wait for Retry-After, then retry.",
"retryable": true,
"request_id": "req_01JQ5W3H8M2N4P6R8T0V2X4Z6B"
}{
"type": "https://docs.alura.io/errors/internal_error",
"title": "Internal error",
"status": 500,
"code": "internal_error",
"detail": "Internal error",
"suggestion": "Retry; if it keeps failing, report the request_id.",
"retryable": true,
"request_id": "req_01JQ5W3H8M2N4P6R8T0V2X4Z6B"
}{
"type": "https://docs.alura.io/errors/credits_unavailable",
"title": "API credits unavailable",
"status": 503,
"code": "credits_unavailable",
"detail": "API credits unavailable",
"suggestion": "Retry shortly.",
"retryable": true,
"request_id": "req_01JQ5W3H8M2N4P6R8T0V2X4Z6B"
}Authorizations
An API key: Authorization: Bearer alura_sk_....
Headers
Makes a retry safe: the same key with the same request within 24 hours answers from the first write (with Idempotent-Replayed: true) and never writes to Etsy twice; a write that failed with nothing written (Retry-After set) is tried again under it. The same key with a different request is a 409 conflict; while the first request still runs, 409 idempotency_processing (or the same 202). Required for relative changes such as adjust_price.
1 - 255Path Parameters
The Etsy listing ID. A listing outside the workspace is 404.
^[0-9]{1,20}$"1834720561"
Query Parameters
true: plan the write and send nothing: what it would change, the Etsy calls it would make, and nothing reserved, charged or recorded. Free; counts toward the per-minute write limit.
Body
The title, 1-140 characters.
1 - 140The description; replaces the whole text.
50000Every tag, at most 13; replaces them all (an empty list removes every tag). Not with tags_add or tags_remove.
131 - 30Tags to add to the tags the listing has on Etsy right now (read live when the write runs, not from Alura's copy); one already there is kept once. The result may have at most 13 tags.
1 - 13 elements1 - 30Tags to remove from the tags the listing has on Etsy right now, case-insensitive; one the listing does not have is ignored.
1 - 13 elements1 - 30Every material, at most 13; replaces them all.
131 - 45Etsy's category (its taxonomy_id), from browse_categories or GET /v1/categories.
^[1-9][0-9]{0,9}$Etsy's who_made.
i_did, someone_else, collective Etsy's when_made, for example made_to_order, 2020_2026 or before_2007.
^[a-z0-9_]{1,20}$true: a craft supply or tool; false: a finished product.
A section of the listing's shop; null takes the listing out of its section. A section of another shop is 404.
^[0-9]{1,20}$A shipping profile of the listing's shop. A profile of another shop is 404.
^[0-9]{1,20}$A return policy of the listing's shop; null removes the listing's policy. A policy of another shop is 404.
^[0-9]{1,20}$A processing profile of the listing's shop (list them with GET /v1/workspace/processing-profiles); set on every offering, so a listing with variations is 409 listing_has_variations without apply_to: "all_variants". A profile of another shop is 404.
^[0-9]{1,20}$Every production partner who helps make the item; replaces them all (an empty list removes them).
50A production partner of the listing's shop. A partner of another shop is 404.
^[0-9]{1,20}$true: Etsy renews the listing automatically when it expires (a listing fee each time).
inactive deactivates the listing on Etsy. Publishing (active) is not available through this operation yet.
inactive, active The new price of every offering in the listing's own currency, as a decimal string such as "24.99" (a number with at most 2 decimals is accepted too); above 0 and at most 50,000 in the listing's currency.
A relative price change of every offering. Needs a request key (REST Idempotency-Key, MCP request_id), so a retry never applies it twice.
Show child attributes
Show child attributes
The quantity in stock of every offering, 0-999.
0 <= x <= 999Add this many (negative to remove; never below 0) to every offering's quantity. Needs a request key, so a retry never applies it twice.
-999 <= x <= 999The SKU of every offering, at most 32 characters. Only on a listing without variations.
1 - 32all_variants: apply price, adjust_price, quantity, adjust_quantity or processing_profile_id to every variant of a listing with variations (without it such a listing is 409 listing_has_variations). Never for sku.
all_variants Response
OK: the write landed on Etsy (or, with dry_run=true, what it would do).
- Option 1
- Option 2
"workspace.listing"Etsy ID, as a string.
Etsy ID, as a string.
The listing on Etsy.
Etsy's listing state, for example active, inactive or draft.
The listing's price as Etsy answered; usd is null unless the listing is priced in USD.
Show child attributes
Show child attributes
The listing's total quantity across its enabled offerings, as Etsy and get_my_listing count it (not the per-offering value a request sends: 3 on each of 2 variants is 6).
Etsy's category (category_id in the request).
Show child attributes
Show child attributes
The shop section; null when the listing is in none.
Show child attributes
Show child attributes
Etsy ID, as a string.
Etsy ID, as a string.
The processing profile every offering has; null when they differ or Etsy did not say.
Etsy ID, as a string.
When Etsy last changed the listing.
When Etsy answered the write.
The write: its change ID and what landed.
Show child attributes
Show child attributes
Why a part of the answer is unknown; empty when nothing is.
Show child attributes
Show child attributes