addEntity(), removeEntity(), listEntities()
Manage feature entities for per-seat and org-scoped billing
Entity Management
Entities represent scoped resources like seats, workspaces, or team members. Use these methods to manage entities for per-seat billing and entity-scoped usage tracking.
Flat API
owo.addEntity(params)
Add an entity to a customer. Validates against feature limits.
await owo.addEntity({
customer: string, // Customer ID or email
feature: string, // Feature slug (e.g., "seats")
entity: string, // Your entity ID
name?: string, // Display name
email?: string, // Contact email
metadata?: Record<string, unknown>, // Custom data
}): Promise<AddEntityResult>Returns:
interface AddEntityResult {
success: boolean;
entityId: string;
featureId: string;
count: number; // Current entity count
limit: number | null;
remaining: number | null;
}Throws: limit_exceeded if adding would exceed the plan limit.
owo.removeEntity(params)
Remove an entity and free up the slot.
await owo.removeEntity({
customer: string, // Customer ID or email
feature: string, // Feature slug
entity: string, // Entity ID to remove
}): Promise<RemoveEntityResult>Returns:
interface RemoveEntityResult {
success: boolean;
entityId: string;
count: number; // Remaining entity count
}owo.listEntities(params?)
List entities for a customer.
await owo.listEntities({
customer: string, // Customer ID or email
feature?: string, // Optional: filter by feature
}): Promise<ListEntitiesResult>Returns:
interface Entity {
id: string;
featureId: string;
name?: string;
email?: string;
metadata?: Record<string, unknown>;
status: "active" | "pending_removal";
createdAt: string;
}
interface ListEntitiesResult {
success: boolean;
entities: Entity[];
total: number;
}Examples
Add Team Members (Seats)
import { Owostack } from "@owostack/core";
const owo = new Owostack({ secretKey: process.env.OWOSTACK_API_KEY });
// Add team members - validates against seat limit
try {
await owo.addEntity({
customer: "org@acme.com",
feature: "seats",
entity: "user_123",
name: "John Doe",
email: "john@acme.com",
metadata: { role: "admin", department: "engineering" },
});
console.log("Seat added successfully");
} catch (err) {
if (err.code === "limit_exceeded") {
console.log("Seat limit reached - upgrade required");
}
}Check Seat Availability First
// Optional: Check if seat is available before adding
const check = await owo.check({
customer: "org@acme.com",
feature: "seats",
value: 1,
});
if (check.allowed) {
await owo.addEntity({
customer: "org@acme.com",
feature: "seats",
entity: "user_456",
name: "Jane Smith",
});
} else {
console.log("No seats available");
}List and Manage Seats
// List all active seats
const { entities } = await owo.listEntities({
customer: "org@acme.com",
feature: "seats",
});
console.log(`Active seats: ${entities.length}`);
entities.forEach((seat) => {
console.log(`- ${seat.name} (${seat.email})`);
});
// Remove a team member
await owo.removeEntity({
customer: "org@acme.com",
feature: "seats",
entity: "user_123",
});Multiple Entity Types
You can have different entity types per feature:
// Admin seats (different feature, different limit)
await owo.addEntity({
customer: "org@acme.com",
feature: "admin-seats",
entity: "admin_1",
name: "CEO",
});
// Regular member seats
await owo.addEntity({
customer: "org@acme.com",
feature: "member-seats",
entity: "member_1",
name: "Engineer",
});Entity-Scoped Usage
Once an entity is added, you can track and check usage scoped to that entity:
// Track AI credits for a specific seat
await owo.track({
customer: "org@acme.com",
feature: "ai-credits",
entity: "user_123", // Must exist!
value: 50,
});
// Check remaining credits for the seat
const status = await owo.check({
customer: "org@acme.com",
feature: "ai-credits",
entity: "user_123",
});
console.log(`${status.balance} credits remaining`);Important: Entities must be created with addEntity() before using them in check() or track(). Attempting to track a non-existent entity returns entity_not_found error.
Customer-Bound API
You can also call entity methods on the customer object:
const org = await owo.customer({ email: "org@acme.com" });
// Add entity via customer object
await org.addEntity({
feature: "seats",
entity: "user_123",
name: "John Doe",
});
// List entities
const { entities } = await org.listEntities({ feature: "seats" });
// Remove entity
await org.removeEntity({ feature: "seats", entity: "user_123" });Validation
- Entity uniqueness: Entity IDs are unique per feature. You can reuse the same ID across different features.
- Limit enforcement:
addEntity()validates synchronously against the feature limit. - Entity required:
check()andtrack()require entities to exist. Returnsentity_not_founderror otherwise.
Related
customer()- Create and manage customerscheck()- Check feature access (supports entity scope)track()- Track usage (supports entity scope)- Seat Pricing Guide - Complete walkthrough