Listar — Productos
Consulta los datos de «Productos». El resultado depende de los parámetros de esta operación.
GET/api/v1/products
- Autenticación
Bearer- Disponible desde
- STANDARD
- Permisos necesarios
catalog.product:read
Ejemplos de código
Ejemplo de solicitud
cURL
: "${SHOPENTLY_SHOP_URL:?}"
curl --disable --globoff --fail-with-body --silent --show-error \
--proto '=https' --connect-timeout 5 --max-time 30 \
--request GET \
--header "Authorization: Bearer ${SHOPENTLY_ACCESS_TOKEN:?}" \
--url "${SHOPENTLY_SHOP_URL%/}"'/api/v1/products?limit=20'
PHP
<?php
declare(strict_types=1);
$baseUrl = rtrim(getenv('SHOPENTLY_SHOP_URL') ?: '', '/');
$origin = parse_url($baseUrl);
if (!$origin || ($origin['scheme'] ?? '') !== 'https' || empty($origin['host']) ||
isset($origin['user'], $origin['pass']) || isset($origin['user']) || isset($origin['path']) ||
isset($origin['query']) || isset($origin['fragment'])) {
throw new RuntimeException('SHOPENTLY_SHOP_URL must be an HTTPS origin');
}
$credential = getenv('SHOPENTLY_ACCESS_TOKEN') ?: '';
if ($credential === '' || strpbrk($credential, "\r\n") !== false) {
throw new RuntimeException('Invalid credential');
}
$headers = [];
$headers[] = 'Authorization: Bearer ' . $credential;
$responseHeaders = [];
$handle = curl_init($baseUrl . '/api/v1/products?limit=20');
curl_setopt_array($handle, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => $headers,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_PROTOCOLS => CURLPROTO_HTTPS,
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_SSL_VERIFYHOST => 2,
CURLOPT_CONNECTTIMEOUT => 5,
CURLOPT_TIMEOUT => 30,
CURLOPT_HEADERFUNCTION => static function ($handle, string $line) use (&$responseHeaders): int {
if (str_contains($line, ':')) {
[$name, $value] = explode(':', $line, 2);
$responseHeaders[strtolower(trim($name))] = trim($value);
}
return strlen($line);
},
]);
$raw = curl_exec($handle);
$status = curl_getinfo($handle, CURLINFO_RESPONSE_CODE);
$error = curl_error($handle);
curl_close($handle);
if ($raw === false) {
throw new RuntimeException('Transport error: ' . $error);
}
if ($status < 200 || $status >= 300) {
throw new RuntimeException('HTTP ' . $status . '; request_id=' .
($responseHeaders['x-request-id'] ?? '') . '; retry_after=' . ($responseHeaders['retry-after'] ?? ''));
}
$result = $raw === '' ? null : json_decode($raw, true, 512, JSON_THROW_ON_ERROR | JSON_BIGINT_AS_STRING);
echo json_encode($result, JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE), PHP_EOL;
Python
from contextlib import ExitStack
import json
import os
from urllib.parse import urlsplit
import requests # python -m pip install requests
base_url = os.environ["SHOPENTLY_SHOP_URL"].rstrip("/")
origin = urlsplit(base_url)
if origin.scheme != "https" or not origin.hostname or origin.username or origin.password or origin.path or origin.query or origin.fragment:
raise ValueError("SHOPENTLY_SHOP_URL must be an HTTPS origin")
credential = os.environ['SHOPENTLY_ACCESS_TOKEN']
if not credential or "\r" in credential or "\n" in credential:
raise ValueError("Invalid credential")
headers = {}
headers["Authorization"] = 'Bearer' + " " + credential
body = None
if body is not None:
headers["Content-Type"] = "application/json"
with ExitStack() as stack:
session = stack.enter_context(requests.Session())
files = None
if False:
image = stack.enter_context(open(os.environ["SHOPENTLY_IMAGE_FILE"], "rb"))
if os.fstat(image.fileno()).st_size > 5242880:
raise ValueError("Image exceeds 5 MiB")
files = {"file": ("article.png", image, "image/png")}
response = session.request(
'GET', base_url + '/api/v1/products?limit=20', headers=headers,
data=body.encode("utf-8") if body is not None else None, files=files,
timeout=(5, 30), allow_redirects=False,
)
if not 200 <= response.status_code < 300:
raise RuntimeError(f"HTTP {response.status_code}; request_id={response.headers.get('X-Request-ID', '')}; retry_after={response.headers.get('Retry-After', '')}")
if False:
if response.headers.get("Content-Type") != "image/webp" or len(response.content) > 5242880:
raise ValueError("Unexpected image response")
with open(os.environ["SHOPENTLY_OUTPUT_FILE"], "xb") as output:
output.write(response.content)
else:
result = response.json() if response.content else None
print(json.dumps(result, ensure_ascii=False, indent=2))
Ejemplo de respuesta 200
{
"data": [
{
"availability": {
"available_from": null,
"available_until": null,
"is_available": true
},
"brand_id": null,
"condition": "new",
"created_at": "2026-01-01T12:00:00Z",
"id": "example",
"name": "Example",
"number": "example",
"price": {
"amount": "0.00",
"currency": "PLN",
"minor_units": 2,
"tax_included": true
},
"price_version": 1,
"primary_category_id": "example",
"primary_media_id": "example",
"published": false,
"sku": "example",
"slug": "example",
"tax_category_id": "example",
"updated_at": "2026-01-01T12:00:00Z",
"variants_enabled": false,
"version": 1
}
],
"meta": {
"locale": "en",
"market_code": "PL",
"market_id": "example",
"pagination": {
"has_more": false,
"limit": 20,
"next_cursor": null
},
"request_id": "example"
}
}
Cómo funciona
La integración puede leer productos no eliminados, incluidos los borradores, excepto los bloqueados por un límite del plan. Los productos bloqueados se excluyen de las listas; el acceso directo devuelve entitlements.resource_blocked. Por tanto, la visibilidad en la API difiere de la publicación en la tienda.
Parámetros
Parámetros de consulta
limitNúmero enteroOpcionalNúmero máximo de registros en esta página.
minimum:1maximum:100cursorCadena de texto nullOpcionalValor de continuación opaco devuelto por la página anterior.
Cadena de texto:minLength:1maxLength:1024localeCadena de texto nullOpcionalIdioma seleccionado para esta solicitud.
Cadena de texto:minLength:2maxLength:20market_idCadena de texto nullOpcionalIdentificador del mercado devuelto por el endpoint de contexto.
Restricciones · Cadena de texto 1
pattern"^[a-z0-9][a-z0-9_-]{0,62}$"
market_codeCadena de texto nullOpcionalCódigo del mercado devuelto por el endpoint de contexto.
Cadena de texto:minLength:1maxLength:16skuCadena de texto nullOpcionalCódigo de referencia de inventario.
Cadena de texto:minLength:1maxLength:100Restricciones · Cadena de texto 1
pattern"^\\S+$"
publishedBooleano nullOpcionalIndica si el recurso está publicado.
brand_idCadena de texto nullOpcionalIdentificador de la marca.
Restricciones · Cadena de texto 1
pattern"^[a-z0-9][a-z0-9_-]{0,62}$"
category_idCadena de texto nullOpcionalIdentificador de la categoría.
Restricciones · Cadena de texto 1
pattern"^[a-z0-9][a-z0-9_-]{0,62}$"
Esta operación no acepta un cuerpo JSON.
Respuestas
Respuesta 200
Modelo completo: ApiResponse_list_ProductSummaryData__
dataLista <ProductSummaryData> ObligatorioContenido de una respuesta correcta.
Campos ·
dataModelo completo:
ProductSummaryDataavailabilityAvailabilityDataObligatorioInformación de disponibilidad en el contexto seleccionado.
brand_idCadena de texto nullObligatorioIdentificador de la marca.
conditionCadena de textoObligatorioEstado del producto.
Restricciones
enum["new", "refurbished", "used", "returned", "display", "damaged"]
created_atCadena de textoObligatorioMomento de creación.
format:"date-time"idCadena de textoObligatorioIdentificador del recurso; consérvalo tal como se devuelve.
nameCadena de texto nullObligatorioNombre del recurso en el contexto correspondiente.
numberCadena de textoObligatorioNúmero de pedido o solicitud mostrado al usuario.
pricePriceDatanullObligatorioInformación del precio en el contexto seleccionado.
price_versionNúmero enteroObligatorioVersión actual del precio para controlar cambios simultáneos.
primary_category_idCadena de texto nullObligatorioIdentificador de la categoría principal.
primary_media_idCadena de texto nullObligatorioIdentificador del archivo multimedia principal.
publishedBooleanoObligatorioIndica si el recurso está publicado.
skuCadena de textoObligatorioCódigo de referencia de inventario.
slugCadena de texto nullObligatorioSegmento de la ruta URL en el idioma seleccionado.
tax_category_idCadena de textoObligatorioIdentificador de la categoría fiscal.
updated_atCadena de textoObligatorioMomento de la última actualización.
format:"date-time"variants_enabledBooleanoObligatorioIndica si el producto utiliza variantes.
versionNúmero enteroObligatorioVersión del recurso utilizada para controlar cambios simultáneos.
metaContextPageMetaContextMetaPageMetaRequestMetaObligatorioMetadatos de la respuesta.
Campos ·
metaModelo completo:
ContextPageMetalocaleCadena de textoObligatorioIdioma seleccionado para esta solicitud.
market_codeCadena de textoObligatorioCódigo del mercado devuelto por el endpoint de contexto.
market_idCadena de textoObligatorioIdentificador del mercado devuelto por el endpoint de contexto.
paginationPaginationObligatorioMetadatos de la paginación por cursor.
request_idCadena de textoObligatorioIdentificador de la solicitud; en los metadatos de respuesta identifica la solicitud HTTP.
minLength:1maxLength:100
localeCadena de textoObligatorioIdioma seleccionado para esta solicitud.
market_codeCadena de textoObligatorioCódigo del mercado devuelto por el endpoint de contexto.
market_idCadena de textoObligatorioIdentificador del mercado devuelto por el endpoint de contexto.
request_idCadena de textoObligatorioIdentificador de la solicitud; en los metadatos de respuesta identifica la solicitud HTTP.
minLength:1maxLength:100
paginationPaginationObligatorioMetadatos de la paginación por cursor.
request_idCadena de textoObligatorioIdentificador de la solicitud; en los metadatos de respuesta identifica la solicitud HTTP.
minLength:1maxLength:100
request_idCadena de textoObligatorioIdentificador de la solicitud; en los metadatos de respuesta identifica la solicitud HTTP.
minLength:1maxLength:100
Estado HTTP
200- Respuesta correcta Esquema
400- Solicitud no válida
401- Autenticación necesaria
403- Permiso denegado
404- Recurso no encontrado
409- Conflicto de versión
422- Error de validación
429- Límite de solicitudes excedido
Otros estados HTTP (7)
405- Método no permitido
413- Solicitud demasiado grande
415- Formato no compatible
500- Error del servidor
502- Error de la pasarela API
503- Servicio no disponible
504- Tiempo de espera agotado
Catálogo de errores: ErrorResponse
Cabeceras
401
WWW-AuthenticateCadena de textoOpcionalEsquema de autenticación exigido por el servidor.
405
AllowCadena de textoOpcionalMétodos HTTP admitidos por este recurso.
429, 503
Retry-AfterNúmero enteroOpcionalEspera mínima antes de reintentar, en segundos.
minimum:0