PriceKit

Your calculator on your website — developer guide

Three ways to show PriceKit calculators outside PriceKit: the embed code for any site, the WordPress plugin, and the API. In every case the price is calculated on PriceKit's server only; formulas and hidden option prices never reach a browser. Requires PriceKit Pro (the trial included).

1. Embed code

Every active calculator is on your website automatically, at its latest saved version. In PriceKit: "Website & API" → "Your calculators on your website" → enter your domain → copy the calculator's embed code. The calculator shows only inside those domains (browser frame-ancestors protection) and sizes itself.

<div data-pricekit="https://pricekit-clients.ghosounmedia.com/f/LINK-TOKEN"></div>
<script src="https://pricekit-clients.ghosounmedia.com/assets/embed.js" async></script>

Options: data-lang="en" for the language, data-title for the frame title (screen readers). Look, custom CSS, the thank-you message and the page after sending are set in PriceKit: "Website & API".

2. WordPress plugin

  1. Download the plugin from PriceKit: "Website & API" → Keys → "Download the WordPress plugin", upload it in WordPress and activate it.
  2. Create a "secret key" in PriceKit and paste it in WordPress: Settings → PriceKit.
  3. Add the "PriceKit calculator" block, or the shortcode:
[pricekit calculator="CALCULATOR-ID" product="123" lang="en"]

The calculator is part of the page and takes the theme's fonts and colours. product (optional) shows WooCommerce "Add to cart" at the price calculated by PriceKit (signed; a browser cannot change it). You may add your own Turnstile or reCAPTCHA keys in the plugin settings.

3. API v1

Address: https://pricekit-clients.ghosounmedia.com/v1 — JSON, UTF-8.

KeyWhereAllows
Authorization: Bearer sk_…Your site's server onlyEverything: list, form, calculate, send requests, signed price
X-PriceKit-Key: pk_…Browsers on your registered domains only (https)List, form and calculate only — never sends requests
RequestWhat it does
GET /v1/calculatorsThe account's website calculators (every active calculator automatically, and "On my website" links).
GET /v1/calculators/{id}?lang=enThe form: fields, options, contact data and texts — no pricing.
POST /v1/calculators/{id}/calculateField states, option prices when allowed, the final price on request.
POST /v1/calculators/{id}/requestsSend a customer request (secret key only) — it reaches "Customer requests".
POST /v1/calculators/{id}/priceA signed price for WooCommerce or your shop (secret key only).
GET /v1/public-keyThe public key that checks signed prices.

curl

curl -H "Authorization: Bearer sk_…" https://pricekit-clients.ghosounmedia.com/v1/calculators

curl -H "Authorization: Bearer sk_…" -H "Content-Type: application/json" \
  -d '{"answers":{"bedrooms":"two","extras":["oven"]},"requestPrice":true,"language":"ar"}' \
  https://pricekit-clients.ghosounmedia.com/v1/calculators/CALCULATOR-ID/calculate

curl -H "Authorization: Bearer sk_…" -H "Content-Type: application/json" \
  -d '{"answers":{"bedrooms":"two"},"contact":{"name":"Samer","phone":"0599123456","email":"samer@example.com"},
       "language":"ar","idempotencyKey":"9f1c…","priceShown":true,"elapsedMs":42000,"visitor":{"ip":"203.0.113.5"}}' \
  https://pricekit-clients.ghosounmedia.com/v1/calculators/CALCULATOR-ID/requests

Answers: text or a number as text ("12.5"), true/false, the option key for a single choice, an array of keys for multiple choice, dates as yyyy-MM-dd.

When sending requests: pass the visitor's address (visitor.ip), the time since the form was shown (elapsedMs) and leave website empty — invisible protection against automated sending. idempotencyKey prevents the same request twice.

HTTPerrorMeaning
401invalid_keyWrong or revoked key, or the wrong kind of key.
403origin_not_allowed · secret_key_required · unavailableUnregistered domain for a site key; an operation that needs the secret key; calculators paused (subscription or administrator).
404not_foundNo such active calculator in this account.
400invalidErrors in answers or contact data (issues: field + message).
409price_hiddenThe calculator does not show its final price, so no signed price.
429rejectedStopped by the invisible protection (automated or repeated sending).

4. Checking a signed price

The response holds payload (a JSON text with the calculator, answers, total, currency and expiry) and signature (ECDSA P-256 / SHA-256, DER, base64) over "PriceKit.Price.v1\n" + payload. Always check it on your server:

// PHP
$pem = json_decode(file_get_contents('https://pricekit-clients.ghosounmedia.com/v1/public-key'), true)['pem'];
$ok  = openssl_verify("PriceKit.Price.v1\n" . $payload, base64_decode($signature), $pem, OPENSSL_ALGO_SHA256) === 1;
$data = json_decode($payload, true);   // check $data['calculator'], $data['expiresAt'] > time(), $data['currency']

// Node.js
const { verify } = require('crypto');
const ok = verify('sha256', Buffer.from('PriceKit.Price.v1\n' + payload), pem, Buffer.from(signature, 'base64'));

5. Webhooks

In PriceKit: "Website & API" → Webhooks → add an https address. Every new customer request is POSTed as JSON, retried for about two hours until your system answers 2xx.

X-PriceKit-Event: request.created        (ping for "send a test")
X-PriceKit-Delivery: 2f6c…
X-PriceKit-Signature: t=1767225600,v1=5d41402abc…   // HMAC-SHA256(secret, t + "." + body), hex

{"id":"…","event":"request.created","createdAt":"…","data":{"request":{
  "id":"…","number":"1C41F42E","status":"New","calculator":"…","link":{"kind":"website",…},
  "contact":{"name":"…","phone":"…","email":"…"},"answers":[{"field":"…","label":"…","value":"…"}],
  "price":{"total":"120.00","currency":"SAR","display":"120.00 SAR"},"receiptUrl":"…"}}}

// Node.js check
const [t, v1] = header.split(',').map(p => p.split('=')[1]);
const ok = crypto.timingSafeEqual(Buffer.from(v1), Buffer.from(
  crypto.createHmac('sha256', secret).update(t + '.' + rawBody).digest('hex')));

6. Fair use and privacy

No visible limits: calculators, visitors, calculations and requests are unlimited within the "fair use" of the PriceKit terms. The invisible protection only stops automated sending. We keep daily counts per site, and visitor addresses only as hashes (removed after 30 days).

Website settings in PriceKit · PriceKit