Skip to content

Get started

Quickstart

Go from API key to competitor prices in about five minutes. Pick your language in any code panel and every panel follows.

  1. Get your key#

    Create your key in GetPrice: Settings → API & Integrations → Create API key. Only an admin can do this, and your organisation has one key. The full key is shown once, so copy it to your secret store before you close the dialog. Store it where your code can read it, never in the code itself.

    The 8 characters after gp_live_ are your key's prefix. The prefix isn't secret, so quote it to support when you need to identify a key. After the key is created, Settings shows only the prefix and the last 4 characters.

    export GETPRICE_API_KEY="gp_live_…"  # your key
    export GETPRICE_API_KEY="gp_live_…"  # your key
    # Python 3.9+ with requests:
    #   pip install requests
    export GETPRICE_API_KEY="gp_live_…"  # your key
    # Node.js 22.18+ runs a .ts file directly:
    #   node quickstart.ts
    # Node.js 20+: save the code as .mts, then
    #   npx tsx quickstart.mts
    export GETPRICE_API_KEY="gp_live_…"  # your key
    # PHP 8.2+ with the curl extension:
    #   php quickstart.php
    export GETPRICE_API_KEY="gp_live_…"  # your key
    # .NET 8: dotnet new console, paste the code
    # into Program.cs, then dotnet run
    # Once, in odoo-bin shell -d <your-database>.
    # Or: Settings > Technical > System Parameters.
    icp = env["ir.config_parameter"].sudo()
    icp.set_param("getprice.api_key", "gp_live_…")
    env.cr.commit()
    Your key
    gp_live_k3Xa91Qz_••••••••••••••••••••••••••••••••••••••
  2. Make your first request#

    Call GET /v1/me to check that your key works. It returns your key's name, your company, the key's scopes and your rate limit.

    A 401 means the key is missing or wrong. See Errors.

    BASE=https://api.getprice.ai/v1
    curl "$BASE/me" \
      -H "Authorization: Bearer $GETPRICE_API_KEY"
    import os
    
    import requests
    
    BASE = "https://api.getprice.ai/v1"
    KEY = os.environ["GETPRICE_API_KEY"]
    
    resp = requests.get(
        f"{BASE}/me",
        headers={"Authorization": f"Bearer {KEY}"},
        timeout=30,
    )
    resp.raise_for_status()
    me = resp.json()
    name = me["company"]["name"]
    per_minute = me["limits"]["per_minute"]
    print(f"Connected: {name}, {per_minute}/min")
    interface Me {
      company: { name: string };
      limits: { per_minute: number };
    }
    
    const BASE = "https://api.getprice.ai/v1";
    const KEY = process.env.GETPRICE_API_KEY;
    const url = `${BASE}/me`;
    const res = await fetch(url, {
      headers: { Authorization: `Bearer ${KEY}` },
    });
    if (!res.ok) {
      throw new Error(`GetPrice returned ${res.status}`);
    }
    const me = (await res.json()) as Me;
    const { name } = me.company;
    const perMinute = me.limits.per_minute;
    console.log(`Connected: ${name}, ${perMinute}/min`);
    <?php
    $base = "https://api.getprice.ai/v1";
    $key = getenv("GETPRICE_API_KEY");
    $ch = curl_init("$base/me");
    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
    );
    printf(
        "Connected: %s, %d/min\n",
        $data["company"]["name"],
        $data["limits"]["per_minute"],
    );
    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("me");
    res.EnsureSuccessStatusCode();
    var me = await res.Content
        .ReadFromJsonAsync<Me>(json);
    var name = me!.Company.Name;
    var perMinute = me.Limits.PerMinute;
    Console.WriteLine(
        $"Connected: {name}, {perMinute}/min");
    
    record Me(Company Company, Limits Limits);
    record Company(string Name);
    record Limits(int PerMinute);
    # In odoo-bin shell
    import requests
    
    BASE = "https://api.getprice.ai/v1"
    icp = env["ir.config_parameter"].sudo()
    KEY = icp.get_param("getprice.api_key")
    
    resp = requests.get(
        f"{BASE}/me",
        headers={"Authorization": f"Bearer {KEY}"},
        timeout=30,
    )
    resp.raise_for_status()
    me = resp.json()
    name = me["company"]["name"]
    per_minute = me["limits"]["per_minute"]
    print(f"Connected: {name}, {per_minute}/min")
    Response
    {
      "key": {
        "name": "Odoo production",
        "prefix": "k3Xa91Qz",
        "environment": "live"
      },
      "company": {
        "name": "Example Wholesale (Pty) Ltd"
      },
      "scopes": [
        "catalog:read",
        "matches:read",
        "skus:write"
      ],
      "limits": {
        "per_minute": 120,
        "window_seconds": 60
      }
    }
  3. Look up a SKU#

    Ask for the comparison set behind one of your SKUs. Repeat sku to look up to 100 SKUs in one request.

    skus tells you what happened to each SKU you sent. found means the set is in data. See Core concepts for the other statuses.

    BASE=https://api.getprice.ai/v1
    curl -G "$BASE/comparison-sets" \
      -H "Authorization: Bearer $GETPRICE_API_KEY" \
      --data-urlencode "sku=10072L"
    import json
    import os
    
    import requests
    
    BASE = "https://api.getprice.ai/v1"
    KEY = os.environ["GETPRICE_API_KEY"]
    
    resp = requests.get(
        f"{BASE}/comparison-sets",
        params=[("sku", "10072L")],
        headers={"Authorization": f"Bearer {KEY}"},
        timeout=30,
    )
    resp.raise_for_status()
    print(json.dumps(resp.json(), indent=2))
    const BASE = "https://api.getprice.ai/v1";
    const KEY = process.env.GETPRICE_API_KEY;
    const params = new URLSearchParams({ sku: "10072L" });
    const url = `${BASE}/comparison-sets?${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();
    console.log(JSON.stringify(page, null, 2));
    <?php
    $base = "https://api.getprice.ai/v1";
    $key = getenv("GETPRICE_API_KEY");
    $sku = rawurlencode("10072L");
    $ch = curl_init("$base/comparison-sets?sku=$sku");
    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, flags: JSON_THROW_ON_ERROR);
    echo json_encode(
        $data,
        JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES,
    ), "\n";
    using System.Net.Http.Headers;
    using System.Text.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 res = await http.GetAsync(
        "comparison-sets?sku=10072L");
    res.EnsureSuccessStatusCode();
    var body = await res.Content.ReadAsStringAsync();
    using var doc = JsonDocument.Parse(body);
    var pretty = new JsonSerializerOptions
    {
        WriteIndented = true,
    };
    Console.WriteLine(
        JsonSerializer.Serialize(doc.RootElement, pretty));
    # In odoo-bin shell
    import json
    
    import requests
    
    BASE = "https://api.getprice.ai/v1"
    icp = env["ir.config_parameter"].sudo()
    KEY = icp.get_param("getprice.api_key")
    
    resp = requests.get(
        f"{BASE}/comparison-sets",
        params=[("sku", "10072L")],
        headers={"Authorization": f"Bearer {KEY}"},
        timeout=30,
    )
    resp.raise_for_status()
    print(json.dumps(resp.json(), indent=2))
    Response
    {
      "data": [
        {
          "id": "set_x7Kp2Lm9",
          "name": "Baked Beans in Tomato Sauce 410g",
          "sku": "10072L",
          "own_product": {
            "id": "prd_8fK2mQa1",
            "name": "Baked Beans in Tomato Sauce 410g",
            "url": "https://shop.example.com/product/10072L",
            "price": {
              "amount": "18.99",
              "was": null,
              "currency": "ZAR"
            },
            "last_collected_at": "2026-11-02T04:12:09Z",
            "stale": false
          },
          "competitors": [
            {
              "competitor": {
                "id": "cmp_3LqV8nP2",
                "name": "Harbour Market",
                "domain": "harbourmarket.example.com"
              },
              "product": {
                "id": "prd_Q2vN9cD4",
                "name": "Baked Beans 410g",
                "url": "https://harbourmarket.example.com/baked-beans-in-tomato-sauce-410g"
              },
              "price": {
                "amount": "17.99",
                "was": "19.99",
                "currency": "ZAR"
              },
              "last_collected_at": "2026-11-02T03:05:11Z",
              "availability": "unknown",
              "status": "active",
              "stale": false,
              "match": {
                "review": "same",
                "reviewed_by": "customer",
                "confidence": null
              }
            },
            {
              "competitor": {
                "id": "cmp_7RwK4tB9",
                "name": "Cape Fresh",
                "domain": "capefresh.example.com"
              },
              "product": {
                "id": "prd_Hm3Wc8Kp",
                "name": "Baked Beans In Tomato Sauce 410g",
                "url": "https://capefresh.example.com/baked-beans-in-tomato-sauce-410g"
              },
              "price": {
                "amount": "18.99",
                "was": null,
                "currency": "ZAR"
              },
              "last_collected_at": "2026-11-02T03:11:40Z",
              "availability": "unknown",
              "status": "active",
              "stale": false,
              "match": {
                "review": "same",
                "reviewed_by": "getprice",
                "confidence": 0.94
              }
            },
            {
              "competitor": {
                "id": "cmp_9TzM2cX5",
                "name": "Northwind Wholesale",
                "domain": "northwindwholesale.example.com"
              },
              "product": {
                "id": "prd_Zt6Pa2Rn",
                "name": "Baked Beans In Tomato Sauce 410g",
                "url": "https://northwindwholesale.example.com/baked-beans-in-tomato-sauce-410g"
              },
              "price": {
                "amount": "17.99",
                "was": null,
                "currency": "ZAR"
              },
              "last_collected_at": "2026-11-02T03:20:05Z",
              "availability": "unknown",
              "status": "active",
              "stale": false,
              "match": {
                "review": "unreviewed",
                "reviewed_by": null,
                "confidence": 0.81
              }
            },
            {
              "competitor": {
                "id": "cmp_2HdR6wJ3",
                "name": "Metro Bulk",
                "domain": "metrobulk.example.com"
              },
              "product": {
                "id": "prd_Yc1Ke7Fs",
                "name": "Baked Beans in Tomato Sauce 24 x 410g",
                "url": "https://metrobulk.example.com/baked-beans-24x410g"
              },
              "price": {
                "amount": "429.00",
                "was": null,
                "currency": "ZAR"
              },
              "last_collected_at": "2026-10-24T04:31:58Z",
              "availability": "unknown",
              "status": "active",
              "stale": true,
              "match": {
                "review": "with_differences",
                "reviewed_by": "customer",
                "confidence": null
              }
            }
          ],
          "integrity": "ok",
          "updated_at": "2026-11-02T04:14:00Z"
        }
      ],
      "next_cursor": null,
      "skus": [
        {
          "sku": "10072L",
          "status": "found",
          "set_id": "set_x7Kp2Lm9",
          "product_id": "prd_8fK2mQa1"
        }
      ]
    }
  4. Read the competitor prices#

    Each entry in competitors is one retailer's listing of the same item. Read price for what they charge and last_collected_at for when GetPrice last read it.

    Harbour Market is on promotion: its price.was is R19.99, so shoppers save R2.00. Two of these need a second look. Metro Bulk's listing is a 24-pack kept on purpose (review: "with_differences"), and its price is stale. Northwind Wholesale's match isn't confirmed yet (review: "unreviewed").

    Next, read Core concepts, or go straight to the Nightly ERP sync guide.

    BASE=https://api.getprice.ai/v1
    curl -sG "$BASE/comparison-sets" \
      -H "Authorization: Bearer $GETPRICE_API_KEY" \
      --data-urlencode "sku=10072L" |
      jq -r '.data[].competitors[]
        | select(.price != null)
        | "\(.competitor.name): R\(.price.amount)"
          + " at \(.last_collected_at)"
          + (if .stale then " (stale)" else "" end)'
    import os
    
    import requests
    
    BASE = "https://api.getprice.ai/v1"
    KEY = os.environ["GETPRICE_API_KEY"]
    
    resp = requests.get(
        f"{BASE}/comparison-sets",
        params=[("sku", "10072L")],
        headers={"Authorization": f"Bearer {KEY}"},
        timeout=30,
    )
    resp.raise_for_status()
    for cset in resp.json()["data"]:
        for e in cset["competitors"]:
            if e["price"] is None:
                continue
            name = e["competitor"]["name"]
            amount = e["price"]["amount"]
            when = e["last_collected_at"]
            stale = " (stale)" if e["stale"] else ""
            print(f"{name}: R{amount} at {when}{stale}")
    interface Entry {
      competitor: { name: string };
      price: { amount: string } | null;
      last_collected_at: string | null;
      stale: boolean;
    }
    interface Page {
      data: { competitors: Entry[] }[];
    }
    
    const BASE = "https://api.getprice.ai/v1";
    const KEY = process.env.GETPRICE_API_KEY;
    const params = new URLSearchParams({ sku: "10072L" });
    const url = `${BASE}/comparison-sets?${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 Page;
    for (const set of page.data) {
      for (const e of set.competitors) {
        if (!e.price) continue;
        const stale = e.stale ? " (stale)" : "";
        console.log(
          `${e.competitor.name}: R${e.price.amount}` +
            ` at ${e.last_collected_at}${stale}`,
        );
      }
    }
    <?php
    $base = "https://api.getprice.ai/v1";
    $key = getenv("GETPRICE_API_KEY");
    $sku = rawurlencode("10072L");
    $ch = curl_init("$base/comparison-sets?sku=$sku");
    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 $set) {
        foreach ($set["competitors"] as $e) {
            if ($e["price"] === null) {
                continue;
            }
            printf(
                "%s: R%s at %s%s\n",
                $e["competitor"]["name"],
                $e["price"]["amount"],
                $e["last_collected_at"],
                $e["stale"] ? " (stale)" : "",
            );
        }
    }
    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(
        "comparison-sets?sku=10072L");
    res.EnsureSuccessStatusCode();
    var page = await res.Content
        .ReadFromJsonAsync<Page>(json);
    foreach (var set in page!.Data)
    {
        foreach (var e in set.Competitors)
        {
            if (e.Price is null) continue;
            var stale = e.Stale ? " (stale)" : "";
            Console.WriteLine(
                $"{e.Competitor.Name}: R{e.Price.Amount}"
                + $" at {e.LastCollectedAt}{stale}");
        }
    }
    
    record Page(List<CompSet> Data);
    record CompSet(List<Entry> Competitors);
    record Entry(
        Competitor Competitor,
        Price? Price,
        string? LastCollectedAt,
        bool Stale);
    record Competitor(string Name);
    record Price(string Amount);
    # In odoo-bin shell
    import requests
    
    BASE = "https://api.getprice.ai/v1"
    icp = env["ir.config_parameter"].sudo()
    KEY = icp.get_param("getprice.api_key")
    
    resp = requests.get(
        f"{BASE}/comparison-sets",
        params=[("sku", "10072L")],
        headers={"Authorization": f"Bearer {KEY}"},
        timeout=30,
    )
    resp.raise_for_status()
    for cset in resp.json()["data"]:
        for e in cset["competitors"]:
            if e["price"] is None:
                continue
            name = e["competitor"]["name"]
            amount = e["price"]["amount"]
            when = e["last_collected_at"]
            stale = " (stale)" if e["stale"] else ""
            print(f"{name}: R{amount} at {when}{stale}")
    Output
    Harbour Market: R17.99 at 2026-11-02T03:05:11Z
    Cape Fresh: R18.99 at 2026-11-02T03:11:40Z
    Northwind Wholesale: R17.99 at 2026-11-02T03:20:05Z
    Metro Bulk: R429.00 at 2026-10-24T04:31:58Z (stale)