Esivaatimukset ja turvallisuus
Käytä eristettyä sandbox-avainta, jolla on catalog:read-oikeus, sekä bash-, curl- ja jq-ohjelmia. Erä hyväksyy 1–100 syötettä. Yhdistä tunnettu tuote ja tarkoituksella puuttuva kanoninen tunniste, ja lue molempien tarjoustulokset. Tuotantoerät kuluttavat yhden vertailukrediitin syötettä kohden, myös ilman osumaa.
Suorita eristetty harjoitus
- 1Hae tuotetunnisteet
- 2Yhdistä tunnettu ja puuttuva tunniste
- 3Säilytä osittaiset tulokset ja puuttuva näyttö
Suorita omalta palvelimeltasi
set -euo pipefail
# Requires bash, curl and jq. Use an isolated sandbox API key.
DOCS_BASE_URL="${DOCS_BASE_URL:-https://hintadata.fi}"
: "${HINTADATA_API_KEY:?Set a sandbox API key privately}"
DOCS_VARIABLES=$(jq -cn '{}')
DOCS_RESPONSE_FILE=$(mktemp)
trap 'rm -f -- "$DOCS_RESPONSE_FILE"' EXIT
# search: expected HTTP 200
DOCS_PATH="$(jq -cnr --argjson vars "$DOCS_VARIABLES" '"/v1/search?q=sony&limit=2"')"
DOCS_STATUS=$(curl --silent --show-error --max-time 20 --output "$DOCS_RESPONSE_FILE" --write-out '%{http_code}' -X 'GET' "$DOCS_BASE_URL$DOCS_PATH" -H "Authorization: Bearer $HINTADATA_API_KEY")
[[ "$DOCS_STATUS" == '200' ]] || { printf '%s\n' 'Unexpected HTTP status at search' >&2; exit 1; }
DOCS_RESPONSE=$(jq -c . "$DOCS_RESPONSE_FILE")
jq -en --argjson vars "$DOCS_VARIABLES" --argjson response "$DOCS_RESPONSE" --argjson status "$DOCS_STATUS" '((($response | if type == "object" or type == "array" then has("query") else false end))) and ($response["query"] == ("sony"))' >/dev/null
jq -en --argjson vars "$DOCS_VARIABLES" --argjson response "$DOCS_RESPONSE" --argjson status "$DOCS_STATUS" '((($response | if type == "object" or type == "array" then has("items") else false end) and ($response["items"] | if type == "object" or type == "array" then has(0) else false end) and ($response["items"][0] | if type == "object" or type == "array" then has("canonical_product_id") else false end)) == true)' >/dev/null
DOCS_VARIABLES=$(jq -cn --argjson vars "$DOCS_VARIABLES" --argjson response "$DOCS_RESPONSE" '$vars + {"productId":$response["items"][0]["canonical_product_id"],"secondId":$response["items"][1]["canonical_product_id"]}')
printf '%s\n' 'search: verified'
# resolve: expected HTTP 200
jq -e 'has("productId")' <<< "$DOCS_VARIABLES" >/dev/null
DOCS_PATH="$(jq -cnr --argjson vars "$DOCS_VARIABLES" '"/v1/products/resolve"')"
DOCS_STATUS=$(curl --silent --show-error --max-time 20 --output "$DOCS_RESPONSE_FILE" --write-out '%{http_code}' -X 'POST' "$DOCS_BASE_URL$DOCS_PATH" -H "Authorization: Bearer $HINTADATA_API_KEY" -H 'Content-Type: application/json' --data "$(jq -cnr --argjson vars "$DOCS_VARIABLES" '{"items":[{"canonical_product_id":$vars["productId"]},{"canonical_product_id":"docs-missing-product"}]}')")
[[ "$DOCS_STATUS" == '200' ]] || { printf '%s\n' 'Unexpected HTTP status at resolve' >&2; exit 1; }
DOCS_RESPONSE=$(jq -c . "$DOCS_RESPONSE_FILE")
jq -en --argjson vars "$DOCS_VARIABLES" --argjson response "$DOCS_RESPONSE" --argjson status "$DOCS_STATUS" '((($response | if type == "object" or type == "array" then has("items") else false end) and ($response["items"] | if type == "object" or type == "array" then has(0) else false end) and ($response["items"][0] | if type == "object" or type == "array" then has("status") else false end))) and ($response["items"][0]["status"] == ("matched"))' >/dev/null
jq -en --argjson vars "$DOCS_VARIABLES" --argjson response "$DOCS_RESPONSE" --argjson status "$DOCS_STATUS" '((($response | if type == "object" or type == "array" then has("items") else false end) and ($response["items"] | if type == "object" or type == "array" then has(0) else false end) and ($response["items"][0] | if type == "object" or type == "array" then has("candidates") else false end) and ($response["items"][0]["candidates"] | if type == "object" or type == "array" then has(0) else false end))) and ($response["items"][0]["candidates"][0] == ($vars["productId"]))' >/dev/null
jq -en --argjson vars "$DOCS_VARIABLES" --argjson response "$DOCS_RESPONSE" --argjson status "$DOCS_STATUS" '((($response | if type == "object" or type == "array" then has("items") else false end) and ($response["items"] | if type == "object" or type == "array" then has(1) else false end) and ($response["items"][1] | if type == "object" or type == "array" then has("status") else false end))) and ($response["items"][1]["status"] == ("unmatched"))' >/dev/null
jq -en --argjson vars "$DOCS_VARIABLES" --argjson response "$DOCS_RESPONSE" --argjson status "$DOCS_STATUS" '((($response | if type == "object" or type == "array" then has("items") else false end) and ($response["items"] | if type == "object" or type == "array" then has(1) else false end) and ($response["items"][1] | if type == "object" or type == "array" then has("candidates") else false end))) and ($response["items"][1]["candidates"] == ([]))' >/dev/null
printf '%s\n' 'resolve: verified'
# offers: expected HTTP 200
jq -e 'has("productId")' <<< "$DOCS_VARIABLES" >/dev/null
DOCS_PATH="$(jq -cnr --argjson vars "$DOCS_VARIABLES" '"/v1/offers/batch"')"
DOCS_STATUS=$(curl --silent --show-error --max-time 20 --output "$DOCS_RESPONSE_FILE" --write-out '%{http_code}' -X 'POST' "$DOCS_BASE_URL$DOCS_PATH" -H "Authorization: Bearer $HINTADATA_API_KEY" -H 'Content-Type: application/json' --data "$(jq -cnr --argjson vars "$DOCS_VARIABLES" '{"items":[{"canonical_product_id":$vars["productId"]},{"canonical_product_id":"docs-missing-product"}]}')")
[[ "$DOCS_STATUS" == '200' ]] || { printf '%s\n' 'Unexpected HTTP status at offers' >&2; exit 1; }
DOCS_RESPONSE=$(jq -c . "$DOCS_RESPONSE_FILE")
jq -en --argjson vars "$DOCS_VARIABLES" --argjson response "$DOCS_RESPONSE" --argjson status "$DOCS_STATUS" '((($response | if type == "object" or type == "array" then has("items") else false end) and ($response["items"] | if type == "object" or type == "array" then has(0) else false end) and ($response["items"][0] | if type == "object" or type == "array" then has("status") else false end))) and ($response["items"][0]["status"] == ("matched"))' >/dev/null
jq -en --argjson vars "$DOCS_VARIABLES" --argjson response "$DOCS_RESPONSE" --argjson status "$DOCS_STATUS" '((($response | if type == "object" or type == "array" then has("items") else false end) and ($response["items"] | if type == "object" or type == "array" then has(1) else false end) and ($response["items"][1] | if type == "object" or type == "array" then has("status") else false end))) and ($response["items"][1]["status"] == ("unmatched"))' >/dev/null
jq -en --argjson vars "$DOCS_VARIABLES" --argjson response "$DOCS_RESPONSE" --argjson status "$DOCS_STATUS" '((($response | if type == "object" or type == "array" then has("items") else false end) and ($response["items"] | if type == "object" or type == "array" then has(1) else false end) and ($response["items"][1] | if type == "object" or type == "array" then has("offers") else false end))) and ($response["items"][1]["offers"] == ([]))' >/dev/null
jq -en --argjson vars "$DOCS_VARIABLES" --argjson response "$DOCS_RESPONSE" --argjson status "$DOCS_STATUS" '((($response | if type == "object" or type == "array" then has("items") else false end) and ($response["items"] | if type == "object" or type == "array" then has(1) else false end) and ($response["items"][1] | if type == "object" or type == "array" then has("best_offer") else false end))) and ($response["items"][1]["best_offer"] == (null))' >/dev/null
printf '%s\n' 'offers: verified'Varmista tulos
Molemmat erät palauttavat HTTP 200, mutta vain ensimmäinen rivi yhdistyy. Syötejärjestys säilyy. Puuttuvalla rivillä ei ole ehdokkaita tai tarjouksia ja best_offer on null: kyse on puuttuvasta näytöstä, ei nollahinnasta eikä todisteesta loppuneesta varastosta. Komennot tarkistavat nämä arvot erikseen.
Palautuminen ja siivous
Käsittele jokaisen rivin tila erikseen. Korjaa unmatched-rivin tunniste; tarkista ambiguous-rivin ehdokkaat ja valitse täsmällinen kanoninen tunniste. Virheellinen GTIN tai useita tunnisteita samalla rivillä hylkää pyynnön. Jos saat 503 source_stale -virheen, odota lähteen omistajan päivittävän aineisto; älä muuta virhettä tyhjäksi onnistuneeksi tulokseksi. Nämä vain lukevat POST-kutsut eivät tarvitse Idempotency-Key-otsaketta.
Noudata 429- ja tilapäisissä 5xx-virheissä Retry-After-ohjetta ja rajaa uudelleenyritykset. Älä vie API-avaimia tai vastausrunkoja lokeihin tai tukipyyntöihin.