> This page is for API, version 2026-01-01 (Stable) (default).
> For other versions, use one of these documentation indexes:
> - 2026-01-01 (Stable) (default): https://developer.deel.com/api/stable/llms.txt

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://developer.deel.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://developer.deel.com/_mcp/server.

# Retrieve a product's catalog details

GET https://api.letsdeel.com/rest/it/products/{product_id}

Returns catalog data for a single product — variants, images, hardware spec, and available addons. Variants are filtered to those the organization's allowed acquisition types cover, and (when country is supplied) to those shipping to that country. No pricing, taxes, fees, contract-setting-derived values, or stock counts are returned. Use this after listing products to pull a specific product's variant and addon options before creating an order.

 **Token scopes**: `it-products:read`

 **Beta**: this version requires the `X-Beta: true` request header and its contract may change before it is promoted to stable. It is scheduled to become stable on 2026-12-17.

Reference: https://developer.deel.com/api/deel-it/endpoints/it-products/retrieve-an-it-product-v-2026-09-17

## Authentication

- `Authorization` header (bearer token, required) — ## Authentication The Deel API uses bearer tokens to authenticate requests. All API calls must be made over HTTPS — calls over plain HTTP or without authentication will fail. ```curl curl -X GET 'https://api.letsdeel.com/rest/v2/contracts' \ -H 'Authorization: Bearer YOUR-TOKEN-HERE' ``` [Learn more about authentication](/api/authentication)
- `Authorization` header (bearer token, required) — Standard OAuth2 security scheme based on https://swagger.io/docs/specification/authentication/

## Servers

- `https://api.letsdeel.com/rest` (Production, default)
- `https://api-staging.letsdeel.com/rest` (Demo)

## Request

### Path parameters

- `product_id` (string, required) — Unique identifier of the product

### Query parameters

- `country` (string, optional) — ISO 3166 alpha-2 country code. When set, restricts returned variants to those shipping to this country.

### Headers

- `X-Beta` (enum, required, default: true) — Opts in to the beta version of this endpoint. Must be `true`.
  - Allowed values: `true`

## Response

### 200

OK

- `data` (ItProductsProductIdGetResponsesContentApplicationJsonSchemaData, required)

## Errors

### 400 Bad Request Error

Bad Request

- `errors` (list of ItProductsProductIdGetResponsesContentApplicationJsonSchemaErrorsItems, required)

### 401 Unauthorized Error

Operation failed.

- `request` (ApiErrorRequest, optional)
- `errors` (list of ApiError, optional)

### 403 Forbidden Error

Operation failed.

- `request` (ApiErrorRequest, optional)
- `errors` (list of ApiError, optional)

### 404 Not Found Error

Not Found

- `errors` (list of ItProductsProductIdGetResponsesContentApplicationJsonSchemaErrorsItems, required)

### 500 Internal Server Error

Internal Server Error

- `errors` (list of ItProductsProductIdGetResponsesContentApplicationJsonSchemaErrorsItems, required)

## Types

### ItProductsProductIdGetResponsesContentApplicationJsonSchemaData

- `id` (string, required) — Unique identifier of the product
- `name` (string, required) — Product name
- `brand` (string, required) — Company that produced the product
- `images` (list of ItProductsProductIdGetResponsesContentApplicationJsonSchemaDataImagesItems, required) — Ordered list of product images. The first element is the cover image.
- `category` (enum, required) — Product category
  - Allowed values: `ADAPTER`, `CABLE`, `CHAIR`, `CHARGER`, `COMPACT_DESKTOP`, `DESK`, `DESKTOP`, `DESK_RISER`, `DESK_TIDY`, `DOCKING_STATION`, `DONGLE`, `FOOTREST`, `HEADSET`, `KEYBOARD`, `LAPTOP`, `LAPTOP_STAND`, `MICE_TRACKPAD`, `MOBILE_DEVICE`, `MONITOR`, `MONITOR_ARM`, `OTHER`, `PRINTER`, `SHREDDER`, `STANDING_MAT`, `TABLET`, `TASK_LIGHT`, `WEBCAM`, `WELCOME_PACK`, `WIFI_RANGE_EXTENDER`
- `variants` (list of ItProductsProductIdGetResponsesContentApplicationJsonSchemaDataVariantsItems, required) — Catalog variants for this product — one per SKU
- `public_id` (string, required) — Public identifier of the product
- `description` (string, required) — Free-text product description
- `available_addons` (list of ItProductsProductIdGetResponsesContentApplicationJsonSchemaDataAvailableAddonsItems, required) — Menu of addons the organization has available to attach on POST /orders. Callers submit an addon by `id` on the order's contract_setting.addons[]. Pricing is not returned in Bundle 2 — the invoice reveals amounts once the order lands.
- `product_hardware_spec` (ItProductsProductIdGetResponsesContentApplicationJsonSchemaDataProductHardwareSpec, required, nullable) — Structured hardware detail — nullable when no hardware spec is recorded (accessories, consumables)

### ItProductsProductIdGetResponsesContentApplicationJsonSchemaErrorsItems

- `code` (string, required) — Error code of the handler which produced the returned error
- `field` (string, required, nullable) — The field name where input validation failed
- `message` (string, required) — Description of the returned error

### ApiErrorRequest

- `method` (string, optional) — The HTTP method of the failed request
- `url` (string, optional) — The relative URL of the failed request
- `status` (double, optional) — The status code of the response
- `api_req_id` (string, optional) — The request ID of the failed request
- `docs` (string, optional) — A link to the official documentation for the requested endpoint resource
- `source` (string, optional) — The source handler which produced the returned error
- `code` (double, optional) — The code of the source handler which produced the returned error

### ApiError

- `message` (string, optional) — A description of the returned error
- `path` (string, optional) — The JSON path where input validation failed

### ItProductsProductIdGetResponsesContentApplicationJsonSchemaDataImagesItems

- `id` (string, required) — Unique identifier of the image
- `url` (string, required) — Public URL of the image

### ItProductsProductIdGetResponsesContentApplicationJsonSchemaDataVariantsItems

- `id` (string, required) — Unique identifier of the variant
- `sku` (string, required, nullable) — SKU of the variant
- `size` (string, required, nullable) — Physical size or dimension label — style + size together uniquely identify a variant within a product
- `image` (ItProductsProductIdGetResponsesContentApplicationJsonSchemaDataVariantsItemsImage, required, nullable) — Image of this variant, null when the variant has no image
- `style` (string, required, nullable) — Marketing style (colour, tier, etc.) — style + size together uniquely identify a variant within a product
- `public_id` (string, required) — Public identifier of the variant
- `keyboard_layout` (enum, required, nullable) — Physical keyboard layout (laptops only)
  - Allowed values: `BELGIAN_AZERTY`, `CANADIAN_MULTILINGUAL_STANDARD_QWERTY`, `CZECH_QWERTY`, `DANISH_QWERTY`, `DUTCH_QWERTY`, `EGYPTIAN_LOCAL`, `ENGLISH_RUSSIAN_QWERTY`, `EU_STANDARD_QWERTY`, `FRENCH_AZERTY`, `GERMAN_QWERTZ`, `INDIAN_QWERTY`, `INTERNATIONAL_ENGLISH_QWERTY`, `ITALIAN_QWERTY`, `JAPANESE_QWERTY`, `KOREAN_QWERTY`, `LATAM_QWERTY`, `NORWEGIAN_QWERTY`, `PORTUGUESE_QWERTY`, `SPANISH_QWERTY`, `SWEDISH_QWERTY`, `SWISS_FRENCH_QWERTZ`, `SWISS_GERMAN_QWERTZ`, `TURKISH_QWERTY`, `UK_ENGLISH_QWERTY`, `UNKNOWN`, `US_ENGLISH_QWERTY`
- `operating_system` (enum, required, nullable) — Operating system installed on this variant (devices only)
  - Allowed values: `ANDROID_PHONE`, `ANDROID_TABLET`, `CHROME_OS`, `IOS_PHONE`, `IOS_TABLET`, `LINUX`, `MACOS`, `WINDOWS`
- `available_countries` (list of enum, required) — ISO 3166 alpha-2 country codes where this variant can be ordered
  - Allowed values: `AD`, `AE`, `AF`, `AG`, `AI`, `AL`, `AM`, `AN`, `AO`, `AQ`, `AR`, `AS`, `AT`, `AU`, `AW`, `AX`, `AZ`, `BA`, `BB`, `BD`, `BE`, `BF`, `BG`, `BH`, `BI`, `BJ`, `BL`, `BM`, `BN`, `BO`, `BQ`, `BR`, `BS`, `BT`, `BV`, `BW`, `BY`, `BZ`, `CA`, `CC`, `CD`, `CF`, `CG`, `CH`, `CI`, `CK`, `CL`, `CM`, `CN`, `CO`, `CR`, `CU`, `CV`, `CW`, `CX`, `CY`, `CZ`, `DE`, `DJ`, `DK`, `DM`, `DO`, `DZ`, `EC`, `EE`, `EG`, `EH`, `ER`, `ES`, `ET`, `FI`, `FJ`, `FK`, `FM`, `FO`, `FR`, `GA`, `GB`, `GD`, `GE`, `GF`, `GG`, `GH`, `GI`, `GL`, `GM`, `GN`, `GP`, `GQ`, `GR`, `GS`, `GT`, `GU`, `GW`, `GY`, `HK`, `HM`, `HN`, `HR`, `HT`, `HU`, `IC`, `ID`, `IE`, `IL`, `IM`, `IN`, `IO`, `IQ`, `IR`, `IS`, `IT`, `JE`, `JM`, `JO`, `JP`, `KE`, `KG`, `KH`, `KI`, `KM`, `KN`, `KP`, `KR`, `KW`, `KY`, `KZ`, `LA`, `LB`, `LC`, `LI`, `LK`, `LR`, `LS`, `LT`, `LU`, `LV`, `LY`, `MA`, `MC`, `MD`, `ME`, `MF`, `MG`, `MH`, `MK`, `ML`, `MM`, `MN`, `MO`, `MP`, `MQ`, `MR`, `MS`, `MT`, `MU`, `MV`, `MW`, `MX`, `MY`, `MZ`, `NA`, `NC`, `NE`, `NF`, `NG`, `NI`, `NL`, `NO`, `NP`, `NR`, `NU`, `NZ`, `OM`, `PA`, `PE`, `PF`, `PG`, `PH`, `PK`, `PL`, `PM`, `PN`, `PR`, `PS`, `PT`, `PW`, `PY`, `QA`, `RE`, `RO`, `RS`, `RU`, `RW`, `SA`, `SB`, `SC`, `SD`, `SE`, `SG`, `SH`, `SI`, `SJ`, `SK`, `SL`, `SM`, `SN`, `SO`, `SR`, `SS`, `ST`, `SV`, `SX`, `SY`, `SZ`, `TC`, `TD`, `TF`, `TG`, `TH`, `TJ`, `TK`, `TL`, `TM`, `TN`, `TO`, `TR`, `TT`, `TV`, `TW`, `TZ`, `UA`, `UG`, `US`, `UY`, `UZ`, `VA`, `VC`, `VE`, `VG`, `VI`, `VN`, `VU`, `WF`, `WS`, `XK`, `YE`, `YT`, `ZA`, `ZM`, `ZW`
- `allowed_rental_terms` (list of enum, required) — Rental terms permitted for this variant. Empty for non-rental variants.
  - Allowed values: `MONTH_12`, `MONTH_24`
- `allowed_acquisition_types` (list of enum, required) — Acquisition types allowed for this variant
  - Allowed values: `PURCHASE`, `RENTAL`, `REUSE`

### ItProductsProductIdGetResponsesContentApplicationJsonSchemaDataAvailableAddonsItems

- `id` (string, required) — Unique identifier of the addon. Submit this on POST /orders under contract_setting.addons[].id.
- `name` (string, required) — Public name of the addon
- `type` (enum, required) — Kind of addon — SERVICE bundles cover service/support, WARRANTY bundles cover extended cover.
  - Allowed values: `SERVICE`, `WARRANTY`
- `is_premium` (boolean, required) — Whether the addon is a premium (paid) offering. Free/default addons are false.

### ItProductsProductIdGetResponsesContentApplicationJsonSchemaDataProductHardwareSpec

Structured hardware detail — nullable when no hardware spec is recorded (accessories, consumables)

- `memory_gb` (long, required, nullable) — Memory (RAM) capacity in gigabytes (laptops, mobile devices, tablets)
- `processor` (string, required, nullable) — Processor model (laptops only)
- `storage_gb` (long, required, nullable) — Storage capacity in gigabytes (laptops, mobile devices, tablets)
- `display_size` (string, required, nullable) — Diagonal display size in inches (devices with a screen only)
- `storage_type` (enum, required, nullable) — Storage medium type (laptops only)
  - Allowed values: `HDD`, `SSD`
- `has_hdmi_port` (boolean, required, nullable) — Whether the device has an HDMI port (laptops, monitors)
- `has_display_port` (boolean, required, nullable) — Whether the device has a DisplayPort connection (laptops, monitors)
- `product_category` (enum, required) — Category of the product this hardware spec belongs to
  - Allowed values: `ADAPTER`, `CABLE`, `CHAIR`, `CHARGER`, `COMPACT_DESKTOP`, `DESK`, `DESKTOP`, `DESK_RISER`, `DESK_TIDY`, `DOCKING_STATION`, `DONGLE`, `FOOTREST`, `HEADSET`, `KEYBOARD`, `LAPTOP`, `LAPTOP_STAND`, `MICE_TRACKPAD`, `MOBILE_DEVICE`, `MONITOR`, `MONITOR_ARM`, `OTHER`, `PRINTER`, `SHREDDER`, `STANDING_MAT`, `TABLET`, `TASK_LIGHT`, `WEBCAM`, `WELCOME_PACK`, `WIFI_RANGE_EXTENDER`
- `usb_c_connections` (long, required, nullable) — Number of USB-C connections (laptops, monitors)
- `has_usb_c_video_input` (boolean, required, nullable) — Whether the monitor supports USB-C video input (monitors only)

### ItProductsProductIdGetResponsesContentApplicationJsonSchemaDataVariantsItemsImage

Image of this variant, null when the variant has no image

- `id` (string, required) — Unique identifier of the image
- `url` (string, required) — Public URL of the image

## Examples

**Response**

```json
{
  "data": {
    "id": "8e9a2b4c-1d5f-4c3e-9b7a-2f6d8c1e4a5b",
    "name": "MacBook Pro 16",
    "brand": "Apple",
    "images": [
      {
        "id": "b1c3d5e7-8a9b-4c2d-9e0f-1a2b3c4d5e6f",
        "url": "https://cdn.deel.com/products/mbp16-space-black.png"
      }
    ],
    "category": "LAPTOP",
    "variants": [
      {
        "id": "2f4e7ab1-9d3c-4b1f-9e34-6dfb0d6a12ab",
        "sku": "MBP16-M3P-SPACE-UK",
        "size": "16-inch",
        "image": {
          "id": "b1c3d5e7-8a9b-4c2d-9e0f-1a2b3c4d5e6f",
          "url": "https://cdn.deel.com/products/mbp16-space-black.png"
        },
        "style": "Space Black",
        "public_id": "VAR-2f4e",
        "keyboard_layout": "UK_ENGLISH_QWERTY",
        "operating_system": "MACOS",
        "available_countries": [
          "AD"
        ],
        "allowed_rental_terms": [
          "MONTH_12"
        ],
        "allowed_acquisition_types": [
          "PURCHASE"
        ]
      }
    ],
    "public_id": "PRD-8e9a",
    "description": "16-inch laptop with M3 Pro chip, 32GB memory, and 1TB storage.",
    "available_addons": [
      {
        "id": "5c1a7d3e-8b2f-4a6c-9e1d-3f5b7a8c9d0e",
        "name": "Standard service",
        "type": "SERVICE",
        "is_premium": false
      }
    ],
    "product_hardware_spec": {
      "memory_gb": 32,
      "processor": "M3 Pro",
      "storage_gb": 1024,
      "display_size": "16.0",
      "storage_type": "SSD",
      "has_hdmi_port": true,
      "has_display_port": false,
      "product_category": "LAPTOP",
      "usb_c_connections": 3,
      "has_usb_c_video_input": true
    }
  }
}
```

**SDK Code**

```python
import requests

url = "https://api.letsdeel.com/rest/it/products/8e9a2b4c-1d5f-4c3e-9b7a-2f6d8c1e4a5b"

querystring = {"country":"US"}

headers = {
    "X-Beta": "true",
    "Authorization": "Bearer <token>"
}

response = requests.get(url, headers=headers, params=querystring)

print(response.json())
```

```javascript
const url = 'https://api.letsdeel.com/rest/it/products/8e9a2b4c-1d5f-4c3e-9b7a-2f6d8c1e4a5b?country=US';
const options = {method: 'GET', headers: {'X-Beta': 'true', Authorization: 'Bearer <token>'}};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go
package main

import (
	"fmt"
	"net/http"
	"io"
)

func main() {

	url := "https://api.letsdeel.com/rest/it/products/8e9a2b4c-1d5f-4c3e-9b7a-2f6d8c1e4a5b?country=US"

	req, _ := http.NewRequest("GET", url, nil)

	req.Header.Add("X-Beta", "true")
	req.Header.Add("Authorization", "Bearer <token>")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby
require 'uri'
require 'net/http'

url = URI("https://api.letsdeel.com/rest/it/products/8e9a2b4c-1d5f-4c3e-9b7a-2f6d8c1e4a5b?country=US")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)
request["X-Beta"] = 'true'
request["Authorization"] = 'Bearer <token>'

response = http.request(request)
puts response.read_body
```

```java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.get("https://api.letsdeel.com/rest/it/products/8e9a2b4c-1d5f-4c3e-9b7a-2f6d8c1e4a5b?country=US")
  .header("X-Beta", "true")
  .header("Authorization", "Bearer <token>")
  .asString();
```

```php
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('GET', 'https://api.letsdeel.com/rest/it/products/8e9a2b4c-1d5f-4c3e-9b7a-2f6d8c1e4a5b?country=US', [
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'X-Beta' => 'true',
  ],
]);

echo $response->getBody();
```

```csharp
using RestSharp;

var client = new RestClient("https://api.letsdeel.com/rest/it/products/8e9a2b4c-1d5f-4c3e-9b7a-2f6d8c1e4a5b?country=US");
var request = new RestRequest(Method.GET);
request.AddHeader("X-Beta", "true");
request.AddHeader("Authorization", "Bearer <token>");
IRestResponse response = client.Execute(request);
```

```swift
import Foundation

let headers = [
  "X-Beta": "true",
  "Authorization": "Bearer <token>"
]

let request = NSMutableURLRequest(url: NSURL(string: "https://api.letsdeel.com/rest/it/products/8e9a2b4c-1d5f-4c3e-9b7a-2f6d8c1e4a5b?country=US")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```