Managing Organizations
Team access, roles, environments, tiers, and governance
An organization is the top-level container for all AgentPost resources. This guide covers organization management: team roles, member invitations, environment setup, tier limits, governance policies, and audit logging.
Organization structure
Organization (AcmeCo)
|-- Owner: [email protected]
|-- Admin: [email protected]
|-- Member: [email protected]
|
|-- Environments
| |-- Production (default)
| +-- Staging
|
|-- API Keys
|-- Inboxes, Messages, Threads...
|-- Webhook Endpoints
|-- Custom Domains
|-- Governance Policies
|-- Audit LogRoles
| Role | Permissions |
|---|---|
| Owner | Full access. Can transfer ownership, manage billing, delete the org. Only one owner per org. |
| Admin | Full resource access. Can manage members, environments, domains, and governance policies. Cannot transfer ownership or delete the org. |
| Member | Standard resource access. Can use inboxes, send/read messages, manage labels. Cannot manage members or governance. |
Inviting members
import AgentPost from 'agentpost';
const client = new AgentPost({ apiKey: 'ap_sk_...' });
// Invite a new team member
const invitation = await client.org.invite({
email: '[email protected]',
role: 'member',
});
console.log(`Invitation sent: ${invitation.id}`);
console.log(`Status: ${invitation.status}`); // "pending"from agentpost import AgentPost
client = AgentPost(api_key="ap_sk_...")
invitation = client.org.invite(
email="[email protected]",
role="member",
)
print(f"Invitation sent: {invitation.id}")curl -X POST https://api.agent-post.dev/api/v1/org/invitations \
-H "Authorization: Bearer $AGENTPOST_API_KEY" \
-H "Content-Type: application/json" \
-d '{"email": "[email protected]", "role": "member"}'Managing invitations
// List pending invitations
const invitations = await client.org.listInvitations();
// Revoke an invitation
await client.org.revokeInvitation('inv_abc123');invitations = client.org.list_invitations()
client.org.revoke_invitation("inv_abc123")# List invitations
curl "https://api.agent-post.dev/api/v1/org/invitations" \
-H "Authorization: Bearer $AGENTPOST_API_KEY"
# Revoke an invitation
curl -X POST "https://api.agent-post.dev/api/v1/org/invitations/inv_abc123/revoke" \
-H "Authorization: Bearer $AGENTPOST_API_KEY"Managing members
// List all members
const members = await client.org.listMembers();
// Update a member's role
await client.org.updateMember('mem_abc123', { role: 'admin' });
// Remove a member
await client.org.removeMember('mem_abc123');members = client.org.list_members()
client.org.update_member("mem_abc123", role="admin")
client.org.remove_member("mem_abc123")# List members
curl "https://api.agent-post.dev/api/v1/org/members" \
-H "Authorization: Bearer $AGENTPOST_API_KEY"
# Update role
curl -X PATCH "https://api.agent-post.dev/api/v1/org/members/mem_abc123" \
-H "Authorization: Bearer $AGENTPOST_API_KEY" \
-H "Content-Type: application/json" \
-d '{"role": "admin"}'
# Remove member
curl -X DELETE "https://api.agent-post.dev/api/v1/org/members/mem_abc123" \
-H "Authorization: Bearer $AGENTPOST_API_KEY"Tier limits
Organizations have tiers that determine resource limits:
| Resource | Free | Starter | Team | Enterprise |
|---|---|---|---|---|
| Inboxes | 5 | 25 | 100 | Unlimited |
| Domains | 1 | 5 | 20 | Unlimited |
| Members | 2 | 10 | 50 | Unlimited |
| Environments | 1 | 3 | 10 | Unlimited |
| Webhook endpoints | 3 | 10 | 50 | Unlimited |
| Daily sends | 100 | 1,000 | 10,000 | Unlimited |
Checking usage
const usage = await client.org.getUsage();
console.log(`Inboxes: ${usage.inboxes.used}/${usage.inboxes.limit}`);
console.log(`Daily sends: ${usage.daily_sends.used}/${usage.daily_sends.limit}`);
console.log(`Members: ${usage.members.used}/${usage.members.limit}`);usage = client.org.get_usage()
print(f"Inboxes: {usage.inboxes['used']}/{usage.inboxes['limit']}")
print(f"Daily sends: {usage.daily_sends['used']}/{usage.daily_sends['limit']}")curl "https://api.agent-post.dev/api/v1/org/usage" \
-H "Authorization: Bearer $AGENTPOST_API_KEY"Requesting a tier upgrade
await client.org.requestUpgrade({
requested_tier: 'team',
reason: 'Growing team needs more inboxes and higher send limits',
});client.org.request_upgrade(
requested_tier="team",
reason="Growing team needs more inboxes and higher send limits",
)curl -X POST "https://api.agent-post.dev/api/v1/org/upgrade-request" \
-H "Authorization: Bearer $AGENTPOST_API_KEY" \
-H "Content-Type: application/json" \
-d '{"requested_tier": "team", "reason": "Growing team needs more inboxes"}'Governance policies
Configure organization-wide policies for security and compliance:
// Get current policies
const policies = await client.org.getPolicies();
// Update policies
await client.org.updatePolicies({
require_mfa: true,
session_timeout_hours: 8,
api_key_max_age_days: 90,
ip_allowlist_enabled: true,
});policies = client.org.get_policies()
client.org.update_policies(
require_mfa=True,
session_timeout_hours=8,
api_key_max_age_days=90,
ip_allowlist_enabled=True,
)# Get policies
curl "https://api.agent-post.dev/api/v1/org/policies" \
-H "Authorization: Bearer $AGENTPOST_API_KEY"
# Update policies
curl -X PATCH "https://api.agent-post.dev/api/v1/org/policies" \
-H "Authorization: Bearer $AGENTPOST_API_KEY" \
-H "Content-Type: application/json" \
-d '{"require_mfa": true, "session_timeout_hours": 8}'IP allowlist
Restrict API access to specific IP addresses or CIDR ranges:
// Add an IP to the allowlist
await client.org.addIpAllowlistEntry({
cidr: '203.0.113.0/24',
description: 'Office network',
});
// List allowlist entries
const entries = await client.org.listIpAllowlist();client.org.add_ip_allowlist_entry(
cidr="203.0.113.0/24",
description="Office network",
)
entries = client.org.list_ip_allowlist()curl -X POST "https://api.agent-post.dev/api/v1/org/ip-allowlist" \
-H "Authorization: Bearer $AGENTPOST_API_KEY" \
-H "Content-Type: application/json" \
-d '{"cidr": "203.0.113.0/24", "description": "Office network"}'Audit log
View a record of all actions performed within your organization:
const auditLog = await client.org.getAuditLog({
limit: 50,
});
for (const entry of auditLog.data) {
console.log(`${entry.created_at} | ${entry.actor_email} | ${entry.action} | ${entry.resource_type}`);
}audit_log = client.org.get_audit_log(limit=50)
for entry in audit_log.data:
print(f"{entry.created_at} | {entry.actor_email} | {entry.action}")curl "https://api.agent-post.dev/api/v1/org/audit-log?limit=50" \
-H "Authorization: Bearer $AGENTPOST_API_KEY"Ownership transfer
Transfer organization ownership to another member:
// Initiate transfer
const transfer = await client.org.transferOwnership({
new_owner_id: 'mem_bob123',
});
// The new owner must accept the transfer
// (done through the web console or API)transfer = client.org.transfer_ownership(
new_owner_id="mem_bob123",
)curl -X POST "https://api.agent-post.dev/api/v1/org/transfer-ownership" \
-H "Authorization: Bearer $AGENTPOST_API_KEY" \
-H "Content-Type: application/json" \
-d '{"new_owner_id": "mem_bob123"}'SSO configuration
Configure Single Sign-On for enterprise organizations:
// Set up OIDC SSO
const ssoConfig = await client.org.createSsoConfig({
protocol: 'oidc',
issuer_url: 'https://auth.acmeco.com',
client_id: 'your-client-id',
client_secret: 'your-client-secret',
});
// Activate SSO
await client.org.activateSso(ssoConfig.id);sso_config = client.org.create_sso_config(
protocol="oidc",
issuer_url="https://auth.acmeco.com",
client_id="your-client-id",
client_secret="your-client-secret",
)
client.org.activate_sso(sso_config.id)# Create OIDC SSO configuration
curl -X POST "https://api.agent-post.dev/api/v1/org/sso" \
-H "Authorization: Bearer $AGENTPOST_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"protocol": "oidc",
"issuer_url": "https://auth.acmeco.com",
"client_id": "your-client-id",
"client_secret": "your-client-secret"
}'SSO supports both OIDC and SAML protocols. When SSO enforcement is enabled, all members (except the owner) must authenticate through the configured identity provider. JIT (Just-In-Time) provisioning automatically creates accounts for new SSO users.
Tips
- The owner role cannot be shared -- there is exactly one owner per organization
- Invitation counts include pending invitations when checking tier limits
- Governance policies auto-create a row on first read (lazy initialization)
- IP allowlist is integrated into auth middleware -- it checks after org resolution
- Audit log retention varies by tier: 7 days (free) to 730 days (enterprise)
- Ownership transfer is atomic: the old owner becomes an admin in the same transaction
- SSO enforcement has an owner bypass for emergency access