Plumaas Docs
The Plumaas API uses simple REST conventions: JSON bodies, predictable URLs, and HTTP status codes. The full OpenAPI spec is at /api/openapi.json and a Swagger UI lives at /api/docs.
Quickstart
After signing up, you get an API key. Use it as a bearer token.
cURL
# Create a payment link
curl https://plumaas.com/api/v1/charges \
-H "Authorization: Bearer $PLUMAAS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"org_id": "ORG_UUID",
"amount_cents": 12900,
"currency": "USD",
"description": "Subscription — December"
}'Python
pip install plumaas
from plumaas import Plumaas
p = Plumaas(api_key="psk_live_...")
charge = p.charges.create(org_id="ORG_UUID", amount_cents=12900,
description="Subscription — December")
print(charge["pay_url"])Node.js
const res = await fetch("https://plumaas.com/api/v1/charges", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.PLUMAAS_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
org_id: "ORG_UUID",
amount_cents: 12900,
currency: "USD",
description: "Subscription — December",
}),
});
const charge = await res.json();
console.log(charge.pay_url);Authentication
Plumaas uses bearer tokens. Pass Authorization: Bearer YOUR_API_KEY on every request. Keys are shown once at creation — store them in your secret manager.
- Live keys start with
psk_live_ - Test keys start with
psk_test_ - Rotate via dashboard → API keys → Generate. Old key keeps working for 24h after rotation.
Webhooks
Plumaas signs every outbound webhook with HMAC-SHA256. Verify before trusting the payload.
Signature format
X-Plumaas-Event: charge.succeeded
X-Plumaas-Timestamp: 1758432000
X-Plumaas-Signature: t=1758432000,v1=<hex_hmac_sha256>
# signed payload = f"{timestamp}.{body}"Verifying — Python
from plumaas import verify_webhook
@app.post("/plumaas/webhook")
async def hook(req):
body = await req.body()
if not verify_webhook(SECRET, body, dict(req.headers)):
raise HTTPException(401)
event = await req.json()
# event["event"] is one of charge.succeeded | charge.failed | ...Verifying — Node.js
import crypto from "node:crypto";
function verify(secret, body, headers, tolerance = 300) {
const sigHeader = headers["x-plumaas-signature"];
if (!sigHeader) return false;
const parts = Object.fromEntries(sigHeader.split(",").map(p => p.split("=")));
const ts = Number(parts.t);
if (!ts || Math.abs(Date.now()/1000 - ts) > tolerance) return false;
const expected = crypto.createHmac("sha256", secret)
.update(`${ts}.`).update(body).digest("hex");
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1));
}Events available
charge.succeeded— payment capturedcharge.failed— gateway declined; goes into the dunning queuecharge.refunded— full or partial refund issuedsubscription.created— new recurring schedulesubscription.canceled— schedule canceled
Test before going live
Send a sample event to your endpoint from the dashboard, or via API:
curl -X POST https://plumaas.com/api/v1/webhook-endpoints/$EP_ID/test \
-H "Authorization: Bearer $PLUMAAS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"event": "charge.succeeded"}'Ready to start?
Create an account in under a minute — KYB review happens in the background.
Get started