@moureau/basebox
v0.0.34
Published
Type-safe SDK for the Basebox BaaS platform. Built on [Eden Treaty](https://elysiajs.com/eden/treaty/overview) — every method is fully typed against the API.
Downloads
1,862
Readme
@basebox/sdk
Type-safe SDK for the Basebox BaaS platform. Built on Eden Treaty — every method is fully typed against the API.
Install
bun add @basebox/sdkQuick Start
import { Basebox } from '@basebox/sdk';
const basebox = new Basebox({
baseUrl: 'https://api.basebox.com',
publicKey: 'bb_anon_...', // base64-encoded { organization_id, project_id }
});Auth Modes
The SDK has three modes, each targeting a different route group:
| Mode | Auth | Use Case |
|------|------|----------|
| basebox.client({ sessionId }) | Bearer token | Client-side apps, admin dashboards |
| basebox.managed({ apiKey }) | X-API-Key header | Server-to-server (e.g., Broto) |
| basebox.public() | None | OAuth flow initiation |
Client (Session-Based)
For authenticated users. The sessionId comes from the OAuth callback popup.
const client = basebox.client({ sessionId: 'session-token-from-oauth' });Auth
// Check if session is valid
const { data } = await client.auth.check();
// Logout
await client.auth.logout();User Profile
// Get current profile
const { data } = await client.user.profile();
// Update profile
await client.user.updateProfile({ name: 'New Name', picture: 'https://...' });
// List organizations
const { data } = await client.user.organizations({ page: 1, page_size: 20 });Payments (PIX)
// List my payments
const { data } = await client.payments.list({ page: 1, page_size: 20 });
// Filter by status
const { data } = await client.payments.list({ page: 1, page_size: 20, status: 'completed' });
// Get specific payment
const { data } = await client.payments.get('payment-id');CDN / File Storage
// Request presigned upload URL
const { data } = await client.cdn.upload({
filename: 'photo.png',
content_type: 'image/png',
size: 102400,
});
// data.asset — asset record
// data.uploadUrl — presigned PUT URL (expires in 5 min)
// Upload the file directly to R2
await fetch(data.uploadUrl, {
method: 'PUT',
body: file,
headers: { 'Content-Type': 'image/png' },
});
// List my files
const { data } = await client.cdn.files({ page: 1, page_size: 20 });
// Filter by MIME type
const { data } = await client.cdn.files({ page: 1, page_size: 20, type: 'image/png' });
// Delete a file
await client.cdn.delete('file-id');Admin (Owner/Admin Role Required)
Admin methods are available on the same client instance. The API rejects calls from non-admin users with 403.
User Management
// List users with search/filters
const { data } = await client.admin.users.list({
page: 1,
page_size: 20,
search: 'john', // search by name or email
roles: ['admin'], // filter by role
status: 'active', // 'active' | 'banned'
});
// Look up by email
const { data } = await client.admin.users.getByEmail('[email protected]');
// Get user profile + account
const { data } = await client.admin.users.get('profile-id');
// Ban user
await client.admin.users.ban('profile-id', {
reason: 'Violated terms',
expires_at: '2026-04-01T00:00:00Z', // optional
});
// Unban user
await client.admin.users.unban('profile-id');
// Change role
await client.admin.users.updateRole('profile-id', { role: 'admin' });
// Soft-delete user
await client.admin.users.delete('profile-id');
// List user's files
const { data } = await client.admin.users.files('profile-id', { page: 1, page_size: 20 });
// Delete user's file
await client.admin.users.deleteFile('profile-id', 'file-id');Payment Management
// List project payments
const { data } = await client.admin.payments.list({ page: 1, page_size: 20 });
// Revenue summary
const { data } = await client.admin.payments.summary();
// data.summary.totalRevenue — total collected (amount + platform fee)
// data.summary.platformFees — platform fee total
// data.summary.netRevenue — what goes to the project owner
// data.summary.paymentCount
// Get specific payment
const { data } = await client.admin.payments.get('payment-id');CDN Management
// List all project files
const { data } = await client.admin.cdn.files({ page: 1, page_size: 20 });
// Storage usage stats
const { data } = await client.admin.cdn.storage();
// data.usage.totalSize, data.usage.fileCount
// data.byType — breakdown by MIME type
// Delete any file
await client.admin.cdn.delete('file-id');Managed (API Key-Based)
For server-to-server operations. API keys are created via the managed API or during organization genesis.
const managed = basebox.managed({ apiKey: 'bb_...' });Organization
// Get current org
const { data } = await managed.organization.get();
// Update org settings
await managed.organization.update({
name: 'My Org',
slug: 'my-org',
platform_fee_cents: 149, // R$1.49 platform fee
});
// Delete org (soft-delete)
await managed.organization.delete();Projects
// List projects
const { data } = await managed.projects.list({ page: 1, page_size: 20 });
// Create project
const { data } = await managed.projects.create({ name: 'My App', slug: 'my-app' });
// Get / update / delete
const { data } = await managed.projects.get('project-id');
await managed.projects.update('project-id', { name: 'Renamed' });
await managed.projects.delete('project-id');API Keys
import { ApiKeyLevel } from '@basebox/sdk';
// Create org-level key
const { data } = await managed.apiKeys.create({
name: 'Production Key',
level: 'organization',
});
// data.api_key.raw_key — only returned once, store it safely
// Create project-scoped key
const { data } = await managed.apiKeys.create({
name: 'Project Key',
level: 'project',
project_id: 'project-id',
expires_at: '2027-01-01T00:00:00Z',
});
// List all keys (hashes are never exposed)
const { data } = await managed.apiKeys.list();
// Revoke a key
await managed.apiKeys.revoke('key-id');Profiles (Per Project)
profiles() takes a projectId since profiles are scoped to projects.
const profiles = managed.profiles('project-id');
// List with filters
const { data } = await profiles.list({
page: 1,
page_size: 20,
search: 'john',
status: 'active',
});
// Get / ban / unban / delete / update role
const { data } = await profiles.get('profile-id');
await profiles.ban('profile-id', { reason: 'Abuse' });
await profiles.unban('profile-id');
await profiles.updateRole('profile-id', { role: 'admin' });
await profiles.delete('profile-id');Payments (Per Project)
Payments are created server-side. The profileId identifies which user is paying — amount is always set by your backend, never by the client.
const payments = managed.payments('project-id');
// Create a PIX payment for a user
const { data } = await payments.create({
profileId: 'profile-id',
amount_cents: 1500,
metadata: { plan: 'Pro' },
});
// data.payment — payment record
// data.pix.code — PIX copy-paste code
// data.pix.qr — QR code base64
// List payments
const { data } = await payments.list({ page: 1, page_size: 20 });
// Revenue summary
const { data } = await payments.summary();
// Get specific payment
const { data } = await payments.get('payment-id');Public (No Auth)
For initiating the OAuth flow before a user has a session.
const pub = basebox.public();
// org/project IDs come from the publicKey set in the constructor
const { user, sessionId, profile } = await pub.auth.oauth2.initiate('google');
// Opens a popup, completes OAuth, resolves with the sessionError Handling
All API errors return { error: string, code: string } with appropriate HTTP status codes.
const { data, error, status } = await client.payments.get('nonexistent');
if (error) {
console.log(error.value);
// { error: 'Payment not found', code: 'PAYMENT_NOT_FOUND' }
}Common error codes:
| Code | Status | Meaning |
|------|--------|---------|
| PROFILE_NOT_FOUND | 404 | Profile doesn't exist or was deleted |
| CROSS_PROJECT | 403 | Trying to access resources from another project |
| SELF_BAN | 400 | Cannot ban yourself |
| ALREADY_BANNED | 400 | User is already banned |
| CANNOT_BAN_OWNER | 403 | Cannot ban the project owner |
| CANNOT_ASSIGN_OWNER | 403 | Cannot assign the owner role |
| SLUG_TAKEN | 409 | Organization or project slug already exists |
| ORG_PROJECT_MISMATCH | 403 | Project doesn't belong to the API key's org |
Platform Fee Model
Payments use a configurable platform fee (default R$0.99):
- Customer pays:
amount_cents + platformFeeCents(e.g., R$15.99) - Project owner receives:
amount_cents(e.g., R$15.00) - Platform keeps:
platformFeeCents(e.g., R$0.99)
Configure via managed API:
await managed.organization.update({ platform_fee_cents: 149 }); // R$1.49