bubble-api-tools
v3.3.2
Published
Bubble.io API sdk
Maintainers
Readme
bubble-api-tools
A TypeScript wrapper for calling Bubble.io public endpoints:
- Workflow API (
/wf/...) — trigger backend workflows exposed as public API workflows. - Data API (
/obj/...) — CRUD operations on Bubble database types + bulk create.
Check out the Bubble.io API Docs:
Install
npm i bubble-api-toolsQuick start
import { Bubble } from "bubble-api-tools";
// Minimal config and usage example:
const bubble = Bubble.init({
name: "appname", // your Bubble app name (appname.bubbleapps.io)
authKey: process.env.BUBBLE_API_TOKEN, // optional, but usually required
customDomain: "example.com", // optional
mainBranch: "my-branch", // optional
});
// Initialize a Workflow API endpoint with your parameters (optional) (POST)
await bubble.workflow.initialization.post("my-endpoint", {
versionTest: true,
payload: { param1: "value", param2: 123 },
});
// Call a Workflow API endpoint (POST)
await bubble.workflow.post("my-endpoint", {
versionTest: true,
payload: { param1: "value", param2: 123 },
});
// Call a Workflow API endpoint (GET)
await bubble.workflow.get("my-endpoint", {
versionTest: true,
});
// Data API: create a Thing
await bubble.data.post("customer", {
versionTest: true,
payload: { name: "Mario", age: 33 },
});App configuration
The interface exposes app: BubbleApp:
type BubbleApp = {
name: string; // Bubble app name (appname.bubbleapps.io)
authKey?: string; // Bearer token (admin or user)
customDomain?: string; // e.g. mydomain.com (without https://)
mainBranch?: string; // branch path (commonly version-test)
apiVersion?: string; // default latest (if supported by your implementation)
metadata?: Record<string, any>;
}Root URL helpers
getApiRoot(type, options)
Builds the API root URL for a given API type.
// Examples:
bubble.getApiRoot("wf", { versionTest: true });
bubble.getApiRoot("wf", { useCustomDomain: true, versionTest: true });
bubble.getApiRoot("data", { useCustomDomain: true });type:"wf" | "data"useCustomDomain: whentrue, usesapp.customDomaininstead of*.bubbleapps.ioversionTest: whentrue, targets theversion-test(or your configured test branch)
Workflow API
All workflow calls require the workflow name (wfName).
workflow.post(wfName, options)
Triggers POST /api/1.1/wf/<wfName>
await bubble.workflow.post("my-endpoint", {
payload: { param1: "value", param2: 123 },
versionTest: true,
});workflow.get(wfName, options)
Triggers GET /api/1.1/wf/<wfName> (useful for webhooks that require GET)
await bubble.workflow.get("my-endpoint", {
queryParameters: [{ key: "foo", value: "bar" }],
versionTest: true,
});Initialization endpoints
Bubble supports .../wf/<wfName>/initialize to Detect request data.
workflow.initialization.post(wfName, options)
Triggers POST /api/1.1/wf/<wfName>/initialize
workflow.initialization.get(wfName, options)
Triggers GET /api/1.1/wf/<wfName>/initialize
Data API
All data calls take a path string. In practice this is usually:
- a type name (e.g.
"customer") for collection endpoints - a type + id (e.g.
"customer/<thingId>") for single-record endpoints
Create
data.post(path, options)
POST /api/1.1/obj/<path>
await bubble.data.post("customer", {
payload: { name: "Mario", age: 33 },
versionTest: true,
});Read
data.get(path, options?)
GET /api/1.1/obj/<path>
await bubble.data.get("customer", { versionTest: true }); // list of customers
await bubble.data.get("customer/169...", { versionTest: true }); // single customerUpdate
data.patch(path, options)
PATCH /api/1.1/obj/<path>
await bubble.data.patch("customer/169...", {
payload: { age: 34 },
versionTest: true,
});data.put(path, options)
PUT /api/1.1/obj/<path>
await bubble.data.put("customer/169...", {
payload: { name: "Mario", age: 34 },
versionTest: true,
});Delete
data.delete(path, options?)
DELETE /api/1.1/obj/<path>
await bubble.data.delete("customer/169...", { versionTest: true });Query parameters
For endpoints that support querystrings (e.g. constraints), pass queryParameters.
await bubble.data.get("customer", {
versionTest: true,
queryParameters: [
{ key: "constraints", value: JSON.stringify([{ key: "age", constraint_type: "greater than", value: 30 }]) },
],
});Bulk create (Data API)
data.bulk.post(path, options)
Creates many Things in one request.
await bubble.data.bulk.post("customer", {
versionTest: true,
payload: [
{ name: "A", age: 1 },
{ name: "B", age: 2 },
],
});Notes on auth
authKeyis sent asAuthorization: Bearer <token>.- Use an admin token for server-to-server tasks.
- Use a user token when you want Bubble to apply user-level permissions.
Check out the Bubble.io API Docs:
Types reference
Interface
type BubbleInterface = {
workflow: {
post: (wfName: string, options: {
payload?: Record<string, any>;
useCustomDomain?: boolean;
versionTest?: boolean;
}) => Promise<any>;
get: (wfName: string, options: {
queryParameters?: Record<string, string>[];
useCustomDomain?: boolean;
versionTest?: boolean;
}) => Promise<any>;
initialization: {
post: (wfName: string, options: {
payload?: Record<string, any>;
useCustomDomain?: boolean;
versionTest?: boolean;
}) => Promise<any>;
get: (wfName: string, options: {
queryParameters?: Record<string, string>[];
useCustomDomain?: boolean;
versionTest?: boolean;
}) => Promise<any>;
}
};
data: {
post: (path: string, options: {
queryParameters?: Record<string, string>[] | undefined;
useCustomDomain?: boolean;
versionTest?: boolean;
payload?: Record<string, any>;
}) => Promise<any>;
bulk: {
post: (path: string, options: {
queryParameters?: Record<string, string>[];
useCustomDomain?: boolean;
versionTest?: boolean;
payload?: Record<string, any>[];
}) => Promise<any>;
};
patch: (path: string, options: {
queryParameters?: Record<string, string>[];
useCustomDomain?: boolean;
versionTest?: boolean;
payload?: Record<string, any>;
}) => Promise<any>;
put: (path: string, options: {
queryParameters?: Record<string, string>[];
useCustomDomain?: boolean;
versionTest?: boolean;
payload?: Record<string, any>;
}) => Promise<any>;
get: (path: string, options?: {
queryParameters?: Record<string, string>[];
useCustomDomain?: boolean;
versionTest?: boolean;
}) => Promise<any>;
delete: (path: string, options?: {
queryParameters?: Record<string, string>[];
useCustomDomain?: boolean;
versionTest?: boolean;
}) => Promise<any>;
}
getApiRoot: (type: BubbleApiType, options: {
useCustomDomain?: boolean;
versionTest?: boolean;
}) => string;
app: BubbleApp;
initialized?: boolean;
}Other Types
type BubbleApiType = "wf" | "data";
type CrudMethods = "POST" | "GET" | "PUT" | "DELETE" | "PATCH";
type BubbleApp = {
name: string;
authKey?: string;
customDomain?: string;
mainBranch?: string;
apiVersion?: string;
metadata?: { [key: string]: any };
}