Integration Guide
Everything your store needs to list products, attribute sales, and get paid. All API requests go to https://app.wardrowbe.com/api/v1 and all amounts are USD.
Authentication
Every API request is authenticated with an API key you generate in the portal’s Settings tab after signing in with your emailed link. Send it in the X-Partner-API-Key header. The key is shown once at generation; keep it secret, and rotate it any time from the same tab, which invalidates the old key immediately.
curl https://app.wardrowbe.com/api/v1/partner/me \
-H "X-Partner-API-Key: sp_your_key_here"Product feed
Give us an HTTPS URL that returns your catalog as JSON and we pull it four times a day (you can also trigger a sync from the portal). The feed is either a top-level array of products or an object with a products array.
Limits: 500 products, 10 MB, HTTPS only. Products with an external_product_id we have seen before are updated in place; without it, feed items are created once and never updated.
{
"products": [
{
"external_product_id": "SKU-1042",
"name": "Classic White Oxford Shirt",
"external_url": "https://yourstore.com/products/oxford-white",
"image_url": "https://yourstore.com/images/oxford-white.jpg",
"price_cents": 6900,
"currency": "USD",
"clothing_type": "shirt",
"colors": ["white"],
"style": ["smart-casual", "formal"],
"formality": "smart-casual",
"season": ["all-season"],
"sizes_available": ["S", "M", "L", "XL"],
"gender_target": "unisex"
}
]
}Feed fields
| Field | Required | Notes |
|---|---|---|
name | yes | Product display name, max 255 chars |
external_url | yes | HTTPS product page URL on your store |
price_cents | yes | Integer price in cents (USD only) |
clothing_type | yes | One of: shirt, t-shirt, top, polo, blouse, tank-top, sweater, hoodie, cardigan, vest, pants, jeans, shorts, skirt, dress, jumpsuit, jacket, blazer, coat, suit, shoes, sneakers, boots, sandals, socks, tie, hat, scarf, belt, bag, accessories, underwear, swimwear. Other values are rejected with a feed item error. Underwear is accepted in feeds but never shown in user suggestions; correct labeling is your responsibility, and intimates cataloged under another type will be treated as that type |
external_product_id | recommended | Your stable product ID; enables updates instead of duplicates |
currency | no | Must be "USD" when present; other currencies are rejected |
description | no | Plain-text description |
image_url | no | HTTPS product image URL |
colors | no | Array of lowercase color names |
primary_color | no | Single dominant color |
pattern | no | e.g. solid, striped, plaid |
material | no | e.g. cotton, wool, leather |
style | no | Array of style tags: casual, formal, streetwear, … |
formality | no | casual, smart-casual, or formal |
season | no | Array: summer, winter, all-season, … |
sizes_available | no | Array of size strings |
gender_target | no | unisex (default), male, or female. Scopes which users can be shown the product, based on their shopping preference |
is_active | no | Set false to hide a product without deleting it |
Items with any other currency are skipped and reported in your feed status. Use the portal’s Feed tab to validate the feed before your first sync.
Products API
Prefer to push instead of being pulled? Manage products directly. The same fields as the feed apply.
# List your products
GET /api/v1/partner/me/products
# Create a product
POST /api/v1/partner/me/products
{ "name": "...", "external_url": "https://...", "price_cents": 6900, "clothing_type": "shirt" }
# Update a product
PATCH /api/v1/partner/me/products/{product_id}
# Remove a product
DELETE /api/v1/partner/me/products/{product_id}Click attribution
When a user clicks one of your products, we redirect them to your external_url with tracking parameters appended. Persist wr_sid (for example in the visitor’s session or cart): it is the suggestion ID you must echo back when the order completes. A conversion must be reported within 30 days of the click; claims against older clicks are rejected with 409.
https://yourstore.com/products/oxford-white
?utm_source=wardrowbe
&utm_medium=partner
&utm_campaign=wardrobe_gap
&ref=wardrowbe
&wr_sid=7f3d2a10-9c4b-4e2f-8a1d-2b6c9e5f0a44 <- keep thisReporting conversions
When an attributed order is placed, report it with the stored wr_sid as suggestion_id. Reporting is idempotent per order_reference: replaying the exact same report is safe and returns the original result, while reusing an order reference with a different suggestion or amount is rejected with 409. amount_cents is the order total in USD cents; it is the basis for your commission and is reviewed before you are invoiced. If one order contains several suggested items, report each suggestion separately with a per-line reference such as ORDER123-1, ORDER123-2.
POST /api/v1/partner/me/conversions
X-Partner-API-Key: sp_your_key_here
Content-Type: application/json
{
"suggestion_id": "7f3d2a10-9c4b-4e2f-8a1d-2b6c9e5f0a44",
"order_reference": "ORDER-2026-18492",
"amount_cents": 6900
}Reporting refunds
If an attributed order is refunded, tell us so the commission is deducted from your next invoice instead of being billed and reversed later. Every refund needs a refund_reference that is unique within your store (your RMA or credit-note number works); replays with the same reference are idempotent, and the same reference with a different amount is rejected with 409. Omit amount_cents to refund the full remaining amount, or send a partial amount; partial refunds accumulate, and refunding more than the reported order total is rejected with 409.
POST /api/v1/partner/me/refunds
{
"suggestion_id": "7f3d2a10-9c4b-4e2f-8a1d-2b6c9e5f0a44",
"refund_reference": "RMA-2026-00311",
"amount_cents": 3450,
"reason": "Customer returned one of two items"
}Webhooks
Configure a webhook URL and signing secret in the portal’s Settings tab to receive events: conversion, refund, feed_sync_completed, and feed_sync_failed. Each delivery carries the event name, a unique delivery ID, a Unix timestamp, and an HMAC-SHA256 signature computed with your secret over the timestamp, a period, and the raw request body. Verify against the exact bytes you received (do not re-serialize the JSON), and reject deliveries whose timestamp is more than a few minutes old to block replays.
Failed deliveries are retried five times with increasing delays (about 1 minute, 5 minutes, 30 minutes, then 2 hours apart), so a short outage on your side does not lose events.
POST https://yourstore.com/webhooks/wardrowbe
X-Wardrowbe-Event: conversion
X-Wardrowbe-Delivery: 0d5c9a3e-...
X-Wardrowbe-Timestamp: 1783958400
X-Wardrowbe-Signature: 3f5a9c... # hex(hmac_sha256(secret, timestamp + "." + raw_body))
# Verify (Python)
import hashlib, hmac, time
signed = f"{timestamp_header}.".encode() + raw_body
expected = hmac.new(secret.encode(), signed, hashlib.sha256).hexdigest()
valid = (
hmac.compare_digest(expected, signature_header)
and abs(time.time() - int(timestamp_header)) < 300
)Commission
You keep 100% of every sale. Commission accrues on reported conversions minus refunds, at the rate in your partnership agreement, and we invoice you for it. See Commission & Attribution for the full lifecycle: monthly calculation, review, charge, and the minimum roll-forward.
Questions or feed URL changes: [email protected].