LLocalPrice DOCS
LOCALPRICE API · v0.7

Ship India-specific pricing
without trusting the browser.

LocalPrice turns a global product price into a deterministic INR recommendation, stores the result as a secure quote, and lets your backend verify the exact amount before creating checkout.

01Your backend$49 · USD · SaaS
02LocalPriceRules + seller limits
03Verified checkout₹1,499 · INR
Server-side only

Keep lp_test_… and lp_live_… keys on your server. Send only the public quote ID through browser or mobile clients.

Create your first trusted INR quote

Start with a TEST key. It uses isolated sandbox data and cannot consume LIVE allowance.

  1. 1

    Set your key

    Store it in your server environment—never in frontend JavaScript.

    .env
    LOCALPRICE_API_KEY="lp_test_your_key_here"
  2. 2

    Create a quote

    Use a unique idempotency key for each logical pricing operation.

    POST /v1/prices/quote
    curl -X POST "$LOCALPRICE_BASE_URL/v1/prices/quote" \
      -H "Authorization: Bearer $LOCALPRICE_API_KEY" \
      -H "Content-Type: application/json" \
      -H "Idempotency-Key: product-pro-annual-v1" \
      -d '{
        "amount": 49,
        "currency": "USD",
        "targetMarket": "IN",
        "productType": "saas",
        "pricingMode": "localized"
      }'
    quote.ts
    import { LocalPrice } from '@localprice/node';
    
    const localprice = new LocalPrice({
      apiKey: process.env.LOCALPRICE_API_KEY!,
    });
    
    const quote = await localprice.quotes.create({
      amount: 49,
      currency: 'USD',
      targetMarket: 'IN',
      productType: 'saas',
      pricingMode: 'localized',
    }, { idempotencyKey: 'product-pro-annual-v1' });
  3. 3

    Use the response

    Display localizedAmount to the customer and save quoteId for checkout verification. Money is returned as decimal strings to prevent floating-point loss.

    201 Created
    {
      "data": {
        "quoteId": "quote_kN0cRjTQY0wJ8A6wE5b5FDzQ",
        "status": "ACTIVE",
        "mode": "TEST",
        "pricingMode": "localized",
        "sourceAmount": "49.0000",
        "sourceCurrency": "USD",
        "localizedAmount": "1499.00",
        "localizedCurrency": "INR",
        "targetMarket": "IN",
        "productType": "saas",
        "pricingModelVersion": "v1",
        "expiresAt": "2026-09-01T12:00:00.000Z"
      }
    }

Authentication and environments

Send the API key as a Bearer token on every pricing endpoint.

HTTP
Authorization: Bearer lp_test_your_key_here
TEST

lp_test_…

Sandbox quotes, isolated data, 1,000 monthly requests. Ideal for development and CI.

LIVE

lp_live_…

Production quotes, paid allowance, completely isolated from TEST resources.

Never expose secret keys

Do not embed a LocalPrice API key in a browser, mobile app, public repository, log line, URL, or analytics event. Route calls through your backend.

1. Create a quote

POST/v1/prices/quoteAuthenticated

Choose localized for an India-optimized recommendation or fx for direct market-rate conversion. Omitting the mode preserves the localized default. Both create the same secure, project-scoped quote.

Request body

FieldTypeDescription
amountnumber · required

Positive source price. Use a JSON number, not a formatted currency string.

currencyenum · required

USD, EUR, JPY, KRW, or AED.

targetMarketenum · required

Must be IN in V1.

pricingModeenum · optional

localized (default) or fx.

productTypeenum · conditional

Required for localized unless the project supplies a default; optional for FX.

sellerConstraintsobject · localized only

FX requests containing constraints return CONSTRAINT_NOT_SUPPORTED_FOR_FX_MODE.

Headers

Authorizationrequired

Bearer lp_test_… or Bearer lp_live_…

Idempotency-Keyrecommended

Unique per logical quote creation; makes retries safe.

X-Request-Idoptional

Your trace ID: letters, digits, ., _, or -; maximum 64 characters.

2. Display the localized price

Return only display-safe quote data to the frontend. Keep the source input and LocalPrice key server-side.

Browser₹1,499Displays quote
Sends quoteId
HTTPS
Your backendquote_01J…Owns API key
Creates checkout
HTTPS
LocalPriceINR 1499Stores quote
Verifies amount
Treat the browser as untrusted

The displayed amount is presentation data. Never accept an INR amount submitted by the client as the checkout authority.

3. Verify before charging

POST/v1/prices/quotes/:quoteId/verifyAuthenticated

From your backend, verify the quote immediately before creating a payment-provider session. Use the returned checkout.amount and checkout.currency exactly.

checkout.ts
const verified = await localprice.quotes.verify(quoteId);

const checkoutSession = await payments.checkout.create({
  currency: verified.checkout.currency, // "INR"
  amount: verified.checkout.amount,     // 1499
  metadata: { localpriceQuoteId: verified.id },
});
✓ Do

Use the stored, verified checkout values returned by LocalPrice.

× Don't

Recalculate, round, convert, or trust an amount supplied by the browser.

Retrieve a quote

GET/v1/prices/quotes/:quoteIdAuthenticated

Retrieve the stored quote for display refreshes or server-side inspection. Quotes remain isolated by project and mode; a quote created with a TEST key is invisible to LIVE keys.

Supported values

Source currencies

USDEURJPYKRWAEDINR

Product types

saasai_tooldeveloper_toolonline_coursecreator_tooldigital_product

Enum values are case-sensitive. The only V1 target market is IN, and localized currency is always INR.

Pricing modes and seller constraints

localized applies FX, affordability, category, constraints, price-point rounding, and a recommendation range. fx applies only source amount × current FX rate and normal two-decimal INR rounding. Optional constraints keep a localized recommendation inside your commercial boundaries. Precedence is evaluated per field: request value > project default > LocalPrice default.

sellerConstraints
{
  "maximumRegionalDiscountPercent": 70,
  "minimumRevenueRetentionPercent": 30,
  "minimumLocalizedPriceINR": 1299,
  "maximumLocalizedPriceINR": 2999,
  "sellerCostAmount": 8,
  "sellerCostCurrency": "USD",
  "minimumGrossMarginPercent": 40
}
maximumRegionalDiscountPercent0–100

Caps discount relative to direct FX price.

minimumRevenueRetentionPercent0–100

Protects the minimum source-price revenue retained.

minimumLocalizedPriceINRpositive INR

Sets an explicit floor.

maximumLocalizedPriceINRpositive INR

Sets an explicit ceiling.

sellerCostAmount + 2 moreall required together

Cost amount, cost currency, and minimum gross margin form one constraint group.

Conflicts fail closed

An impossible combination returns 422 CONSTRAINT_CONFLICT. LocalPrice never silently ignores a seller limit.

Quote states

ACTIVE

Safe to display and eligible for verification.

expires or invalidates
EXPIRED

Create a fresh quote. Returns 410.

INVALIDATED

Create a fresh quote. Returns 409.

Always check the verification response at checkout time. Do not infer validity from a timestamp cached in the client.

Stable errors you can act on

Branch on error.code and HTTP status—not the human-readable message. Every error includes a request ID for support and tracing.

Error envelope
{
  "requestId": "req_01J…",
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Request validation failed",
    "details": {}
  }
}
HTTPCodeWhat your integration should do
400VALIDATION_ERROR

Fix the payload; do not retry unchanged.

401API_KEY_MISSING / INVALID / REVOKED

Fix server credentials or replace the key.

403EARLY_ACCESS_REQUIRED

Contact the LocalPrice administrator for approval.

404RESOURCE_NOT_FOUND

Check quote ID, project, and TEST/LIVE mode.

409IDEMPOTENCY_KEY_CONFLICT / QUOTE_INVALIDATED

Use the original payload/new key, or create a new quote.

410QUOTE_EXPIRED

Create and display a new quote.

422CONSTRAINT_CONFLICT

Correct incompatible seller constraints.

429RATE_LIMIT_EXCEEDED / QUOTA_EXCEEDED

Wait for Retry-After, then retry.

502/503*_UNAVAILABLE

Retry later; preserve the same idempotency key.

Retry safely and trace everything

01

Idempotency

Reuse the same key and normalized payload after a timeout. A replay returns the original response with Idempotency-Replayed: true. Completed responses are stored durably in PostgreSQL with the quote and quota. Durable identities do not expire automatically.

02

Rate limits

Inspect RateLimit-Limit, RateLimit-Remaining, and RateLimit-Reset. Respect Retry-After on 429.

03

Request IDs

Log X-Request-Id from every response and include it in support requests. You may supply your own safe trace identifier.

Database-backed retry safety

A Redis cache failure after commit does not invalidate your quote: retry with the same key to recover the original response. Redis remains required for the separate short-term rate limiter. Use a new key for a new quote after expiry.

Access and monthly quota

Early access is currently available to selected early users while we are validating the pricing engine.

New organizations start PENDING. Only a LocalPrice administrator can approve key creation and API access. No subscription payment is required.

Organization and project limits default to 10,000 successful creations and verifications per UTC calendar month. TEST and LIVE share these limits. Retrievals, failed requests, dashboard traffic, and idempotent replays do not consume quota.

Check remaining quota and reset date in Usage & Analytics. Exhaustion returns HTTP 429 QUOTA_EXCEEDED; this is separate from the short-term Redis rate limit.

Production checklist

  • Use a LIVE key only in the production server environment.
  • Create one idempotency key per cart or pricing operation.
  • Send only quoteId through the browser.
  • Verify on your backend immediately before checkout creation.
  • Use verified.checkout.amount and .currency without recalculation.
  • Handle expired and invalidated quotes by creating a fresh quote.
  • Implement bounded retry with jitter for 429, network failures, and temporary 5xx errors.
  • Record X-Request-Id and configure quota alerts.
  • Use GET /health for liveness and GET /ready for dependency readiness.

Node.js SDK

npm install @localprice/node

The TypeScript-first client supports apiKey, baseUrl, timeout, requestId, and conservative maxRetries. Quote creation is retried only when you provide an idempotency key; retrieval and verification are safe to retry.

complete-flow.ts
import { LocalPrice, generateIdempotencyKey } from '@localprice/node';

const localprice = new LocalPrice({
  apiKey: process.env.LOCALPRICE_API_KEY!,
  timeout: 5_000,
  maxRetries: 2,
});

const quote = await localprice.quotes.create({
  amount: 49,
  currency: 'USD',
  targetMarket: 'IN',
  productType: 'saas',
  pricingMode: 'localized',
}, {
  idempotencyKey: generateIdempotencyKey('pricing-page'),
});

// Send quote.id and display-safe fields to the browser.
// Later, on your checkout route:
const verified = await localprice.quotes.verify(quote.id);
console.log(verified.checkout.amount, verified.checkout.currency);

Give coding agents reliable context

LocalPrice publishes concise machine-readable context alongside the full API schema. Give both files to your coding assistant before asking it to build an integration.

Copy this implementation brief

Prompt for an AI coding assistant
Implement LocalPrice using the contract in /docs/llms.txt and
/docs/openapi.yaml. Keep the API key server-side. Create quotes with a
unique Idempotency-Key, return only display-safe quote data to the client,
and pass only quoteId back at checkout. Verify the quote on the server and
use verified.checkout.amount and verified.checkout.currency exactly when
creating payment checkout. Handle stable error.code values, respect
Retry-After, and log X-Request-Id. Do not recalculate or trust client prices.
AI safety boundary

Never paste a real LocalPrice key, customer data, or payment-provider secret into an AI prompt. Use environment-variable placeholders and TEST keys in generated examples.

Endpoint index

Need every schema and response?Open the canonical OpenAPI 3.1 specification.View OpenAPI →
Esc

Type to search sections. Press Enter to open.