### Store API Quickstart with cURL Source: https://vialapi.com/developers This script demonstrates catalog retrieval, order validation, and order creation using the Store API. It requires a VIALAPI_TEST_KEY and uses an Idempotency-Key to ensure safe retries. ```bash #!/usr/bin/env bash set -euo pipefail : "${VIALAPI_TEST_KEY:?Set VIALAPI_TEST_KEY to an expiring vial_test_ credential}" VIALAPI_BASE_URL="${VIALAPI_BASE_URL:-https://vialapi.com}" curl --fail-with-body --silent --show-error \ --request GET "${VIALAPI_BASE_URL}/api/v1/catalog?limit=20" \ --header "Authorization: Bearer ${VIALAPI_TEST_KEY}" \ --header "Accept: application/json" # Replace VIAL-EXAMPLE-SKU with vialApiSku from the authenticated catalog. curl --fail-with-body --silent --show-error \ --request POST "${VIALAPI_BASE_URL}/api/v1/orders/validate" \ --header "Authorization: Bearer ${VIALAPI_TEST_KEY}" \ --header "Accept: application/json" \ --header "Content-Type: application/json" \ --data '{"lineItems":[{"sku":"VIAL-EXAMPLE-SKU","quantity":1}]}' # Use the exact same Idempotency-Key and exact JSON bytes after an uncertain result. curl --fail-with-body --silent --show-error \ --request POST "${VIALAPI_BASE_URL}/api/v1/orders" \ --header "Authorization: Bearer ${VIALAPI_TEST_KEY}" \ --header "Accept: application/json" \ --header "Content-Type: application/json" \ --header "Idempotency-Key: quickstart-order-001" \ --data '{"externalOrderId":"QUICKSTART-001","customer":{"firstName":"API","lastName":"Certification","email":"api-certification@example.test"},"shipTo":{"recipientName":"API Certification","address1":"100 Example Avenue","city":"Atlanta","state":"GA","postalCode":"30309","country":"US","residential":true},"lineItems":[{"sku":"VIAL-EXAMPLE-SKU","quantity":1}],"metadata":{"source":"published-quickstart","vialapiSandboxScenario":"standard"}}' ``` -------------------------------- ### Store API Quickstart Source: https://vialapi.com/developers A certified CI script demonstrating the Store API operations: catalog read, order validation, and order creation with idempotency. It uses a sandbox credential (vial_test_) and the base URL https://vialapi.com. ```APIDOC ## GET /api/v1/catalog ### Description Retrieves the authenticated catalog for the Store API. Requires a valid bearer token. ### Method GET ### Endpoint /api/v1/catalog ### Parameters #### Query Parameters - **limit** (integer) - Optional - Maximum number of catalog items to return. Example: 20. ### Request Example ``` curl --request GET "https://vialapi.com/api/v1/catalog?limit=20" \ --header "Authorization: Bearer vial_test_..." \ --header "Accept: application/json" ``` ### Response #### Success Response (200) Returns the catalog items. The response includes a field `vialApiSku` for each item, used in order operations. ## POST /api/v1/orders/validate ### Description Validates an order without creating it. Useful for checking line items before submission. ### Method POST ### Endpoint /api/v1/orders/validate ### Parameters #### Request Body - **lineItems** (array) - Required - List of line items to validate. - **sku** (string) - Required - The SKU of the item, e.g., VIAL-EXAMPLE-SKU. - **quantity** (integer) - Required - Quantity of the item. ### Request Example ``` { "lineItems": [ { "sku": "VIAL-EXAMPLE-SKU", "quantity": 1 } ] } ``` ### Response #### Success Response (200) Validation result. Details not specified in the source. ## POST /api/v1/orders ### Description Creates an order. The request must include an Idempotency-Key header. Returns 202 Accepted and the order progresses through the lifecycle via webhooks and polling. ### Method POST ### Endpoint /api/v1/orders ### Parameters #### Headers - **Idempotency-Key** (string) - Required - Unique key for idempotent order creation. Reuse the same key and exact JSON bytes on retries. #### Request Body - **externalOrderId** (string) - Required - External order identifier. - **customer** (object) - Required - Customer details. - **firstName** (string) - Required - Customer first name. - **lastName** (string) - Required - Customer last name. - **email** (string) - Required - Customer email. - **shipTo** (object) - Required - Shipping address. - **recipientName** (string) - Required - Recipient name. - **address1** (string) - Required - Street address. - **city** (string) - Required - City. - **state** (string) - Required - State or province. - **postalCode** (string) - Required - Postal code. - **country** (string) - Required - Country code. - **residential** (boolean) - Required - Indicates if the address is residential. - **lineItems** (array) - Required - List of line items. - **sku** (string) - Required - SKU of the item. - **quantity** (integer) - Required - Quantity. - **metadata** (object) - Optional - Additional metadata. - **source** (string) - Optional - Source identifier. - **vialapiSandboxScenario** (string) - Optional - Sandbox scenario identifier. ### Request Example ``` { "externalOrderId": "QUICKSTART-001", "customer": { "firstName": "API", "lastName": "Certification", "email": "api-certification@example.test" }, "shipTo": { "recipientName": "API Certification", "address1": "100 Example Avenue", "city": "Atlanta", "state": "GA", "postalCode": "30309", "country": "US", "residential": true }, "lineItems": [ { "sku": "VIAL-EXAMPLE-SKU", "quantity": 1 } ], "metadata": { "source": "published-quickstart", "vialapiSandboxScenario": "standard" } } ``` ### Response #### Success Response (202 Accepted) Order accepted. The order progresses through the lifecycle via webhooks and polling. ### Error Handling - Retry rule: reuse the exact same Idempotency-Key and exact JSON bytes after any uncertain result. A retried request can never create a second order. ``` -------------------------------- ### Verify VialAPI Webhook in TypeScript Source: https://vialapi.com/developers This function verifies the webhook signature using the raw request body and headers. It includes checks for timestamp tolerance and secret format, and uses timingSafeEqual to prevent timing attacks. ```typescript import { createHmac, timingSafeEqual } from "node:crypto"; type WebhookHeaders = { "webhook-id": string; "webhook-timestamp": string; "webhook-signature": string; }; /** Verify the exact raw bytes before parsing JSON, then deduplicate webhook-id. */ export function verifyVialApiWebhook({ headers, rawBody, secret, nowSeconds = Math.floor(Date.now() / 1_000), toleranceSeconds = 5 * 60 }: { headers: WebhookHeaders; rawBody: string; secret: string; nowSeconds?: number; toleranceSeconds?: number; }) { if (!/^\d+$/u.test(headers["webhook-timestamp"])) return false; const sentAt = Number(headers["webhook-timestamp"]); if (!Number.isSafeInteger(sentAt) || Math.abs(nowSeconds - sentAt) > toleranceSeconds) return false; if (!secret.startsWith("whsec_")) return false; const encodedSecret = secret.slice("whsec_".length); const key = Buffer.from(encodedSecret, "base64"); if (key.length < 24 || key.length > 64 || key.toString("base64") !== encodedSecret) return false; const expected = createHmac("sha256", key) .update(`${headers["webhook-id"]}.${headers["webhook-timestamp"]}.${rawBody}`, "utf8") .digest(); return headers["webhook-signature"].split(/\s+/u).some((candidate) => { const match = /^v1,([A-Za-z0-9+/]+={0,2})$/u.exec(candidate); if (!match?.[1]) return false; const received = Buffer.from(match[1], "base64"); return received.length === expected.length && timingSafeEqual(received, expected); }); } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.