Aller au contenu
ShopentlyLearn

Promotions · Modifier

Promotions · Modifier. Chaque code doit autoriser le cumul. Les réductions sont appliquées dans l’ordre.

PATCH/api/v1/discounts/promotions/{identity}

Authentification
Bearer
Disponible à partir de
STANDARD
Autorisations requises
discounts.promotions:update

Exemples de code

Exemple de requête

cURL

: "${SHOPENTLY_SHOP_URL:?}"

curl --disable --globoff --fail-with-body --silent --show-error \
  --proto '=https' --connect-timeout 5 --max-time 30 \
  --request PATCH \
  --header "Authorization: Bearer ${SHOPENTLY_ACCESS_TOKEN:?}" \
  --header 'Idempotency-Key: learn-update_campaign_api_v1_discounts_promotions__identity__patch' \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "expected_version": 1,
  "markets": [
    {
      "currency": "PLN",
      "market_id": "poland",
      "minor_units": 2
    }
  ],
  "name": "Autumn guide offer"
}' \
  --url "${SHOPENTLY_SHOP_URL%/}"/api/v1/discounts/promotions/example-campaign

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 = ['Idempotency-Key: learn-update_campaign_api_v1_discounts_promotions__identity__patch', 'Content-Type: application/json'];
$headers[] = 'Authorization: Bearer ' . $credential;
$responseHeaders = [];
$handle = curl_init($baseUrl . '/api/v1/discounts/promotions/example-campaign');
curl_setopt_array($handle, [
    CURLOPT_CUSTOMREQUEST => 'PATCH',
    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);
    },
]);
curl_setopt($handle, CURLOPT_POSTFIELDS, '{
  "expected_version": 1,
  "markets": [
    {
      "currency": "PLN",
      "market_id": "poland",
      "minor_units": 2
    }
  ],
  "name": "Autumn guide offer"
}');
$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 = {'Idempotency-Key': 'learn-update_campaign_api_v1_discounts_promotions__identity__patch'}
headers["Authorization"] = 'Bearer' + " " + credential
body = '{\n  "expected_version": 1,\n  "markets": [\n    {\n      "currency": "PLN",\n      "market_id": "poland",\n      "minor_units": 2\n    }\n  ],\n  "name": "Autumn guide offer"\n}'
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(
        'PATCH', base_url + '/api/v1/discounts/promotions/example-campaign', 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))

Exemple de réponse 200

JSON
{
  "data": {
    "deleted": false,
    "id": "example-campaign",
    "version": null
  },
  "meta": {
    "locale": "example",
    "market_code": "example",
    "market_id": "poland",
    "pagination": {
      "has_more": false,
      "limit": 1,
      "next_cursor": null
    },
    "request_id": "learn-example-request"
  }
}

Vue d’ensemble

Les produits et catégories sélectionnés sont réunis. Les catégories incluent les produits directement associés.

Paramètres

Paramètres de chemin

identityChaîneObligatoire

Identifiant utilisé dans ce chemin de ressource.

Contraintes
pattern
"^[a-z0-9][a-z0-9_-]{0,62}$"
Exemple: "example-campaign"

En-têtes de requête

Idempotency-KeyChaîneObligatoire

Identifiant unique d'une opération logique d'écriture.

minLength: 1maxLength: 128
Contraintes
pattern
"^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$"
Exemple: "learn-update_campaign_api_v1_discounts_promotions__identity__patch"

Corps de la requête

application/json · Obligatoire

CampaignUpdate
audienceChaîneFacultatif

Clients

Contraintes
enum
["all", "guest", "customer", "selected"]
Valeur par défaut: "all"
benefit_typeChaîneFacultatif

Variante de la structure de données définie par les valeurs autorisées.

Contraintes
enum
["percentage", "fixed", "none"]
Valeur par défaut: "percentage"
category_idsTableau <Chaîne> Facultatif

Identifiants des catégories associées.

maxItems: 1000
Contraintes · Tableau 1
pattern
"^[a-z0-9][a-z0-9_-]{0,62}$"
codeChaîne nullFacultatif

Code stable lisible par une machine.

Contraintes · Chaîne 1
pattern
"^[A-Za-z0-9]{6,16}$"
Exemple: "LEARN10"
combine_couponsBooléenFacultatif

Cumuler avec d’autres codes

Valeur par défaut: false
combine_promotionsBooléenFacultatif

Autoriser ce code sur les produits bénéficiant de promotions automatiques

Valeur par défaut: false
customer_idsTableau <Chaîne> Facultatif

Données du client enregistrées pour cette ressource.

maxItems: 1000
Contraintes · Tableau 1
pattern
"^[a-z0-9][a-z0-9_-]{0,62}$"
ends_atChaîne nullFacultatif

Actif jusqu'au

Chaîne:format: "date-time"
expected_versionEntierObligatoire

Version lue avant l'écriture ; une différence entraîne le rejet de la modification.

minimum: 1maximum: 9223372036854775807
Exemple: 1
free_shippingBooléenFacultatif

Livraison gratuite

Valeur par défaut: false
marketsTableau <MarketData-Input > Obligatoire

Marchés disponibles dans le contexte de la boutique.

minItems: 1maxItems: 1000
Exemple: [{"currency":"PLN","market_id":"poland","minor_units":2}]
minimum_quantityEntierFacultatif

Nombre minimum d'articles dans le panier

minimum: 1maximum: 2147483647
Valeur par défaut: 1
nameChaîneObligatoire

Nom de la ressource dans le contexte concerné.

minLength: 1maxLength: 160
Exemple: "Autumn guide offer"
per_customer_limitEntierFacultatif

Limite d'utilisations par client

minimum: -1maximum: 2147483647
Valeur par défaut: -1
percentageChaîneFacultatif

Pourcentage

maxLength: 19
Contraintes
pattern
"^(0|[1-9][0-9]{0,13})(\\.[0-9]{1,4})?$"
Valeur par défaut: "10"
product_idsTableau <Chaîne> Facultatif

Identifiants des produits associés.

maxItems: 1000
Contraintes · Tableau 1
pattern
"^[a-z0-9][a-z0-9_-]{0,62}$"
product_scopeChaîneFacultatif

Produits

Contraintes
enum
["all", "selected"]
Valeur par défaut: "all"
show_accountBooléenFacultatif

Dans le compte client

Valeur par défaut: false
show_cartBooléenFacultatif

Dans le panier

Valeur par défaut: false
show_productBooléenFacultatif

Sur les pages produit

Valeur par défaut: false
starts_atChaîne nullFacultatif

Actif à partir du

Chaîne:format: "date-time"
usage_limitEntierFacultatif

Limite d'utilisations

minimum: -1maximum: 2147483647
Valeur par défaut: -1

Réponses

Réponse 200

dataMutationData Obligatoire

Données d'une réponse réussie.

Champs · data
deletedBooléenObligatoire

Indique si la suppression a été appliquée.

idChaîneObligatoire

Identifiant de ressource ; conserver la valeur renvoyée.

versionEntier nullObligatoire

Version de ressource utilisée pour le contrôle de concurrence.

metaContextPageMeta ContextMeta PageMeta RequestMeta Obligatoire

Métadonnées de la réponse.

Champs · meta

ContextPageMeta

localeChaîneObligatoire

Langue sélectionnée pour cette requête.

market_codeChaîneObligatoire

Code de marché renvoyé par le point d'accès au contexte.

market_idChaîneObligatoire

Identifiant de marché renvoyé par le point d'accès au contexte.

paginationPagination Obligatoire

Métadonnées de pagination par curseur.

request_idChaîneObligatoire

Identifiant de demande ; dans les métadonnées, identifiant de la requête HTTP.

minLength: 1maxLength: 100

ContextMeta

localeChaîneObligatoire

Langue sélectionnée pour cette requête.

market_codeChaîneObligatoire

Code de marché renvoyé par le point d'accès au contexte.

market_idChaîneObligatoire

Identifiant de marché renvoyé par le point d'accès au contexte.

request_idChaîneObligatoire

Identifiant de demande ; dans les métadonnées, identifiant de la requête HTTP.

minLength: 1maxLength: 100

PageMeta

paginationPagination Obligatoire

Métadonnées de pagination par curseur.

request_idChaîneObligatoire

Identifiant de demande ; dans les métadonnées, identifiant de la requête HTTP.

minLength: 1maxLength: 100

RequestMeta

request_idChaîneObligatoire

Identifiant de demande ; dans les métadonnées, identifiant de la requête HTTP.

minLength: 1maxLength: 100
Exemple de réponse

Statut HTTP

200
Réponse réussie Schéma
400
Requête invalide
401
Authentification requise
403
Accès refusé
404
Ressource introuvable
409
Conflit de version
422
Échec de validation
429
Limite de requêtes dépassée
Autres statuts HTTP (7)
405
Méthode non autorisée
413
Requête trop volumineuse
415
Format non pris en charge
500
Erreur du serveur
502
Erreur de passerelle API
503
Service indisponible
504
Délai de passerelle dépassé

Catalogue des erreurs: ErrorResponse

En-têtes

401

WWW-AuthenticateChaîneFacultatif

Schéma d'authentification exigé par le serveur.

405

AllowChaîneFacultatif

Méthodes HTTP prises en charge par cette ressource.

429, 503

Retry-AfterEntierFacultatif

Délai minimal avant une nouvelle tentative, en secondes.

minimum: 0