Aller au contenu
ShopentlyLearn

Première requête

Vérifiez la connexion à votre boutique. Créez une clé API, obtenez un jeton et envoyez votre première requête, étape par étape.

Premiers pas

  1. Créer une clé
  2. Obtenir un jeton
  3. Vérifier la connexion

Premiers pas

  1. Créer une clé API

    Ouvrez les paramètres API dans l’administration de votre boutique et créez une clé.

    Conservez la clé en lieu sûr. Vous ne pourrez plus l’afficher après avoir fermé la fenêtre.

    Créer une clé API

    SHOPENTLY_SHOP_URL
    L’adresse HTTPS de votre boutique, sans /api/v1. Remplacez l’exemple par votre propre adresse.
    https://twoj-sklep.example
    SHOPENTLY_API_KEY
    La clé générée dans l’administration de la boutique.
    Authentification

    Les exemples cURL utilisent SHOPENTLY_SHOP_URL, SHOPENTLY_API_KEY et SHOPENTLY_ACCESS_TOKEN comme variables locales. Définissez-les de manière privée sur le serveur d'intégration. Ne publiez jamais de véritables identifiants dans le code, une page web, des captures d'écran ou des journaux.

  2. Obtenir · Jeton

    POST/api/v1/auth/token

    Utilisez votre clé pour obtenir un jeton. Vous l’enverrez avec vos prochaines requêtes.

    Exemples

    Exemple de requête

    cURL

    : "${SHOPENTLY_SHOP_URL:?}"
    
    response=$(curl --disable --globoff --fail-with-body --silent --show-error \
      --proto '=https' --connect-timeout 5 --max-time 30 \
      --write-out '\n%{http_code}' \
      --request POST \
      --header "Authorization: ApiKey ${SHOPENTLY_API_KEY:?}" \
      --header 'Content-Type: application/json' \
      --data-raw '{}' \
      --url "${SHOPENTLY_SHOP_URL%/}"/api/v1/auth/token) || exit 1
    status=$(printf '%s' "$response" | tail -n 1)
    case "$status" in
      2??) printf '%s\n' "$response" | sed '$d' ;;
      *) printf 'HTTP %s\n' "$status" >&2; exit 1 ;;
    esac
    

    PHP

    <?php
    $base = rtrim(getenv('SHOPENTLY_SHOP_URL') ?: '', '/');
    $origin = parse_url($base);
    if (!$origin || ($origin['scheme'] ?? '') !== 'https' || empty($origin['host']) ||
        array_intersect(['user', 'pass', 'path', 'query', 'fragment'], array_keys($origin))) {
        throw new RuntimeException('SHOPENTLY_SHOP_URL must be an HTTPS origin');
    }
    $credential = getenv('SHOPENTLY_API_KEY') ?: '';
    if ($credential === '' || preg_match('/\s/', $credential)) {
        throw new RuntimeException('Invalid credential');
    }
    
    $curl = curl_init($base . '/api/v1/auth/token');
    curl_setopt_array($curl, [
        CURLOPT_CUSTOMREQUEST => 'POST',
        CURLOPT_HTTPHEADER => ['Authorization: ApiKey ' . $credential, 'Content-Type: application/json'],
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_FOLLOWLOCATION => false,
        CURLOPT_PROTOCOLS => CURLPROTO_HTTPS,
        CURLOPT_CONNECTTIMEOUT => 5,
        CURLOPT_TIMEOUT => 30,
        CURLOPT_POSTFIELDS => '{}',
    ]);
    $raw = curl_exec($curl);
    $status = curl_getinfo($curl, CURLINFO_RESPONSE_CODE);
    curl_close($curl);
    if ($raw === false || $status < 200 || $status >= 300) {
        throw new RuntimeException('Request failed; HTTP ' . $status);
    }
    $result = json_decode($raw, true, 512, JSON_THROW_ON_ERROR | JSON_BIGINT_AS_STRING);
    echo json_encode($result, JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT), PHP_EOL;
    

    Python

    import json
    import os
    from urllib.parse import urlsplit
    import requests
    
    base = os.environ["SHOPENTLY_SHOP_URL"].rstrip("/")
    origin = urlsplit(base)
    if (origin.scheme != "https" or not origin.hostname or origin.username is not None
            or origin.path or origin.query or origin.fragment):
        raise ValueError("SHOPENTLY_SHOP_URL must be an HTTPS origin")
    credential = os.environ["SHOPENTLY_API_KEY"]
    if not credential or any(c.isspace() for c in credential):
        raise ValueError("Invalid credential")
    
    response = requests.request(
        "POST", base + "/api/v1/auth/token",
        headers={"Authorization": "ApiKey " + credential},
        timeout=(5, 30), allow_redirects=False, json={},
    )
    if not 200 <= response.status_code < 300:
        raise RuntimeError(f"HTTP {response.status_code}")
    result = response.json()
    print(json.dumps(result, ensure_ascii=False, indent=2))
    

    Exemple de réponse · HTTP 200

    JSON
    {
      "data": {
        "access_token": "EXAMPLE_ACCESS_TOKEN",
        "expires_at": "2026-01-01T12:00:00Z",
        "expires_in": 900,
        "rate_limits": {
          "auth_per_minute": 10,
          "read_per_minute": 60,
          "write_per_minute": 10
        },
        "token_type": "Bearer"
      },
      "meta": {
        "request_id": "example"
      }
    }
    

    Réponse

    data.access_token
    Jeton de l’en-tête Authorization: Bearer. Définissez SHOPENTLY_ACCESS_TOKEN avant d’exécuter l’exemple séparé.
    data.expires_in
    900 secondes, soit 15 minutes après son émission. Les requêtes ne prolongent pas sa validité.
    data.expires_at
    Date et heure d’expiration en UTC. Les restrictions d’accès en vigueur peuvent bloquer le jeton plus tôt.
    data.rate_limits
    Engine ≥ 4.143.0. Chaque réponse de jeton contient data.rate_limits issu de la politique de la boutique au moment de son émission. Toutes les clés partagent ces quotas ; un nouveau jeton ne les réinitialise pas. Un changement d’offre peut s’appliquer avant l’expiration du jeton.
  3. Vérifier la connexion à votre boutique

    GET/api/v1/context

    Envoyez une requête avec le jeton. La réponse indique les langues et les marchés disponibles dans votre boutique.

    Exemple de requête

    cURL

    : "${SHOPENTLY_SHOP_URL:?}"
    
    response=$(curl --disable --globoff --fail-with-body --silent --show-error \
      --proto '=https' --connect-timeout 5 --max-time 30 \
      --write-out '\n%{http_code}' \
      --request GET \
      --header "Authorization: Bearer ${SHOPENTLY_ACCESS_TOKEN:?}" \
      --url "${SHOPENTLY_SHOP_URL%/}"/api/v1/context) || exit 1
    status=$(printf '%s' "$response" | tail -n 1)
    case "$status" in
      2??) printf '%s\n' "$response" | sed '$d' ;;
      *) printf 'HTTP %s\n' "$status" >&2; exit 1 ;;
    esac
    

    PHP

    <?php
    $base = rtrim(getenv('SHOPENTLY_SHOP_URL') ?: '', '/');
    $origin = parse_url($base);
    if (!$origin || ($origin['scheme'] ?? '') !== 'https' || empty($origin['host']) ||
        array_intersect(['user', 'pass', 'path', 'query', 'fragment'], array_keys($origin))) {
        throw new RuntimeException('SHOPENTLY_SHOP_URL must be an HTTPS origin');
    }
    $credential = getenv('SHOPENTLY_ACCESS_TOKEN') ?: '';
    if ($credential === '' || preg_match('/\s/', $credential)) {
        throw new RuntimeException('Invalid credential');
    }
    
    $curl = curl_init($base . '/api/v1/context');
    curl_setopt_array($curl, [
        CURLOPT_CUSTOMREQUEST => 'GET',
        CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $credential],
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_FOLLOWLOCATION => false,
        CURLOPT_PROTOCOLS => CURLPROTO_HTTPS,
        CURLOPT_CONNECTTIMEOUT => 5,
        CURLOPT_TIMEOUT => 30,
    ]);
    $raw = curl_exec($curl);
    $status = curl_getinfo($curl, CURLINFO_RESPONSE_CODE);
    curl_close($curl);
    if ($raw === false || $status < 200 || $status >= 300) {
        throw new RuntimeException('Request failed; HTTP ' . $status);
    }
    $result = json_decode($raw, true, 512, JSON_THROW_ON_ERROR | JSON_BIGINT_AS_STRING);
    echo json_encode($result, JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT), PHP_EOL;
    

    Python

    import json
    import os
    from urllib.parse import urlsplit
    import requests
    
    base = os.environ["SHOPENTLY_SHOP_URL"].rstrip("/")
    origin = urlsplit(base)
    if (origin.scheme != "https" or not origin.hostname or origin.username is not None
            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 any(c.isspace() for c in credential):
        raise ValueError("Invalid credential")
    
    response = requests.request(
        "GET", base + "/api/v1/context",
        headers={"Authorization": "Bearer " + credential},
        timeout=(5, 30), allow_redirects=False,
    )
    if not 200 <= response.status_code < 300:
        raise RuntimeError(f"HTTP {response.status_code}")
    result = response.json()
    print(json.dumps(result, ensure_ascii=False, indent=2))
    

    Exemple de réponse · HTTP 200

    JSON
    {
      "data": {
        "base_market_id": "example",
        "default_locale": "en",
        "global_enabled": false,
        "languages": [
          {
            "code": "en",
            "direction": "ltr",
            "is_default": true,
            "name": "English",
            "native_name": "English",
            "status": "draft"
          }
        ],
        "markets": [
          {
            "code": "PL",
            "currency": {
              "code": "PLN",
              "minor_units": 2
            },
            "id": "example",
            "is_default": true,
            "name": "Poland",
            "price_list": null,
            "status": "draft"
          }
        ],
        "multilingual_enabled": false
      },
      "meta": {
        "locale": "en",
        "market_code": "PL",
        "market_id": "example",
        "request_id": "example"
      }
    }
    

    Réponse

    Utilisez les identifiants de langues et de marchés renvoyés dans les requêtes suivantes.

Comment reconnaître une connexion réussie ?

Une réponse HTTP 200 contenant les données de votre boutique confirme que la connexion fonctionne.

Le programme complet obtient un jeton et lit le contexte en une seule exécution. Le code supplémentaire vérifie la configuration et gère le transport et les erreurs.

Exemple complet

Exécuter l’exemple

Exécutez l’exemple complet dans votre terminal, en PHP ou en Python.

PHP 8.3 (64-bit, ext-curl, JSON) · Python 3.12 + requests · cURL 8 + jq 1.7.

cURL

#!/bin/sh
# POSIX shell, curl 8+, jq 1.7. Credentials stay in environment variables.
set -eu
: "${SHOPENTLY_SHOP_URL:?}"
base=${SHOPENTLY_SHOP_URL%/}
case "$base" in https://*) ;; *) echo 'Use an HTTPS origin' >&2; exit 1;; esac
authority=${base#https://}
case "$authority" in ''|*/*|*\?*|*\#*|*@*) echo 'Use an HTTPS origin' >&2; exit 1;; esac
work=$(mktemp -d)
trap 'rm -rf "$work"' EXIT HUP INT TERM
chmod 700 "$work"
encode() { printf '%s' "$1" | jq -sRr @uri; }
api() {
    method=$1; path=$2; body=${3-}; key=${4-}
    scheme=Bearer; credential=${SHOPENTLY_ACCESS_TOKEN-}
    if [ "$path" = /api/v1/auth/token ]; then scheme=ApiKey; credential=${SHOPENTLY_API_KEY-}; fi
    [ -n "$credential" ] || { echo 'Missing credential' >&2; return 1; }
    set -- --disable --globoff --silent --show-error --proto '=https' --connect-timeout 5 --max-time 30 \
        --request "$method" --header "Authorization: $scheme $credential" \
        --dump-header "$work/headers" --output "$work/body" --write-out '%{http_code}'
    if [ -n "$key" ]; then set -- "$@" --header "Idempotency-Key: $key"; fi
    if [ -n "$body" ]; then set -- "$@" --header 'Content-Type: application/json' --data-raw "$body"; fi
    status=$(curl "$@" --url "$base$path") || return 1
    case "$status" in
        2??) if [ -s "$work/body" ]; then jq -e . "$work/body"; else printf 'null\n'; fi ;;
        *) printf 'HTTP %s\n' "$status" >&2
           jq -c '.error | {code, fields}' "$work/body" >&2 2>/dev/null || true
           return 1 ;;
    esac
}

token=$(api POST /api/v1/auth/token '{}')
SHOPENTLY_ACCESS_TOKEN=$(printf '%s' "$token" | jq -er '.data.access_token')
export SHOPENTLY_ACCESS_TOKEN
api GET /api/v1/context

PHP

<?php
declare(strict_types=1);
// PHP 8.3+, 64-bit, ext-curl. Credentials stay in environment variables.
function env(string $name): string {
    $value = getenv($name);
    if ($value === false || $value === '' || strpbrk($value, "\r\n") !== false) {
        throw new RuntimeException('Invalid environment variable: ' . $name);
    }
    return $value;
}
$base = rtrim(env('SHOPENTLY_SHOP_URL'), '/');
$origin = parse_url($base);
if (!$origin || ($origin['scheme'] ?? '') !== 'https' || empty($origin['host']) ||
    isset($origin['user']) || isset($origin['pass']) || isset($origin['path']) ||
    isset($origin['query']) || isset($origin['fragment']) || PHP_INT_SIZE !== 8) {
    throw new RuntimeException('Use a 64-bit PHP runtime and an HTTPS origin');
}
class ApiError extends RuntimeException {
    public function __construct(public int $status, public array $headers, public array $error) {
        parent::__construct('HTTP ' . $status . '; code=' . ($error['code'] ?? '') .
            '; request_id=' . ($headers['x-request-id'] ?? ''));
    }
}
function api(string $method, string $path, array $query = [], ?array $body = null, ?string $key = null, bool $apiKey = false): ?array {
    global $base;
    $credential = env($apiKey ? 'SHOPENTLY_API_KEY' : 'SHOPENTLY_ACCESS_TOKEN');
    $headers = ['Authorization: ' . ($apiKey ? 'ApiKey ' : 'Bearer ') . $credential];
    if ($key !== null) $headers[] = 'Idempotency-Key: ' . $key;
    if ($body !== null) $headers[] = 'Content-Type: application/json';
    $url = $base . $path . ($query ? '?' . http_build_query($query, '', '&', PHP_QUERY_RFC3986) : '');
    $responseHeaders = [];
    $h = curl_init($url);
    curl_setopt_array($h, [
        CURLOPT_CUSTOMREQUEST => $method, 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 ($h, string $line) use (&$responseHeaders): int {
            if (str_contains($line, ':')) {
                [$name, $value] = explode(':', $line, 2);
                $responseHeaders[strtolower(trim($name))] = trim($value);
            }
            return strlen($line);
        },
    ]);
    if ($body !== null) {
        $json = $apiKey && $body === [] ? '{}' : json_encode($body, JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE);
        curl_setopt($h, CURLOPT_POSTFIELDS, $json);
    }
    $raw = curl_exec($h);
    $status = curl_getinfo($h, CURLINFO_RESPONSE_CODE);
    $error = curl_error($h);
    curl_close($h);
    if ($raw === false) throw new RuntimeException('Transport error: ' . $error);
    if ($status < 200 || $status >= 300) {
        $data = json_decode($raw, true);
        throw new ApiError($status, $responseHeaders, is_array($data) ? ($data['error'] ?? []) : []);
    }
    return $raw === '' ? null : json_decode($raw, true, 512, JSON_THROW_ON_ERROR | JSON_BIGINT_AS_STRING);
}
function output(mixed $value): void {
    echo json_encode($value, JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE), PHP_EOL;
}
$token = api('POST', '/api/v1/auth/token', body: [], apiKey: true)['data'];
putenv('SHOPENTLY_ACCESS_TOKEN=' . $token['access_token']);
output(api('GET', '/api/v1/context'));

Python

"""Run with Python 3.12 and requests. Credentials stay in environment variables."""
import json
import os
import random
import time
from urllib.parse import quote, urlencode, urlsplit
import requests

def env(name):
    value = os.environ[name]
    if not value or "\r" in value or "\n" in value:
        raise ValueError("Invalid environment variable: " + name)
    return value

base = env("SHOPENTLY_SHOP_URL").rstrip("/")
origin = urlsplit(base)
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")

class ApiError(RuntimeError):
    def __init__(self, response):
        self.status = response.status_code
        self.request_id = response.headers.get("X-Request-ID", "")
        self.retry_after = response.headers.get("Retry-After", "")
        try:
            self.error = response.json().get("error", {})
        except (ValueError, AttributeError):
            self.error = {}
        super().__init__(f"HTTP {self.status}; code={self.error.get('code', '')}; request_id={self.request_id}")

def api(method, path, *, query=None, body=None, key=None, api_key=False):
    credential = env("SHOPENTLY_API_KEY" if api_key else "SHOPENTLY_ACCESS_TOKEN")
    headers = {"Authorization": ("ApiKey " if api_key else "Bearer ") + credential}
    if key:
        headers["Idempotency-Key"] = key
    if body is not None:
        headers["Content-Type"] = "application/json"
    response = requests.request(method, base + path, params=query, headers=headers,
        data=json.dumps(body, ensure_ascii=False, allow_nan=False).encode() if body is not None else None,
        timeout=(5, 30), allow_redirects=False)
    if not 200 <= response.status_code < 300:
        raise ApiError(response)
    return response.json() if response.content else None

def segment(value):
    return quote(value, safe="")

token = api("POST", "/api/v1/auth/token", body={}, api_key=True)["data"]
os.environ["SHOPENTLY_ACCESS_TOKEN"] = token["access_token"]
print(json.dumps(api("GET", "/api/v1/context"), ensure_ascii=False, indent=2))

Erreurs et reprise