Tells Warden until when a shop has to register with you. Some findings reach Needs you partly because the shop is not one your members registered, and Warden shows the date on those. Registration deadlines explains when to send one and what Warden does with it.
It needs a key made with Can also send shop registration deadlines ticked, the scope
shop_status. Any other key is answered 403 with scope_not_granted.
A shop is named by its own page, read the way Warden reads a registered storefront. The shop is the
key, so sending one again replaces what Warden held for it, and grace_until: null clears a date.
Query
| Parameter | |
|---|---|
dry_run | 1 to check the key and read every record, and store nothing. true is read the same way. 0 or false is a real request, and any other value is refused. |
Body
At most 500 records. Each shop once per request.
| Field | Type | |
|---|---|---|
url | string, required | The shop's own page: https://www.etsy.com/shop/<name>, <name>.etsy.com, or an eBay /usr/ or /str/ address. Up to 500 characters. |
grace_until | date or null, required | When the shop's time to register ends. Null clears a date sent earlier. |
letter_sent_at | date or null | When you wrote to the shop, if you did. |
Any other field is refused by name. A listing address names no shop and is refused.
Request
curl -sS -X POST "https://3dwarden.com/api/v1/integration/shop-status" \
-H "Authorization: Bearer $WARDEN_KEY" \
-H "Content-Type: application/json" \
-d '{ "records": [ { "url": "https://www.etsy.com/shop/ExamplePrints", "grace_until": "2026-10-23T00:00:00Z", "letter_sent_at": "2026-09-23T00:00:00Z" } ] }'const res = await fetch('https://3dwarden.com/api/v1/integration/shop-status', {
method: 'POST',
headers: { Authorization: `Bearer ${process.env.WARDEN_KEY}`, 'Content-Type': 'application/json' },
body: JSON.stringify({ records: [{ url: 'https://www.etsy.com/shop/ExamplePrints', grace_until: '2026-10-23T00:00:00Z' }] }),
})
if (!res.ok) throw new Error(`${res.status} ${(await res.json()).code}`)
const { written, rejected } = await res.json()import os, requests
res = requests.post(
"https://3dwarden.com/api/v1/integration/shop-status",
headers={"Authorization": f"Bearer {os.environ['WARDEN_KEY']}"},
json={"records": [{"url": "https://www.etsy.com/shop/ExamplePrints", "grace_until": "2026-10-23T00:00:00Z"}]},
timeout=30,
)
res.raise_for_status()Response, 200
{
"written": 1,
"records": [
{ "index": 0, "source": "etsy", "shop": "exampleprints", "grace_until": "2026-10-23T00:00:00.000Z" }
],
"rejected": []
}| Field | Type | |
|---|---|---|
written | integer | How many shops were written. Absent on a dry run, and when every record in the batch was rejected. |
dry_run | boolean | Present and true on a dry run. |
records[].index | integer | The record's position in your request. |
records[].source | string | etsy or ebay, from the address. |
records[].shop | string | The shop name Warden read from the address, lowercased. It is the name Warden compares. |
records[].grace_until | date or null | The date you sent, in the form 2026-10-23T00:00:00.000Z. |
rejected[] | object | A record Warden refused, by index, with your url and the reason in because. Nothing of it was stored. |
Errors
| Status | Code | |
|---|---|---|
| 400 | invalid_request | The body is not { "records": [ ... ] }, is empty, or holds more than 500 records, or dry_run is a value Warden does not read. |
| 401 | invalid_key | The key is missing, malformed, unknown or revoked. |
| 403 | scope_not_granted | The key was not granted shop_status. scope names it. |
| 429 | rate_limited | The key is over its allowance. Wait for Retry-After. |