Skip to content

Guides

Link a new SKU

You've added a product to your ERP, and GetPrice already collects it from your online shop. Its shop page shows no stock code, so GetPrice couldn't pre-load the link. Link your ERP's SKU to it in three steps.

Find the product#

Search your products by part of the name, case-insensitively. unmapped=true leaves out products that already have a SKU link.

BASE=https://api.getprice.ai/v1
curl -G "$BASE/products" \
  -H "Authorization: Bearer $GETPRICE_API_KEY" \
  --data-urlencode "q=pilchards" \
  --data-urlencode "unmapped=true"
import os

import requests

BASE = "https://api.getprice.ai/v1"
KEY = os.environ["GETPRICE_API_KEY"]

resp = requests.get(
    f"{BASE}/products",
    params={"q": "pilchards", "unmapped": "true"},
    headers={"Authorization": f"Bearer {KEY}"},
    timeout=30,
)
resp.raise_for_status()
for product in resp.json()["data"]:
    print(product["id"], product["name"])
interface Product {
  id: string;
  name: string;
}

const BASE = "https://api.getprice.ai/v1";
const KEY = process.env.GETPRICE_API_KEY;
const params = new URLSearchParams({
  q: "pilchards",
  unmapped: "true",
});
const url = `${BASE}/products?${params}`;
const res = await fetch(url, {
  headers: { Authorization: `Bearer ${KEY}` },
});
if (!res.ok) {
  throw new Error(`GetPrice returned ${res.status}`);
}
const page = (await res.json()) as {
  data: Product[];
};
for (const product of page.data) {
  console.log(product.id, product.name);
}
<?php
$base = "https://api.getprice.ai/v1";
$key = getenv("GETPRICE_API_KEY");
$query = http_build_query([
    "q" => "pilchards",
    "unmapped" => "true",
]);
$ch = curl_init("$base/products?$query");
curl_setopt_array($ch, [
    CURLOPT_HTTPHEADER => [
        "Authorization: Bearer $key",
    ],
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($body === false || $status >= 400) {
    throw new RuntimeException(
        "GetPrice returned $status: $body"
    );
}
$data = json_decode(
    $body, true, flags: JSON_THROW_ON_ERROR
);
foreach ($data["data"] as $product) {
    echo $product["id"], " ", $product["name"], "\n";
}
using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Text.Json;
using Naming = System.Text.Json.JsonNamingPolicy;

var key = Environment.GetEnvironmentVariable(
    "GETPRICE_API_KEY");
var api = new Uri("https://api.getprice.ai/v1/");
var http = new HttpClient { BaseAddress = api };
http.Timeout = TimeSpan.FromSeconds(30);
http.DefaultRequestHeaders.Authorization =
    new AuthenticationHeaderValue("Bearer", key);
var json = new JsonSerializerOptions
{
    PropertyNamingPolicy = Naming.SnakeCaseLower,
};

var res = await http.GetAsync(
    "products?q=pilchards&unmapped=true");
res.EnsureSuccessStatusCode();
var page = await res.Content
    .ReadFromJsonAsync<Page>(json);
foreach (var p in page!.Data)
    Console.WriteLine($"{p.Id} {p.Name}");

record Page(List<Product> Data);
record Product(string Id, string Name);
Response
{
  "data": [
    {
      "id": "prd_Lp4sT1x9",
      "name": "Pilchards in Tomato Sauce 400g",
      "url": "https://shop.example.com/product/pilchards-in-tomato-sauce-400g",
      "skus": [],
      "comparison_set_id": "set_R4m8wQe2",
      "price": {
        "amount": "31.99",
        "was": "33.99",
        "currency": "ZAR"
      },
      "last_collected_at": "2026-11-02T04:12:31Z",
      "status": "active"
    }
  ],
  "next_cursor": null
}

PUT your SKU with the product's id. If-None-Match: * makes the call create-only, so you never overwrite a link someone else set.

BASE=https://api.getprice.ai/v1
curl -X PUT "$BASE/sku-mappings/13817L" \
  -H "Authorization: Bearer $GETPRICE_API_KEY" \
  -H "Content-Type: application/json" \
  -H "If-None-Match: *" \
  -d '{"product_id": "prd_Lp4sT1x9"}'
import os

import requests

BASE = "https://api.getprice.ai/v1"
KEY = os.environ["GETPRICE_API_KEY"]

resp = requests.put(
    f"{BASE}/sku-mappings/13817L",
    json={"product_id": "prd_Lp4sT1x9"},
    headers={
        "Authorization": f"Bearer {KEY}",
        "If-None-Match": "*",
    },
    timeout=30,
)
if resp.status_code == 412:
    raise SystemExit("13817L is already linked")
resp.raise_for_status()
print(resp.status_code, resp.json())
const BASE = "https://api.getprice.ai/v1";
const KEY = process.env.GETPRICE_API_KEY;
const url = `${BASE}/sku-mappings/13817L`;
const res = await fetch(url, {
  method: "PUT",
  headers: {
    Authorization: `Bearer ${KEY}`,
    "Content-Type": "application/json",
    "If-None-Match": "*",
  },
  body: JSON.stringify({ product_id: "prd_Lp4sT1x9" }),
});
if (res.status === 412) {
  throw new Error("13817L is already linked");
}
if (!res.ok) {
  throw new Error(`GetPrice returned ${res.status}`);
}
console.log(res.status, await res.json());
<?php
$base = "https://api.getprice.ai/v1";
$key = getenv("GETPRICE_API_KEY");
$ch = curl_init("$base/sku-mappings/13817L");
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => "PUT",
    CURLOPT_HTTPHEADER => [
        "Authorization: Bearer $key",
        "Content-Type: application/json",
        "If-None-Match: *",
    ],
    CURLOPT_POSTFIELDS => json_encode([
        "product_id" => "prd_Lp4sT1x9",
    ]),
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status === 412) {
    throw new RuntimeException(
        "13817L is already linked"
    );
}
if ($body === false || $status >= 400) {
    throw new RuntimeException(
        "GetPrice returned $status: $body"
    );
}
echo $status, " ", $body, "\n";
using System.Net;
using System.Net.Http.Headers;
using System.Net.Http.Json;

var key = Environment.GetEnvironmentVariable(
    "GETPRICE_API_KEY");
var api = new Uri("https://api.getprice.ai/v1/");
var http = new HttpClient { BaseAddress = api };
http.Timeout = TimeSpan.FromSeconds(30);
http.DefaultRequestHeaders.Authorization =
    new AuthenticationHeaderValue("Bearer", key);

var req = new HttpRequestMessage(
    HttpMethod.Put, "sku-mappings/13817L")
{
    Content = JsonContent.Create(
        new { product_id = "prd_Lp4sT1x9" }),
};
req.Headers.IfNoneMatch.Add(EntityTagHeaderValue.Any);
var res = await http.SendAsync(req);
if (res.StatusCode == HttpStatusCode.PreconditionFailed)
    throw new Exception("13817L is already linked");
res.EnsureSuccessStatusCode();
var body = await res.Content.ReadAsStringAsync();
Console.WriteLine($"{(int)res.StatusCode} {body}");
Response
{
  "sku": "13817L",
  "product_id": "prd_Lp4sT1x9",
  "comparison_set_id": null,
  "source": "api",
  "created_at": "2026-11-02T10:05:00Z",
  "updated_at": "2026-11-02T10:05:00Z"
}
ResponseMeaning
201 CreatedLinked. The Location header points at the new link
412 precondition_failedThe SKU is already linked. GET /v1/sku-mappings/13817L shows to what
404 product_not_foundproduct_id isn't one of your own products
422 validation_failedThe body is malformed, such as a missing product_id

Without If-None-Match, PUT creates or replaces the link, returning 200 when it replaced one. To replace a link only if nobody changed it since you read it, send its ETag as If-Match.

Use it#

GET /v1/comparison-sets?sku=13817L now returns the pilchards' comparison set.

To remove the link, call DELETE /v1/sku-mappings/13817L. It returns 204, or 404 if the SKU wasn't linked. Removing a link never deletes the product or its comparison set.