Developer platform
ChyaKharcha API
Use ChyaKharcha as the store, payments and delivery behind your own site, script or AI agent. List and manage products, open hosted checkouts (eSewa in Nepal, Stripe cards internationally), quote delivery, read orders and get webhooks — with one API key. Payouts work exactly as they do on the site.
Overview
- Base URL
https://www.chyakharcha.com/api/v1. JSON in, JSON out. All money is NPR; products also carry an approximate USD price. - Your own shop: create and update products, stock and discounts; receive orders; mark them fulfilled.
- Resell other shops: open a checkout for any active product. You earn the referral share (1% of the item price) on every sale through your key — no setup.
- We handle the rest: payment (eSewa / international card), delivery quotes and booking (Pathao in Nepal, ChyaKharcha international), buyer emails, and payouts (10% platform fee on product subtotals; delivery passes through).
Keys & authentication
Create keys on the dashboard and send one as a bearer token:
Authorization: Bearer ck_live_sk_…| Key | Where | Can |
|---|---|---|
| ck_live_sk_… | Server, script, AI client | Everything: products, orders, checkouts, webhooks |
| ck_live_pk_… | Web pages (safe to expose) | Read public listings, open checkouts |
| ck_test_… | Development | Checkouts are simulated, no money moves; can't change your live shop |
Quick start
1 · Check your key:
curl https://www.chyakharcha.com/api/v1/me -H "Authorization: Bearer $CK_KEY"2 · Add a product (physical products need a weight and a delivery setup on your shop page):
curl https://www.chyakharcha.com/api/v1/products -H "Authorization: Bearer $CK_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"Mute Tee","type":"physical","price_npr":1200,"weight_grams":250,
"stock_quantity":40,"sku":"MUTE-BLK","images":["https://example.com/tee.jpg"]}'3 · Sell it — open a checkout and redirect the buyer:
const res = await fetch("https://www.chyakharcha.com/api/v1/checkout/sessions", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.CK_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({
product_id: 793,
quantity: 1,
success_url: "https://your-site.com/thanks",
cancel_url: "https://your-site.com/cart",
metadata: { cart_id: "c_123" },
}),
})
const session = await res.json()
// redirect the buyer to session.url4 · Fulfil on the order.paid webhook (or poll GET /orders).
import os, requests
r = requests.patch(
"https://www.chyakharcha.com/api/v1/products/793",
headers={"Authorization": f"Bearer {os.environ['CK_KEY']}"},
json={"discount_percent": 15, "stock_quantity": 25},
)
print(r.json()["sale_price_npr"])Claude & ChatGPT
Give an AI assistant a secret key and it can run your inventory in plain language.
Claude — MCP server
URL https://www.chyakharcha.com/api/mcp, header Authorization: Bearer ck_live_sk_…. In Claude Code:
claude mcp add --transport http chyakharcha https://www.chyakharcha.com/api/mcp \
--header "Authorization: Bearer ck_live_sk_…"Tools: get_account, list_products, get_product, create_product, update_product, archive_product, quote_delivery, create_checkout_link, list_orders, get_order, update_order_status.
ChatGPT — custom GPT Actions
- Create a GPT → Configure → Actions → Import from URL:
https://www.chyakharcha.com/api/v1/openapi.json - Authentication: API Key, Auth type Bearer, paste your secret key.
- Ask: “List my products that are low on stock and set a 10% discount on anything with more than 50.”
Any other agent
Point it at /llms.txt — a plain-text guide to the API and its rules.
Products
GET/productsnone · or secret key
?seller=username&type=physical|digital|pod&limit=50&offset=0. With a secret key and no seller: your whole shop, including inactive products, stock and SKUs.POST/productslive secret key
name*, price_npr*, type (physical|digital), description, weight_grams (physical), stock_quantity, sku, images[], discount_percent, active.GET/products/{id}none
PATCH/products/{id}live secret key
name, description, discount_percent, stock_quantity, sku, weight_grams, images, active.DELETE/products/{id}live secret key
- Fair pricing:
price_npris fixed once a product exists. Change what buyers pay withdiscount_percent(0–90);sale_price_nprshows the result. stock_quantity: nullmeans stock isn't tracked. A number counts down automatically as orders are paid; at 0 the product shows “Sold out” and checkouts are refused.- Image URLs must be https; they're copied into ChyaKharcha storage.
Delivery
POST/delivery/quotenone
{ "product_id": 793, "quantity": 2,
"destination": { "country": "NP", "city": "Kathmandu" } }
{ "product_id": 793,
"destination": { "country": "US", "city": "Boston", "state": "MA", "postal_code": "02115" } }Returns options[] with method, label, fee_npr and live_quote. The buyer picks one at checkout; we book the courier when the order is paid.
Checkout
POST/checkout/sessionssecret or publishable key
product_id*, success_url*, quantity, cancel_url, customer_email, metadata (≤20 string values, echoed in webhooks). Returns { id, url, status, expires_at, … }; sessions last 24 hours.GET/checkout/sessions/{id}key that opened it
On url the buyer picks size / colour / finish (print-on-demand), delivery, and pays with eSewa (from Nepal) or card via Stripe (international). Afterwards they return to success_url?checkout_session_id=chk_…&order_id=…. Don't treat the redirect as proof of payment — wait for order.paid or check GET /orders/{id}.
With a test key the page offers “Simulate payment / failure” and sends test webhooks; no order is created and no money moves.
Orders
GET/orderssecret key
?role=seller|partner&status=pending|completed|cancelled. Seller: your shop's paid orders with customer and delivery details. Partner: orders you sold for other shops — product and amount only.GET/orders/{id}secret key
PATCH/orders/{id}live secret key (seller)
{ "status": "completed" | "cancelled", "note": "…" } — the note is shown to the buyer.Webhooks
Add endpoints on the dashboard or via POST /webhook_endpoints. Events: order.paid, order.updated, checkout.completed, product.updated. Sellers receive events for all their orders; partners for checkouts they opened.
POST https://your-site.com/webhooks/chyakharcha
CK-Signature: t=1760000000,v1=5f2c…
{ "id": "evt_paid_…", "type": "order.paid", "livemode": true, "created": "…",
"data": { "order": { "id": "…", "amount_npr": 1450, "product": {…}, "customer": {…},
"checkout_session": { "id": "chk_…", "metadata": { "cart_id": "c_123" } } } } }Verify the signature with your endpoint's whsec_… secret before trusting the body:
import crypto from "node:crypto"
export function verifyChyaKharcha(rawBody, header, secret) {
const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")))
const expected = crypto.createHmac("sha256", secret).update(`${parts.t}.${rawBody}`).digest("hex")
const fresh = Math.abs(Date.now() / 1000 - Number(parts.t)) < 300
return fresh && crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1 || ""))
}import hmac, hashlib, time
def verify_chyakharcha(raw_body: bytes, header: str, secret: str) -> bool:
parts = dict(p.split("=", 1) for p in header.split(","))
expected = hmac.new(secret.encode(), f"{parts['t']}.".encode() + raw_body, hashlib.sha256).hexdigest()
return abs(time.time() - int(parts["t"])) < 300 and hmac.compare_digest(expected, parts.get("v1", ""))Reply with any 2xx within 8 seconds. Failures are retried (3 quick tries, then daily for 3 days) and can be resent from the dashboard. Use the event id to ignore duplicates.
Drop-in widget
No backend needed — paste this where the shop should appear. Use a publishable key.
<!-- A product grid with Buy buttons -->
<div data-ck-shop="smudgewears" data-ck-key="ck_live_pk_…"
data-ck-type="physical" data-ck-limit="12" data-ck-columns="3"></div>
<!-- Or a single Buy button for product 793 -->
<button data-ck-buy="793" data-ck-key="ck_live_pk_…">Buy now</button>
<script src="https://www.chyakharcha.com/ck.js" async></script>Optional: data-ck-success / data-ck-cancel (default: the current page). Call ChyaKharcha.refresh() after adding elements dynamically. Prefer iframes? See the embed builder.
Errors & limits
{ "error": { "type": "invalid_request", "message": "`weight_grams` must be a whole number from 1 to 10000.", "param": "weight_grams" } }Types: invalid_request 400 · authentication_required 401 · permission_denied 403 · not_found 404 · conflict 409 · rate_limited 429 · api_error 500 (safe to retry).
Lists are capped at 100 per page. One product per checkout session (quantity up to 99). Up to 8 images per product, 8 MB each. Up to 10 webhook endpoints and 20 active keys per account.