The Nestuge Developer API is a brand-authenticated REST API. Read your products, transactions, hub members, and a product's customers; import members and customers; generate checkout links; and subscribe to webhooks. Everything your storefront does is available to your own tools.
Responses share a common envelope: status, message, and the payload under data. List endpoints paginate with limit and cursor query parameters and return hasMore and nextCursor alongside the items.
Base URLs
https://nestuge.com/api/v1 # ProductionEvery request is authenticated with a brand API key sent in the x-nestuge-api header. Keys are created from your dashboard under Settings → Developer and come in two modes: nk_live_… for production and nk_test_… for test mode.
Each key is granted scopes such as products:read or webhooks:write; the scopes an endpoint needs are listed next to it in this reference. Verify a key with the ping endpoint. It returns your brand, the key mode, and the granted scopes.
Keep keys server-side. Never embed them in client-side code, and rotate a key from the dashboard if it leaks.
Request
curl https://nestuge.com/api/v1/ping \
-H "x-nestuge-api: nk_test_your_key"Response
{
"status": "success",
"message": "OK",
"data": {
"ok": true,
"brandID": "a1b2c3d4e5",
"mode": "test",
"scopes": ["products:read", "webhooks:write"]
}
}Register an HTTPS endpoint with POST /webhooks (or from the dashboard) to receive events as they happen. The signing secret is returned once at creation and never again. Store it safely.
Every delivery is a JSON event envelope signed with an X-Nestuge-Signature header containing sha256=<hex>, an HMAC-SHA256 of the raw request body using your signing secret. Verify it with the Nestuge SDK before trusting a payload, and always verify against the raw body exactly as received: re-serialized JSON will not match the signature.
Respond with a 2xx status quickly; failed deliveries can be inspected and resent from the webhook deliveries endpoints below.
Event payload
{
"id": "a1b2c3d4e5",
"type": "transaction.succeeded",
"created": "2026-07-06T10:00:00.000Z",
"data": {
// the transaction, purchase, or customer
// the event is about
}
}verify-webhook.ts
import { constructEvent } from '@nestuge/sdk';
const event = await constructEvent({
payload: rawRequestBody, // the raw, unmodified body string
signature: request.headers['x-nestuge-signature'],
secret: process.env.NESTUGE_WEBHOOK_SECRET,
});
switch (event.type) {
case 'transaction.succeeded':
// event.data is the transaction
break;
}Everything in this reference is plain HTTPS + JSON, so any HTTP client works, but the official SDK and example app are the fastest way to a working integration.
JavaScript / TypeScript SDK
@nestuge/sdkThe official SDK for the Developer API. Fully typed, zero runtime dependencies, and runs anywhere fetch does: Node.js 18+, Bun, Deno, and edge runtimes. Ships retries, cursor pagination helpers, typed errors, and webhook signature verification.
Example app: developer console
nestuge-dashboardA small developer console built as the reference consumer of the SDK: connection status, members, products, transactions, and a webhook delivery log with a test-event form. Next.js App Router; every API call happens server-side, so your key never reaches the browser.
Terminal
npm install @nestuge/sdkquickstart.ts
import Nestuge from '@nestuge/sdk';
const nestuge = new Nestuge({ apiKey: process.env.NESTUGE_API_KEY });
// Verify your key works
const { brandID, mode, scopes } = await nestuge.ping();
// List your customers
const { items } = await nestuge.customers.list({ limit: 50 });List hub members
/hubs/{hubID}/membersLists a hub's members (memberships), newest first.
Path parameters
hubID
string
required
Query parameters
limit
string
cursor
string
Request
curl "https://nestuge.com/api/v1/hubs/a1b2c3d4e5/members" \
-H "x-nestuge-api: nk_test_your_key"Request
import Nestuge from '@nestuge/sdk';
const nestuge = new Nestuge({ apiKey: process.env.NESTUGE_API_KEY });
const members = await nestuge.hubs.members.list('a1b2c3d4e5');Response
{
"status": "success",
"message": "OK",
"data": {
"items": [
{
"membershipId": "a1b2c3d4e5",
"name": "Ada Lovelace",
"email": "ada@example.com",
"phone": "+2348012345678",
"hubID": "a1b2c3d4e5",
"status": "active",
"plan": "string",
"joinedAt": "2026-07-06T10:00:00.000Z"
}
],
"hasMore": true,
"nextCursor": "a1b2c3d4e5"
}
}Get a hub member
/hubs/{hubID}/members/{id}Returns a single hub membership by its membership id.
Path parameters
hubID
string
required
id
string
required
Request
curl "https://nestuge.com/api/v1/hubs/a1b2c3d4e5/members/a1b2c3d4e5" \
-H "x-nestuge-api: nk_test_your_key"Request
import Nestuge from '@nestuge/sdk';
const nestuge = new Nestuge({ apiKey: process.env.NESTUGE_API_KEY });
const member = await nestuge.hubs.members.retrieve('a1b2c3d4e5', 'a1b2c3d4e5');Response
{
"status": "success",
"message": "OK",
"data": {
"membershipId": "a1b2c3d4e5",
"name": "Ada Lovelace",
"email": "ada@example.com",
"phone": "+2348012345678",
"hubID": "a1b2c3d4e5",
"status": "active",
"plan": "string",
"joinedAt": "2026-07-06T10:00:00.000Z"
}
}Import members to a hub
/hubs/{hubID}/members/importBulk-imports members into the hub. Send `records` as an array of objects; hubs collect only `fullName` and `email`, both required, e.g. `[{ "fullName": "Ada Lovelace", "email": "ada@example.com" }]`. Queues the import and returns how many records were accepted.
Path parameters
hubID
string
required
Body parameters
records
array of object
required
plan
string
Request
curl -X POST "https://nestuge.com/api/v1/hubs/a1b2c3d4e5/members/import" \
-H "x-nestuge-api: nk_test_your_key" \
-H "Content-Type: application/json" \
-d '{
"records": [
{}
]
}'Request
import Nestuge from '@nestuge/sdk';
const nestuge = new Nestuge({ apiKey: process.env.NESTUGE_API_KEY });
const member = await nestuge.hubs.members.import('a1b2c3d4e5', {
records: [
{}
]
});Response
{
"status": "success",
"message": "OK",
"data": {
"queued": true,
"count": 10
}
}Generate a payment link
/payment-linksCreates a payment link for the given items and returns a link the customer can open to complete payment. Accepts the same payload as the web checkout. Every item must belong to the authenticated brand.
Body parameters
items
array of object
required
items.id
string
required
items.plan
string
required
items.type
string
required
items.hubID
string
items.affiliate
string
items.selected
array of string
items.count
number
items.customAmount
number
form
object
required
form.formData
object
required
form.formData.fullName
string
required
form.formData.email
string
required
form.formData.phone
string
form.guests
array of object
form.guests.id
string
required
form.guests.fullName
string
required
form.guests.email
string
required
currency
string
coupon
string
countryCode
string
addons
array of string
booking
object
address
object
deliveryLocation
string
pickupLocation
string
redirectUrl
string
utmRef
string
adClickID
string
adType
string
checkoutOtpVerificationSkipped
boolean
receive_emails
boolean
Request
curl -X POST "https://nestuge.com/api/v1/payment-links" \
-H "x-nestuge-api: nk_test_your_key" \
-H "Content-Type: application/json" \
-d '{
"items": [
{
"id": "a1b2c3d4e5",
"plan": "string",
"type": "string",
"hubID": "a1b2c3d4e5",
"affiliate": "string",
"selected": [
"string"
],
"count": 10,
"customAmount": 5000
}
],
"form": {
"formData": {
"fullName": "Ada Lovelace",
"email": "ada@example.com",
"phone": "+2348012345678"
},
"guests": [
{
"id": "a1b2c3d4e5",
"fullName": "Ada Lovelace",
"email": "ada@example.com"
}
]
}
}'Request
import Nestuge from '@nestuge/sdk';
const nestuge = new Nestuge({ apiKey: process.env.NESTUGE_API_KEY });
const paymentLink = await nestuge.paymentLinks.create({
items: [
{
id: 'a1b2c3d4e5',
plan: 'string',
type: 'string',
hubID: 'a1b2c3d4e5',
affiliate: 'string',
selected: [
'string'
],
count: 10,
customAmount: 5000
}
],
form: {
formData: {
fullName: 'Ada Lovelace',
email: 'ada@example.com',
phone: '+2348012345678'
},
guests: [
{
id: 'a1b2c3d4e5',
fullName: 'Ada Lovelace',
email: 'ada@example.com'
}
]
}
});Response
{
"status": "success",
"message": "OK",
"data": {
"link": "string"
}
}Verify an API key
/pingAuthenticated health check. Returns the resolved brand and granted scopes so developers can confirm their key works. Any valid key may call it (no scope required).
Request
curl "https://nestuge.com/api/v1/ping" \
-H "x-nestuge-api: nk_test_your_key"Request
import Nestuge from '@nestuge/sdk';
const nestuge = new Nestuge({ apiKey: process.env.NESTUGE_API_KEY });
const ping = await nestuge.ping();Response
{
"status": "success",
"message": "OK",
"data": {
"ok": true,
"brandID": "a1b2c3d4e5",
"scopes": [
"products:read"
]
}
}List products
/productsLists the brand's products (all types), newest first.
Query parameters
limit
string
cursor
string
Request
curl "https://nestuge.com/api/v1/products" \
-H "x-nestuge-api: nk_test_your_key"Request
import Nestuge from '@nestuge/sdk';
const nestuge = new Nestuge({ apiKey: process.env.NESTUGE_API_KEY });
const products = await nestuge.products.list();Response
{
"status": "success",
"message": "OK",
"data": {
"items": [
{
"id": "a1b2c3d4e5",
"type": "string",
"status": "active",
"title": "Design masterclass",
"description": "A hands-on class covering the basics.",
"imageUrl": "https://example.com/image.png",
"url": "https://example.com/webhooks/nestuge",
"visibility": "string",
"isFree": true,
"keywords": [
"string"
],
"createdAt": "2026-07-06T10:00:00.000Z",
"updatedAt": "2026-07-06T10:00:00.000Z",
"event": {
"eventType": "string",
"venue": "Lagos, Nigeria",
"dateTime": "2026-07-06T10:00:00.000Z",
"endDate": "2026-07-06T10:00:00.000Z"
}
}
],
"hasMore": true,
"nextCursor": "a1b2c3d4e5"
}
}Get a product
/products/{id}Returns a single product owned by the brand, including its pricing tiers and content items.
Path parameters
id
string
required
Request
curl "https://nestuge.com/api/v1/products/a1b2c3d4e5" \
-H "x-nestuge-api: nk_test_your_key"Request
import Nestuge from '@nestuge/sdk';
const nestuge = new Nestuge({ apiKey: process.env.NESTUGE_API_KEY });
const product = await nestuge.products.retrieve('a1b2c3d4e5');Response
{
"status": "success",
"message": "OK",
"data": {
"id": "a1b2c3d4e5",
"type": "string",
"status": "active",
"title": "Design masterclass",
"description": "A hands-on class covering the basics.",
"imageUrl": "https://example.com/image.png",
"url": "https://example.com/webhooks/nestuge",
"visibility": "string",
"isFree": true,
"keywords": [
"string"
],
"createdAt": "2026-07-06T10:00:00.000Z",
"updatedAt": "2026-07-06T10:00:00.000Z",
"event": {
"eventType": "string",
"venue": "Lagos, Nigeria",
"dateTime": "2026-07-06T10:00:00.000Z",
"endDate": "2026-07-06T10:00:00.000Z"
},
"tiers": [
{
"id": "a1b2c3d4e5",
"name": "Ada Lovelace",
"type": "string",
"price": {
"amount": 5000,
"currency": "USD"
},
"discount": {
"amount": 5000,
"currency": "USD"
},
"recurrence": {
"periodic": "string",
"count": 10,
"interval": 10
},
"perks": [
"string"
],
"buttonText": "string",
"timeBound": "2026-07-06T10:00:00.000Z",
"slots": 10,
"noOfTickets": 10,
"itemIDs": [
"string"
],
"isDefault": true,
"status": "active",
"archived": true
}
],
"items": [
{
"id": "a1b2c3d4e5",
"type": "string",
"title": "Design masterclass",
"description": "A hands-on class covering the basics.",
"image": "string",
"duration": 30,
"isAddon": true,
"parentId": "a1b2c3d4e5",
"price": {
"amount": 5000,
"currency": "USD"
}
}
],
"checkoutFields": [
{
"id": "a1b2c3d4e5",
"label": "string",
"type": "string",
"required": true,
"options": [
"string"
]
}
]
}
}List a product's customers
/products/{id}/customersLists the product's active customers (purchasers), newest first.
Path parameters
id
string
required
Query parameters
limit
string
cursor
string
Request
curl "https://nestuge.com/api/v1/products/a1b2c3d4e5/customers" \
-H "x-nestuge-api: nk_test_your_key"Request
import Nestuge from '@nestuge/sdk';
const nestuge = new Nestuge({ apiKey: process.env.NESTUGE_API_KEY });
const customers = await nestuge.products.customers.list('a1b2c3d4e5');Response
{
"status": "success",
"message": "OK",
"data": {
"items": [
{
"membershipId": "a1b2c3d4e5",
"name": "Ada Lovelace",
"email": "ada@example.com",
"phone": "+2348012345678",
"hubID": "a1b2c3d4e5",
"status": "active",
"plan": "string",
"joinedAt": "2026-07-06T10:00:00.000Z"
}
],
"hasMore": true,
"nextCursor": "a1b2c3d4e5"
}
}Import customers to a product
/products/{id}/customers/importBulk-imports customers into the product. Send `records` as an array of objects keyed by field id (see `checkoutFields` on the product); `fullName` and `email` are required, e.g. `[{ "fullName": "Ada Lovelace", "email": "ada@example.com" }]`. Queues the import and returns how many records were accepted.
Path parameters
id
string
required
Body parameters
records
array of object
required
plan
string
Request
curl -X POST "https://nestuge.com/api/v1/products/a1b2c3d4e5/customers/import" \
-H "x-nestuge-api: nk_test_your_key" \
-H "Content-Type: application/json" \
-d '{
"records": [
{}
]
}'Request
import Nestuge from '@nestuge/sdk';
const nestuge = new Nestuge({ apiKey: process.env.NESTUGE_API_KEY });
const customer = await nestuge.products.customers.import('a1b2c3d4e5', {
records: [
{}
]
});Response
{
"status": "success",
"message": "OK",
"data": {
"queued": true,
"count": 10
}
}List transactions
/transactionsLists the brand's transactions, newest first.
Query parameters
limit
string
cursor
string
Request
curl "https://nestuge.com/api/v1/transactions" \
-H "x-nestuge-api: nk_test_your_key"Request
import Nestuge from '@nestuge/sdk';
const nestuge = new Nestuge({ apiKey: process.env.NESTUGE_API_KEY });
const transactions = await nestuge.transactions.list();Response
{
"status": "success",
"message": "OK",
"data": {
"items": [
{
"txref": "string",
"type": "string",
"status": "active",
"amount": 5000,
"currency": "USD",
"customer": {
"name": "Ada Lovelace",
"email": "ada@example.com"
},
"createdAt": "2026-07-06T10:00:00.000Z",
"resourceID": "a1b2c3d4e5"
}
],
"hasMore": true,
"nextCursor": "a1b2c3d4e5"
}
}Get a transaction
/transactions/{id}Returns a single transaction by its reference.
Path parameters
id
string
required
Request
curl "https://nestuge.com/api/v1/transactions/a1b2c3d4e5" \
-H "x-nestuge-api: nk_test_your_key"Request
import Nestuge from '@nestuge/sdk';
const nestuge = new Nestuge({ apiKey: process.env.NESTUGE_API_KEY });
const transaction = await nestuge.transactions.retrieve('a1b2c3d4e5');Response
{
"status": "success",
"message": "OK",
"data": {
"txref": "string",
"type": "string",
"status": "active",
"amount": 5000,
"currency": "USD",
"customer": {
"name": "Ada Lovelace",
"email": "ada@example.com"
},
"createdAt": "2026-07-06T10:00:00.000Z",
"resourceID": "a1b2c3d4e5"
}
}List webhook endpoints
/webhooksLists the brand's webhook endpoints.
Query parameters
limit
string
cursor
string
Request
curl "https://nestuge.com/api/v1/webhooks" \
-H "x-nestuge-api: nk_test_your_key"Request
import Nestuge from '@nestuge/sdk';
const nestuge = new Nestuge({ apiKey: process.env.NESTUGE_API_KEY });
const webhooks = await nestuge.webhooks.list();Response
{
"status": "success",
"message": "OK",
"data": {
"items": [
{
"id": "a1b2c3d4e5",
"url": "https://example.com/webhooks/nestuge",
"events": [
"transaction.succeeded"
],
"status": "active",
"description": "A hands-on class covering the basics.",
"createdAt": "2026-07-06T10:00:00.000Z",
"updatedAt": "2026-07-06T10:00:00.000Z"
}
],
"hasMore": true,
"nextCursor": "a1b2c3d4e5"
}
}Create a webhook endpoint
/webhooksRegisters an endpoint URL. The signing secret is returned once in this response and never again.
Body parameters
url
string
required
events
array of enum
required
transaction.succeededtransaction.failedpayout.settledsubscription.renewedsubscription.expiredsubscription.completedmember.joinedmember.removeddescription
string
Request
curl -X POST "https://nestuge.com/api/v1/webhooks" \
-H "x-nestuge-api: nk_test_your_key" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/webhooks/nestuge",
"events": [
"transaction.succeeded"
]
}'Request
import Nestuge from '@nestuge/sdk';
const nestuge = new Nestuge({ apiKey: process.env.NESTUGE_API_KEY });
const webhook = await nestuge.webhooks.create({
url: 'https://example.com/webhooks/nestuge',
events: [
'transaction.succeeded'
]
});Response
{
"status": "success",
"message": "OK",
"data": {
"id": "a1b2c3d4e5",
"url": "https://example.com/webhooks/nestuge",
"events": [
"transaction.succeeded"
],
"status": "active",
"description": "A hands-on class covering the basics.",
"createdAt": "2026-07-06T10:00:00.000Z",
"updatedAt": "2026-07-06T10:00:00.000Z",
"signingSecret": "string"
}
}Get a webhook endpoint
/webhooks/{id}Path parameters
id
string
required
Request
curl "https://nestuge.com/api/v1/webhooks/a1b2c3d4e5" \
-H "x-nestuge-api: nk_test_your_key"Request
import Nestuge from '@nestuge/sdk';
const nestuge = new Nestuge({ apiKey: process.env.NESTUGE_API_KEY });
const webhook = await nestuge.webhooks.retrieve('a1b2c3d4e5');Response
{
"status": "success",
"message": "OK",
"data": {
"id": "a1b2c3d4e5",
"url": "https://example.com/webhooks/nestuge",
"events": [
"transaction.succeeded"
],
"status": "active",
"description": "A hands-on class covering the basics.",
"createdAt": "2026-07-06T10:00:00.000Z",
"updatedAt": "2026-07-06T10:00:00.000Z"
}
}Update a webhook endpoint
/webhooks/{id}Path parameters
id
string
required
Body parameters
url
string
events
array of enum
transaction.succeededtransaction.failedpayout.settledsubscription.renewedsubscription.expiredsubscription.completedmember.joinedmember.removedstatus
enum
activedisableddescription
string
Request
curl -X PATCH "https://nestuge.com/api/v1/webhooks/a1b2c3d4e5" \
-H "x-nestuge-api: nk_test_your_key" \
-H "Content-Type: application/json" \
-d '{}'Request
import Nestuge from '@nestuge/sdk';
const nestuge = new Nestuge({ apiKey: process.env.NESTUGE_API_KEY });
const webhook = await nestuge.webhooks.update('a1b2c3d4e5', {});Response
{
"status": "success",
"message": "OK",
"data": {
"id": "a1b2c3d4e5",
"url": "https://example.com/webhooks/nestuge",
"events": [
"transaction.succeeded"
],
"status": "active",
"description": "A hands-on class covering the basics.",
"createdAt": "2026-07-06T10:00:00.000Z",
"updatedAt": "2026-07-06T10:00:00.000Z"
}
}Delete a webhook endpoint
/webhooks/{id}Path parameters
id
string
required
Request
curl -X DELETE "https://nestuge.com/api/v1/webhooks/a1b2c3d4e5" \
-H "x-nestuge-api: nk_test_your_key"Request
import Nestuge from '@nestuge/sdk';
const nestuge = new Nestuge({ apiKey: process.env.NESTUGE_API_KEY });
const webhook = await nestuge.webhooks.del('a1b2c3d4e5');Response
{
"status": "success",
"message": "OK",
"data": {
"id": "a1b2c3d4e5",
"deleted": false
}
}Send a test webhook event
/webhooks/testSynthesizes a sample event and delivers it through the real signed/retried/logged pipeline as a sample delivery.
Body parameters
eventType
enum
required
transaction.succeededtransaction.failedpayout.settledsubscription.renewedsubscription.expiredsubscription.completedmember.joinedmember.removedendpointID
string
Request
curl -X POST "https://nestuge.com/api/v1/webhooks/test" \
-H "x-nestuge-api: nk_test_your_key" \
-H "Content-Type: application/json" \
-d '{
"eventType": "transaction.succeeded"
}'Request
import Nestuge from '@nestuge/sdk';
const nestuge = new Nestuge({ apiKey: process.env.NESTUGE_API_KEY });
const webhook = await nestuge.webhooks.test({
eventType: 'transaction.succeeded'
});Response
{
"status": "success",
"message": "OK",
"data": {
"created": 10
}
}List webhook deliveries
/webhooks/deliveriesQuery parameters
limit
string
cursor
string
Request
curl "https://nestuge.com/api/v1/webhooks/deliveries" \
-H "x-nestuge-api: nk_test_your_key"Request
import Nestuge from '@nestuge/sdk';
const nestuge = new Nestuge({ apiKey: process.env.NESTUGE_API_KEY });
const deliveries = await nestuge.webhooks.deliveries.list();Response
{
"status": "success",
"message": "OK",
"data": {
"items": [
{
"id": "a1b2c3d4e5",
"endpointID": "a1b2c3d4e5",
"eventType": "transaction.succeeded",
"resourceType": "transaction",
"resourceID": "a1b2c3d4e5",
"status": "pending",
"attempts": 10,
"responseCode": 10,
"mode": "live",
"createdAt": "2026-07-06T10:00:00.000Z",
"deliveredAt": "2026-07-06T10:00:00.000Z"
}
],
"hasMore": true,
"nextCursor": "a1b2c3d4e5"
}
}Get a webhook delivery
/webhooks/deliveries/{id}Path parameters
id
string
required
Request
curl "https://nestuge.com/api/v1/webhooks/deliveries/a1b2c3d4e5" \
-H "x-nestuge-api: nk_test_your_key"Request
import Nestuge from '@nestuge/sdk';
const nestuge = new Nestuge({ apiKey: process.env.NESTUGE_API_KEY });
const delivery = await nestuge.webhooks.deliveries.retrieve('a1b2c3d4e5');Response
{
"status": "success",
"message": "OK",
"data": {
"id": "a1b2c3d4e5",
"endpointID": "a1b2c3d4e5",
"eventType": "transaction.succeeded",
"resourceType": "transaction",
"resourceID": "a1b2c3d4e5",
"status": "pending",
"attempts": 10,
"responseCode": 10,
"mode": "live",
"createdAt": "2026-07-06T10:00:00.000Z",
"deliveredAt": "2026-07-06T10:00:00.000Z"
}
}Resend a webhook delivery
/webhooks/deliveries/{id}/resendPath parameters
id
string
required
Request
curl -X POST "https://nestuge.com/api/v1/webhooks/deliveries/a1b2c3d4e5/resend" \
-H "x-nestuge-api: nk_test_your_key"Request
import Nestuge from '@nestuge/sdk';
const nestuge = new Nestuge({ apiKey: process.env.NESTUGE_API_KEY });
const delivery = await nestuge.webhooks.deliveries.resend('a1b2c3d4e5');Response
{
"status": "success",
"message": "OK",
"data": {
"id": "a1b2c3d4e5",
"endpointID": "a1b2c3d4e5",
"eventType": "transaction.succeeded",
"resourceType": "transaction",
"resourceID": "a1b2c3d4e5",
"status": "pending",
"attempts": 10,
"responseCode": 10,
"mode": "live",
"createdAt": "2026-07-06T10:00:00.000Z",
"deliveredAt": "2026-07-06T10:00:00.000Z"
}
}