Attraction Product API
Integrate Attraction product data with REST/JSON requests. The current API covers promotional products, with public MSRP and account net prices through an API key.
Quick start
Run this request from a terminal to fetch public product summaries.
curl --compressed "https://api.attraction.com/v1/products?locale=en-CA"Catalog responses support gzip. The --compressed option requests a compressed response and lets cURL decode it automatically.
List products
Fetches product summaries for catalogs, listing pages, search, filters, and color exploration.
Public request
curl --compressed "https://api.attraction.com/v1/products?locale=en-CA"{
"locale": "en-CA",
"products": [
{
"sku": "100386U",
"slug": "100386u",
"productName": "Crewneck T-shirt",
"descriptions": {
"tagline": "Crewneck t-shirt, our best-selling t-shirt. Ethica made in Canada.",
"short": "Crewneck t-shirt in jersey in organic cotton and recycled polyester, or 100% organic cotton depending on the colour, our best-selling t-shirt, wide colour range. Ethica made in Canada."
},
"brand": "Ethica",
"customization": {
"colorBlocks": false
},
"catalog": {
"inspiration": ["Promotional"],
"category": "T-shirts",
"for": "Unisex"
},
"keywords": ["t shirt","custom t shirt","crewneck","ethica","made in canada"],
"tag": "Best seller",
"minimumOrder": {
"quantity": 36,
"description": "Minimum 36 decorated units. No minimum undecorated."
},
"studio": {
"available": true
},
"pricing": {
"currency": "CAD",
"msrp": [
{ "minQuantity": 1, "maxQuantity": 23, "price": 30.5 },
{ "minQuantity": 24, "maxQuantity": 99, "price": 28 }
]
},
"images": [
{
"url": "https://www.attraction.com/assets/products/100386u/100386u-primary.webp",
"alt": "White Ethica crewneck T-shirt"
}
],
"colors": [
{
"id": "0001",
"pms": "White",
"name": "White",
"swatches": ["#FFFFFF"],
"colorFamilies": [
{
"name": "White",
"hex": "#F8F8F2"
}
],
"images": [
"https://www.attraction.com/assets/products/100386u/100386u-white.webp"
]
}
]
}
],
"categories": [
{
"name": "T-shirts",
"order": 10
}
],
"brands": {
"Ethica": {
"name": "Ethica",
"url": "https://www.attraction.com/en-ca/products/ethica/",
"description": "Timeless classics, made in Canada with sustainable fibres."
}
}
}Get product details
Fetches one product for a product page, catalog sync, inventory check, asset lookup, or decoration compatibility lookup.
Public request
Product detail, MSRP pricing, available sizes and size upcharges, inventory, color metadata, materials, media, resource links, and compatible decoration methods, without authentication.
curl "https://api.attraction.com/v1/products/100386U?locale=en-CA"{
"sku": "100386U",
"slug": "100386u",
"locale": "en-CA",
"productName": "Crewneck T-shirt",
"descriptions": {
"tagline": "Crewneck t-shirt, our best-selling t-shirt. Ethica made in Canada.",
"short": "Crewneck t-shirt in jersey in organic cotton and recycled polyester, or 100% organic cotton depending on the colour, our best-selling t-shirt, wide colour range. Ethica made in Canada.",
"long": "Crewneck t-shirt. Fabric: jersey in organic cotton and recycled polyester, or 100% organic cotton depending on the colour. Key features: our best-selling t-shirt, wide colour range."
},
"keywords": ["t shirt","custom t shirt","crewneck","ethica","made in canada"],
"note": "For women, order a smaller size than usual (M=S), since this is a unisex style.",
"brand": {
"name": "Ethica",
"url": "https://www.attraction.com/en-ca/products/ethica/",
"description": "Timeless classics, made in Canada with sustainable fibres."
},
"insufficientInventoryMessage": "Insufficient inventory for your project? Ethica styles can usually be produced quickly. Contact us and we'll confirm lead times.",
"catalog": {
"inspiration": ["Promotional"],
"category": "T-shirts",
"for": "Unisex"
},
"links": {
"studio": "https://studio.jameo.com/home?lang=en"
},
"tag": "Best seller",
"minimumOrder": {
"quantity": 36,
"description": "Minimum 36 decorated units. No minimum undecorated."
},
"customization": {
"colorBlocks": false,
"decorations": [
{
"name": "Digital Print (DTG)",
"note": "",
"icon": "https://www.attraction.com/assets/icons/digital-printing.svg",
"link": "https://www.attraction.com/en-ca/decoration/#digital-printing"
}
]
},
"studio": {
"available": true
},
"pricing": {
"currency": "CAD",
"msrp": [
{ "minQuantity": 1, "maxQuantity": 23, "price": 30.5 },
{ "minQuantity": 24, "maxQuantity": 99, "price": 28 }
],
"sizes": [
{ "name": "XS" },
{ "name": "2XL", "surcharge": { "msrp": 4.5 } }
]
},
"images": [
{
"url": "https://www.attraction.com/assets/products/100386u/100386u-primary.webp",
"alt": "White Ethica crewneck T-shirt"
}
],
"assets": {
"images": [
{
"url": "https://www.attraction.com/assets/products/100386u/100386u-primary.webp",
"alt": "White Ethica crewneck T-shirt"
}
],
"resources": [
{
"type": "sizeChart",
"label": "Size chart",
"url": "https://www.attraction.com/assets/products/100386u/100386u.pdf"
}
]
},
"colors": [
{
"id": "0001",
"pms": "White",
"name": "White",
"material": {
"composition": "50% organic cotton, 50% recycled polyester",
"weight": "7.4 oz/linear yd (150 gsm)",
"gsm": 150
},
"swatches": ["#FFFFFF"],
"colorFamilies": [
{
"name": "White",
"hex": "#F8F8F2"
}
],
"images": [
"https://www.attraction.com/assets/products/100386u/100386u-white.webp"
]
}
],
"inventory": [
{ "colorId": "0001", "size": "XS", "quantity": 124 }
]
}Discounted prices
In each tier, price is the current price. regularPrice appears only when that price is reduced (a markdown) and names the original regular price. The same convention applies to pricing.msrp and pricing.net.
{
"pricing": {
"msrp": [
{ "minQuantity": 1, "maxQuantity": 23, "regularPrice": 30, "price": 25 }
],
"net": [
{ "minQuantity": 1, "maxQuantity": 23, "regularPrice": 18, "price": 15 }
]
}
}Net pricing through the API
With an account API key, the product detail response also returns the account's net prices, pricing.net.
The product detail response identifies the account's tier in pricing.priceTier; the pricing-only endpoints return priceTier at the top level. A key follows its account's price tier. Tier changes can take up to 60 seconds to appear in API responses.
The product list, /v1/products, stays MSRP-only either way. A whole catalog is priced through the bulk endpoint below.
Authenticated request
curl -H "Authorization: Bearer $ATTRACTION_API_KEY" \
"https://api.attraction.com/v1/products/100386U?locale=en-CA"{
"sku": "100386U",
"locale": "en-CA",
"pricing": {
"currency": "CAD",
"priceTier": "A2",
"msrp": [
{ "minQuantity": 1, "maxQuantity": 23, "price": 30.5 }
],
"net": [
{ "minQuantity": 1, "maxQuantity": 23, "price": 22.75 }
],
"sizes": [
{ "name": "XS" },
{ "name": "2XL", "surcharge": { "msrp": 4.5, "net": 3.4 } }
]
}
}Pricing for one product
GET /v1/products/{sku}/pricing returns the same price data as the product detail, without the rest of the product, shown in the response alongside. It has no public representation, so it always requires a key: a call with no credentials gets 401 key_required rather than an anonymous MSRP answer.
curl -H "Authorization: Bearer $ATTRACTION_API_KEY" \
"https://api.attraction.com/v1/products/100386U/pricing?locale=en-CA"{
"sku": "100386U",
"currency": "CAD",
"priceTier": "A2",
"msrp": [
{ "minQuantity": 1, "maxQuantity": 23, "price": 30.5 }
],
"net": [
{ "minQuantity": 1, "maxQuantity": 23, "price": 22.75 }
],
"sizes": [
{ "name": "XS" },
{ "name": "2XL", "surcharge": { "msrp": 4.5, "net": 3.4 } }
]
}Pricing for the whole catalog
GET /v1/products/pricing returns that same price data for every product in the requested locale, in one response, with entries sorted by sku. Use this endpoint to update prices in a catalog already in storage. Like the single-product route, it always requires a key.
curl -H "Authorization: Bearer $ATTRACTION_API_KEY" \
"https://api.attraction.com/v1/products/pricing?locale=en-CA"{
"currency": "CAD",
"priceTier": "A2",
"products": [
{
"sku": "100222U",
"msrp": [
{ "minQuantity": 1, "maxQuantity": 23, "price": 42 }
],
"net": [
{ "minQuantity": 1, "maxQuantity": 23, "price": 31.5 }
],
"sizes": [
{ "name": "2XL", "surcharge": { "msrp": 5, "net": 3.75 } }
]
},
{
"sku": "100386U",
"msrp": [
{ "minQuantity": 1, "maxQuantity": 23, "price": 30.5 }
],
"net": [
{ "minQuantity": 1, "maxQuantity": 23, "price": 22.75 }
],
"sizes": [
{ "name": "XS" },
{ "name": "2XL", "surcharge": { "msrp": 4.5, "net": 3.4 } }
]
}
]
}Authentication
Send your account API key as Authorization: Bearer attr_sk_... on each request that needs the account's net prices.
Keys are read-only and never expire; an account holds at most 10 active ones. On product detail and pricing routes, an unusable key gets 401 (invalid_key or key_revoked) rather than a silent fallback to MSRP.
Revoking a key can take up to 60 seconds to affect API responses while a cached verification expires.
Attraction Studio accounts are reserved for distributors. An account already linked to an Attraction distributor automatically receives Studio access, its price tier and the ability to create API keys. Other distributors need our team's approval before these become available.
Rate limits
Request quotas, response headers and retry timing are documented in the REST API rate-limit policy.
Versioning and deprecation
Check the REST API compatibility policy and the integration changelog for deprecation notices and migration requirements.
Error responses
Errors are RFC 9457 objects served as application/problem+json. The examples below show the response shape; each code links to its cause and recovery instructions. Public product requests work without credentials, but both pricing endpoints require an API key.
code is one of: route_not_found, method_not_allowed, invalid_request, unsupported_locale, invalid_sku, unauthorized, key_required, invalid_key, key_revoked, product_not_found, rate_limited, upstream_unavailable, internal_error.
unsupported_locale
400 when locale is not one of en-CA, en-US, or fr-CA.
{
"type": "https://www.attraction.com/developers/#error-unsupported_locale",
"title": "Unsupported locale",
"status": 400,
"detail": "Supported locales are en-CA, en-US, and fr-CA.",
"instance": "/v1/products",
"code": "unsupported_locale"
}key_revoked
401 when the API key was revoked, or the Attraction account behind it no longer holds distributor pricing.
{
"type": "https://www.attraction.com/developers/#error-key_revoked",
"title": "API key revoked",
"status": 401,
"detail": "This API key is no longer active: it was revoked, or the Attraction account behind it no longer holds distributor pricing. Check the key and the account at https://www.attraction.com/api/keys/.",
"instance": "/v1/products/100386u",
"code": "key_revoked"
}product_not_found
404 for /v1/products/{sku} when the SKU does not exist.
{
"type": "https://www.attraction.com/developers/#error-product_not_found",
"title": "Product not found",
"status": 404,
"detail": "No product matches SKU NOPE-NOT-A-SKU.",
"instance": "/v1/products/nope-not-a-sku",
"code": "product_not_found"
}rate_limited
429 when the request exceeds the v1 rate limit.
{
"type": "https://www.attraction.com/developers/#error-rate_limited",
"title": "Too many requests",
"status": 429,
"detail": "The default rate limit is 600 requests per minute per client IP. Retry after the window resets.",
"instance": "/v1/products",
"code": "rate_limited"
}