Docs
Firmly Agentic Commerce
Set theme to dark (⇧+D)

Get Product from URL

GET https://api.firmly.work/api/v1/domains-pdp?url={pdp-url}

Retrieves product information from a merchant’s product detail page (PDP) URL. This endpoint extracts and returns the same detailed product data as the Get a Product endpoint.

​​ Authentication

This endpoint accepts either a device access token (Browser Session) or a Server-to-Server secret.

  • x-firmly-authorization (string, required) — Device access token from Browser Session (client-side) or a Server-to-Server secret (backend).

  • x-firmly-device-id (string) — Required only on the Server-to-Server path — the device ID of the client this request is on behalf of. Maximum 256 characters; allowed characters are a-z, A-Z, 0-9, -, _.

​​ Query Parameters

  • url (string, required) — The full merchant product page URL. Can be plain or URL-encoded. Examples:

    • https://staging.luma.gift/radiant-tee.html
    • https://staging.luma.gift/hero-hoodie.html?variant=MH07-M-Orange
  • postal_code (string) — Postal code to customize pricing, inventory, or availability based on location.

  • cache (boolean, default false) — When true, allows the response to be served from Firmly’s PDP cache (≈5-minute freshness) instead of fetching live from the merchant.

​​ Response

Returns the same Product Details structure as the Get a Product endpoint.

When the url includes a ?variant= parameter, its value is matched against each returned variant’s sku. Pass whatever the merchant’s PDP uses to identify the variant — this is often a string SKU such as WS12-XS-Orange, though some merchants use a numeric variant id. It is compared as-is against each variant’s sku. If the product has variants and none match, the response is 404 VariantNotFound with an available_variants list. The check is skipped when the product has no variants.

​​ Request Example


# Plain URL
curl --request GET \
--url 'https://api.firmly.work/api/v1/domains-pdp?url=https://staging.luma.gift/radiant-tee.html' \
--header 'x-firmly-authorization: YOUR_AUTH_TOKEN'
# URL with query parameters (encoded)
curl --request GET \
--url 'https://api.firmly.work/api/v1/domains-pdp?url=https%3A%2F%2Fstaging.luma.gift%2Fhero-hoodie.html%3Fvariant%3DMH07-M-Orange' \
--header 'x-firmly-authorization: YOUR_AUTH_TOKEN'

​​ Response Example


{
"base_sku": "WS12",
"title": "Radiant Tee",
"handle": "radiant-tee",
"description": "A comfortable and stylish tee perfect for any occasion",
"product_type": "Tees",
"images": [
{
"url": "https://cdn.staging.luma.gift/products/radiant-tee-main.jpg",
"type": "default"
}
],
"variant_option_values": [
{
"display_name": "Size",
"property_accessor": "size",
"position": 0,
"option_values": [
{
"display_name": "Medium",
"value": "M",
"available": true
}
]
},
{
"display_name": "Color",
"property_accessor": "color",
"position": 1,
"option_values": [
{
"display_name": "Orange",
"value": "Orange",
"available": true
}
]
}
],
"variants": [
{
"handle": "radiant-tee-m-orange",
"sku": "WS12-M-Orange",
"title": "Radiant Tee - M Orange",
"display_name": "M / Orange",
"add_to_cart_ref": {
"variant_id": "WS12-M-Orange"
},
"price": {
"currency": "USD",
"value": 22.00,
"number": 2200,
"symbol": "$"
},
"available": true,
"variant_option_list": ["M", "Orange"]
}
],
"reviews": {
"total_reviews": 127,
"average_rating": 4.5
}
}

​​ Error Responses

Errors return a JSON body with code, error, and description. Program against the error value — descriptions are human-readable and may change.

400 — InvalidRequest

The url query parameter is missing or empty.


{ "code": 400, "error": "InvalidRequest", "description": "Invalid request" }
400 — MissingAuthHeader

The x-firmly-authorization header is missing or empty (when authenticating as a device).


{ "code": 400, "error": "MissingAuthHeader", "description": "x-firmly-authorization header is missing or invalid." }
400 — InvalidToken

The authorization token is not a valid JWT structure.


{ "code": 400, "error": "InvalidToken", "description": "Jwt token is invalid." }
400 — InvalidAPIToken

The API token (server-to-server secret) is invalid or has been revoked.


{ "code": 400, "error": "InvalidAPIToken", "description": "API token is invalid." }
400 — BadRequest

Server-to-server auth was attempted but required headers are missing or malformed.


{ "code": 400, "error": "BadRequest", "description": "Bad request." }
401 — Unauthorized

The authorization token was rejected.


{ "code": 401, "error": "Unauthorized", "description": "Unauthorized." }
401 — InvalidJWTToken

The device JWT signature does not verify, or required claims are missing.


{ "code": 401, "error": "InvalidJWTToken", "description": "Jwt token is invalid." }
404 — PartnerNotFound

The appid claim on the device JWT does not map to a known partner / tenant.


{ "code": 404, "error": "PartnerNotFound", "description": "Partner not found." }
404 — DomainNotFound

The host of the supplied url does not match any merchant configured with Firmly, or the merchant has been disabled.


{ "code": 404, "error": "DomainNotFound", "description": "This domain was not found in firmly servers." }
404 — ProductNotFound

The merchant adapter could not resolve a product at the supplied url.


{ "code": 404, "error": "ProductNotFound", "description": "Product not found." }
412 — ProductNotSupported

The product type is not supported by this merchant’s adapter (e.g. some adapters reject gift cards, digital-only SKUs, or subscription items).


{ "code": 412, "error": "ProductNotSupported", "description": "Product is not supported." }
404 — VariantNotFound

The url requested a ?variant= that is not among the product’s variants. The response lists the available variants.


{
"code": 404,
"error": "VariantNotFound",
"description": "Variant WS12-L-Orange not found. Available variants: WS12-M-Orange, WS12-S-White",
"available_variants": [
{ "sku": "WS12-M-Orange", "title": "Radiant Tee - M Orange", "handle": "radiant-tee-m-orange", "available": true },
{ "sku": "WS12-S-White", "title": "Radiant Tee - S White", "handle": "radiant-tee-s-white", "available": true }
]
}
404 — ProductUrlNotImplemented

The merchant’s adapter does not support resolving a product from a URL.


{ "code": 404, "error": "ProductUrlNotImplemented", "description": "Product url is not implemented." }
410 — ProductDiscontinued

The product at the supplied url exists but has been discontinued by the merchant.


{ "code": 410, "error": "ProductDiscontinued", "description": "Product is discontinued." }
412 — OperationNotSupported

The merchant’s adapter does not support URL-based product resolution.


{ "code": 412, "error": "OperationNotSupported", "description": "This operation is not supported for this store." }
503 — StoreUnavailable

The merchant’s site returned an unexpected response and the product could not be retrieved. Retry with backoff.


{ "code": 503, "error": "StoreUnavailable", "description": "Store is unavailable." }