Pular para o conteúdo
ShopentlyLearn

Primeira requisição

Verifique a conexão com sua loja. Crie uma chave de API, obtenha um token e envie sua primeira solicitação, passo a passo.

Primeiros passos

  1. Criar uma chave
  2. Obter um token
  3. Verificar a conexão

Primeiros passos

  1. Criar uma chave de API

    Abra as configurações de API no painel de administração da loja e crie uma chave.

    Guarde a chave em um local seguro. Você não poderá vê-la novamente depois de fechar a janela.

    Criar uma chave de API

    SHOPENTLY_SHOP_URL
    O endereço HTTPS da sua loja, sem /api/v1. Substitua o exemplo pelo seu endereço.
    https://twoj-sklep.example
    SHOPENTLY_API_KEY
    A chave gerada no painel da loja.
    Autenticação

    Os exemplos cURL usam SHOPENTLY_SHOP_URL, SHOPENTLY_API_KEY e SHOPENTLY_ACCESS_TOKEN como variáveis locais de exemplo. Configure-as de forma privada no servidor de integração; nunca publique credenciais reais no código-fonte, em páginas do navegador, capturas de tela ou logs.

  2. Obter · Token

    POST/api/v1/auth/token

    Use sua chave para obter um token. Você o enviará nas próximas solicitações.

    Exemplos

    Exemplo de requisição

    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))
    

    Exemplo de resposta · 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"
      }
    }
    

    Resposta

    data.access_token
    Token para o cabeçalho Authorization: Bearer. Defina SHOPENTLY_ACCESS_TOKEN antes de executar o exemplo separado.
    data.expires_in
    900 segundos, ou seja, 15 minutos a partir da emissão. As requisições não prolongam a validade.
    data.expires_at
    Data e hora de expiração em UTC. As restrições de acesso atuais podem bloquear o token antes.
    data.rate_limits
    Engine ≥ 4.143.0. Cada resposta de token inclui data.rate_limits da política da loja no momento da emissão. Todas as chaves compartilham esses limites; um novo token não os reinicia. Uma mudança de plano pode valer antes de o token expirar.
  3. Verificar a conexão com sua loja

    GET/api/v1/context

    Envie uma solicitação com o token. A resposta mostra os idiomas e mercados disponíveis na sua loja.

    Exemplo de requisição

    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))
    

    Exemplo de resposta · 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"
      }
    }
    

    Resposta

    Use os identificadores de idiomas e mercados retornados nas próximas requisições.

Como reconhecer uma conexão bem-sucedida?

Uma resposta HTTP 200 com os dados da loja confirma que a conexão funciona.

O programa completo obtém um token e lê o contexto em uma única execução. O código adicional valida a configuração e trata o transporte e os erros.

Exemplo completo

Executar o exemplo

Execute o exemplo completo no terminal, em PHP ou em 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))

Erros e recuperação