Integration

API Purchases

Use this endpoint to create purchases from your store and receive the final result through a webhook.

Purchase flow
Main endpoint
POSThttps://bs.hydracidx.com/api/purchase/

Send every purchase request to this route. It is the only purchase entry point for the API.

Authorization

  • Authentication uses the reseller static `url_token`.
  • Send the token in the `Authorization` header using the `Token` scheme.
  • The same token can be reused for every request until you rotate it.
Header example
Authorization: Token YOUR_STATIC_URL_TOKEN

Reseller pricing by quantity

  • The reseller price changes depending on the requested quantity.
  • Different quantity ranges can produce different unit prices.
  • Check the API Products page to see the detailed pricing tiers for each product.

Request parameters

The purchase body contains four required fields and one optional language field.

JSON body

reference_id

string

Your own unique reference for the order in your system.

  • Returned back in the webhook so you can match the response to your original request.
  • Must identify one purchase payload within your reseller account.
  • If request validation fails before acceptance, no purchase is created and the same reference can be submitted again after correcting the request.
  • Repeating the same reference with the same product, quantity, webhook URL, and normalized language is idempotent: HydraCID X returns the existing purchase without charging or delivering it twice.
  • If that existing purchase failed only because reseller credit was insufficient, submitting the unchanged request again after adding enough credit resumes the same purchase.
  • Reusing a reference with any of those fields changed is rejected with HTTP 409 and duplicate_reference_id.
  • Cannot contain spaces.
  • Recommended format: internal order code, invoice ID, or cart reference.
Example: ORDER_100045

product_id

uuid

The public product identifier shown in the API Products section.

  • Do not send internal product IDs.
  • The same field works for all supported product types.
  • Copy it exactly as shown in the panel.
Example: 8d4cde52-7df0-4704-852f-0ef08b4b8ed7

qty

integer

The amount of units you want to buy for the selected product.

  • Minimum value: 1.
  • Maximum value: 500.
  • Used to calculate the reseller pricing tier.
Example: 3

webhook_url

url

HTTPS endpoint in your system that receives the final purchase result.

  • Must accept a JSON POST request.
  • Must use HTTPS and resolve only to public internet addresses.
  • Credentials in the URL, fragments, localhost, private/reserved IPs, and unresolvable hosts are rejected.
  • Redirects are not followed; your endpoint must receive the POST directly.
  • An invalid URL returns HTTP 400 before the purchase starts or the reference is reserved.
  • Should return HTTP 2xx when the payload is processed correctly.
  • If the first delivery fails, HydraCID X retries it up to three times. If it still fails, our team is notified and will try again later.
  • The same result may be delivered more than once. Store one order per purchase_id (or reference_id) and make each identical delivery idempotent.
  • A result that failed only for insufficient reseller credit may later be followed by an updated result for the same IDs when you resubmit the unchanged purchase after adding credit.
Example: https://store.example.com/api/hydracidx/webhook
HTTP 400: {"webhook_url":["Webhook URL must be a direct, publicly reachable HTTPS endpoint. Local, private, link-local and reserved destinations are not allowed."]}

lang

optional string

Selects the language only for the optional indications field in a successful or partial webhook.

  • indications is not included for every product; it is omitted when no additional instructions are available.
  • lang does not translate statuses, details, product data, prices, quantities, keys, or any other webhook field.
  • Supported languages: en English, de German, es Spanish, pt Portuguese, zh Chinese, ru Russian, fr French, ar Arabic, hi Hindi, it Italian, ko Korean, id Indonesian, tr Turkish, vi Vietnamese, and pl Polish.
  • If the field is missing, blank, or contains any other value, HydraCID X uses English.
Example: es

Accepted request

A new, pending, or resumed purchase returns HTTP 202. An identical replay of a terminal result returns HTTP 200. Both responses include the purchase and reference IDs, current status, and processing_queue_status.

  • queued: purchase processing was queued normally.
  • processed: an identical repeated request returned the already completed result without processing it again.
  • manual_retry_required: the purchase was saved but processing did not start. Do not submit a second purchase; HydraCID X support receives a protected recovery alert.

How to test the API

Use the dedicated test product ID below to validate your webhook integration safely.

Safe test mode
Test-only product_id
d0d15b8b-01bb-4d88-97a2-ab6716d86404
  • Send this UUID in `product_id` to trigger a webhook test.
  • No reseller credit will be deducted.
  • No stock will be consumed.
  • A zero-value purchase record is created so the reference remains idempotent.
  • The backend sends the test payload only once; test webhooks do not use automatic delivery retries.

Test request examples

Safe test mode
cURL
curl --request POST \
  --url "https://hydracidx.com/api/purchase/" \
  --header "Authorization: Token YOUR_STATIC_URL_TOKEN" \
  --header "Content-Type: application/json" \
  --data '{"reference_id":"WEBHOOK_TEST_001","product_id":"d0d15b8b-01bb-4d88-97a2-ab6716d86404","qty":1,"lang":"es","webhook_url":"https://store.example.com/api/hydracidx/webhook"}'

Webhook payload example

This is the payload we will send to your server through your configured webhook URL.

{
  "status": "success",
  "purchase_id": 152,
  "reference_id": "ORDER_100045",
  "product_id": "8d4cde52-7df0-4704-852f-0ef08b4b8ed7",
  "product_name": "Windows 11 Pro Retail",
  "qty_requested": 3,
  "qty_processed": 3,
  "unit_reseller_price": "4.50",
  "total_reseller_price": "13.50",
  "keys": [
    "XXXXX-XXXXX-XXXXX-XXXXX-XXXXX"
  ],
  "indications": "<b>Instalación:</b> Sigue las instrucciones proporcionadas para este producto.",
  "detail": "",
  "acts_remaining": 24,
  "warranty_days": 30
}

Recommended security

Verify webhook signatures

HydraCID X signs outgoing webhooks so your server can confirm that the request is authentic and that the JSON body was not changed in transit.

HMAC-SHA256
Signature verification protects your integration and is strongly recommended, but it is optional. Your existing webhook endpoint will continue working normally if it ignores these headers and keeps returning HTTP 2xx.

Headers sent with every signed webhook

HeaderValue
X-Hydra-TimestampUnix timestamp in seconds generated for that delivery attempt.
X-Hydra-Signature-256sha256=<lowercase hexadecimal digest>

Signing contract

  1. Use your static reseller API token as the HMAC secret. Keep it only on your server and never expose it in browser code. If the secret is missing, stop with a configuration error; never calculate or accept a signature using an empty secret.
  2. Read the raw HTTP request body bytes before parsing JSON. Do not parse and re-serialize the body before verification.
  3. Build the signed value as <timestamp>.<raw_body>, with the exact timestamp header, one ASCII period, and the exact body bytes.
  4. Calculate HMAC-SHA256 and format it as sha256=<hex digest>.
  5. Compare the expected and received signatures with a constant-time comparison.
  6. Recommended: reject timestamps older than five minutes to reduce replay risk, and still deduplicate deliveries by purchase_id or reference_id.
signed_value = X-Hydra-Timestamp + "." + raw_request_body
signature = "sha256=" + HMAC_SHA256(api_token, signed_value).hex()
  • Each retry has a new timestamp and signature, while the webhook JSON payload remains the same.
  • If you rotate your API token, update the secret in your webhook receiver immediately; later attempts use the current token.
  • No challenge, signature echo, or special response body is required. Return your normal HTTP 2xx after processing.

Webhook signature verification examples

Server-side
Python
import hashlib
import hmac
import os
import time
from flask import abort, request

secret = os.environ['HYDRACIDX_API_TOKEN'].encode('utf-8')
raw_body = request.get_data(cache=True)
timestamp = request.headers.get('X-Hydra-Timestamp', '')
provided = request.headers.get('X-Hydra-Signature-256', '')

try:
    if abs(int(time.time()) - int(timestamp)) > 300:
        abort(401)
except ValueError:
    abort(401)

signed_payload = timestamp.encode('ascii') + b'.' + raw_body
expected = 'sha256=' + hmac.new(secret, signed_payload, hashlib.sha256).hexdigest()
if not hmac.compare_digest(expected, provided):
    abort(401)

payload = request.get_json()
# Process purchase_id idempotently, then return HTTP 2xx.

Possible statuses

  • pending: purchase created and still processing.
  • success: purchase completed successfully.
  • failed: purchase rejected or no stock was available.
  • partial: only part of the requested quantity could be delivered.

Conditional webhook fields

  • acts_remaining is only returned for online MAK or LTSC products.
  • warranty_days is returned only if warranty applies.
  • download_url is returned if product needs a downloadable resource.
  • indications is an optional HTML string with additional instructions for the delivered product. The field is omitted when no additional instructions are available. When present, it uses the language requested through lang, with English as the fallback.