Organizations API - arilonUK/iotagentmesh GitHub Wiki

Organizations API

The Organizations API provides comprehensive management of multi-tenant organizations within the IoT Agent Mesh platform. Organizations serve as the top-level container for users, IoT agents, and all related resources.

Overview

Organizations enable complete data isolation and access control in a multi-tenant environment. Each organization has its own:

  • User management and role-based access control
  • IoT agent registry and configurations
  • Telemetry data and analytics
  • Alert rules and notification settings
  • Integration configurations

Base Endpoint

/rest/v1/organizations

Authentication

All endpoints require JWT authentication with appropriate organization access permissions.

Required Headers:

Authorization: Bearer YOUR_JWT_TOKEN
apikey: YOUR_SUPABASE_ANON_KEY
Content-Type: application/json

Endpoints

List Organizations

Get all organizations accessible to the authenticated user.

GET /rest/v1/organizations

Query Parameters

Parameter Type Required Description
select string No Columns to return (default: *)
order string No Sort order (e.g., created_at.desc)
limit integer No Number of results (default: 20, max: 1000)
offset integer No Number of results to skip

Rate limits are per authenticated user per organization.

# Organizations API

The Organizations API provides comprehensive management of multi-tenant organizations within the IoT Agent Mesh platform. Organizations serve as the top-level container for users, IoT agents, and all related resources.

Overview

Organizations enable complete data isolation and access control in a multi-tenant environment. Each organization has its own:

  • User management and role-based access control
  • IoT agent registry and configurations
  • Telemetry data and analytics
  • Alert rules and notification settings
  • Integration configurations

Base Endpoint

/rest/v1/organizations

Authentication

All endpoints require JWT authentication with appropriate organization access permissions.

Required Headers:

Authorization: Bearer YOUR_JWT_TOKEN
apikey: YOUR_SUPABASE_ANON_KEY
Content-Type: application/json

Endpoints

List Organizations

Get all organizations accessible to the authenticated user.

GET /rest/v1/organizations

Query Parameters

Parameter Type Required Description
select string No Columns to return (default: *)
order string No Sort order (e.g., created_at.desc)
limit integer No Number of results (default: 20, max: 1000)
offset integer No Number of results to skip

Response

{
  "data": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "name": "Acme Corporation",
      "slug": "acme-corp",
      "description": "Industrial IoT solutions provider",
      "settings": {
        "timezone": "UTC",
        "date_format": "ISO8601",
        "alert_defaults": {
          "email_notifications": true,
          "sms_notifications": false
        }
      },
      "subscription": {
        "plan": "enterprise",
        "status": "active",
        "agent_limit": 10000,
        "user_limit": 100
      },
      "created_at": "2024-01-15T10:30:00Z",
      "updated_at": "2024-07-20T14:22:00Z"
    }
  ],
  "count": 1,
  "status": 200,
  "statusText": "OK"
}

Code Examples

JavaScript/TypeScript:

const { data: organizations, error } = await supabase
  .from('organizations')
  .select('*')
  .order('created_at', { ascending: false })

if (error) throw error
console.log('Organizations:', organizations)

Python:

response = supabase.table('organizations').select('*').order('created_at', desc=True).execute()
organizations = response.data

cURL:

curl -X GET \
  "https://your-project-id.supabase.co/rest/v1/organizations" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -H "apikey: YOUR_SUPABASE_ANON_KEY"

Get Organization

Retrieve details of a specific organization.

GET /rest/v1/organizations?id=eq.{organization_id}

Path Parameters

Parameter Type Required Description
organization_id UUID Yes Unique organization identifier

Response

{
  "data": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "name": "Acme Corporation",
      "slug": "acme-corp",
      "description": "Industrial IoT solutions provider",
      "settings": {
        "timezone": "America/New_York",
        "date_format": "MM/DD/YYYY",
        "alert_defaults": {
          "email_notifications": true,
          "sms_notifications": true,
          "webhook_notifications": false
        },
        "data_retention": {
          "telemetry_days": 365,
          "logs_days": 90,
          "alerts_days": 180
        }
      },
      "subscription": {
        "plan": "enterprise",
        "status": "active",
        "agent_limit": 10000,
        "user_limit": 100,
        "api_requests_limit": 1000000,
        "storage_limit_gb": 1024
      },
      "stats": {
        "total_agents": 245,
        "active_agents": 238,
        "total_users": 12,
        "total_alerts": 3
      },
      "created_at": "2024-01-15T10:30:00Z",
      "updated_at": "2024-07-20T14:22:00Z"
    }
  ]
}

Code Examples

JavaScript/TypeScript:

const { data: organization, error } = await supabase
  .from('organizations')
  .select('*')
  .eq('id', organizationId)
  .single()

if (error) throw error
console.log('Organization:', organization)

Create Organization

Create a new organization. Only authenticated users can create organizations.

POST /rest/v1/organizations

Request Body

{
  "name": "Tech Innovations Inc",
  "slug": "tech-innovations",
  "description": "Next-generation IoT solutions for smart cities",
  "settings": {
    "timezone": "UTC",
    "date_format": "ISO8601",
    "alert_defaults": {
      "email_notifications": true,
      "sms_notifications": false,
      "webhook_notifications": true
    },
    "data_retention": {
      "telemetry_days": 90,
      "logs_days": 30,
      "alerts_days": 60
    }
  }
}

Request Schema

Field Type Required Description
name string Yes Organization display name (2-100 chars)
slug string Yes URL-friendly identifier (2-50 chars, lowercase, hyphens)
description string No Organization description (max 500 chars)
settings object No Organization configuration settings
settings.timezone string No Default timezone (default: 'UTC')
settings.date_format string No Date format preference
settings.alert_defaults object No Default alert notification settings
settings.data_retention object No Data retention policies

Response

{
  "data": [
    {
      "id": "7f3e8b2a-1d45-4c8e-9a7b-2e5f8c9d0a1b",
      "name": "Tech Innovations Inc",
      "slug": "tech-innovations",
      "description": "Next-generation IoT solutions for smart cities",
      "settings": {
        "timezone": "UTC",
        "date_format": "ISO8601",
        "alert_defaults": {
          "email_notifications": true,
          "sms_notifications": false,
          "webhook_notifications": true
        },
        "data_retention": {
          "telemetry_days": 90,
          "logs_days": 30,
          "alerts_days": 60
        }
      },
      "subscription": {
        "plan": "starter",
        "status": "active",
        "agent_limit": 10,
        "user_limit": 5,
        "api_requests_limit": 10000,
        "storage_limit_gb": 1
      },
      "created_at": "2024-07-23T10:30:00Z",
      "updated_at": "2024-07-23T10:30:00Z"
    }
  ]
}

Code Examples

JavaScript/TypeScript:

const { data: organization, error } = await supabase
  .from('organizations')
  .insert({
    name: 'Tech Innovations Inc',
    slug: 'tech-innovations',
    description: 'Next-generation IoT solutions for smart cities',
    settings: {
      timezone: 'UTC',
      alert_defaults: {
        email_notifications: true,
        sms_notifications: false
      }
    }
  })
  .select()
  .single()

if (error) throw error
console.log('Created organization:', organization)

Python:

organization_data = {
    "name": "Tech Innovations Inc",
    "slug": "tech-innovations",
    "description": "Next-generation IoT solutions for smart cities",
    "settings": {
        "timezone": "UTC",
        "alert_defaults": {
            "email_notifications": True,
            "sms_notifications": False
        }
    }
}

response = supabase.table('organizations').insert(organization_data).execute()
organization = response.data[0]

Update Organization

Update an existing organization's details and settings.

PATCH /rest/v1/organizations?id=eq.{organization_id}

Request Body

{
  "name": "Acme Corporation Ltd",
  "description": "Updated description for the organization",
  "settings": {
    "timezone": "America/New_York",
    "alert_defaults": {
      "email_notifications": true,
      "sms_notifications": true,
      "webhook_notifications": true
    },
    "data_retention": {
      "telemetry_days": 180,
      "logs_days": 60
    }
  }
}

Response

{
  "data": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "name": "Acme Corporation Ltd",
      "slug": "acme-corp",
      "description": "Updated description for the organization",
      "settings": {
        "timezone": "America/New_York",
        "date_format": "MM/DD/YYYY",
        "alert_defaults": {
          "email_notifications": true,
          "sms_notifications": true,
          "webhook_notifications": true
        },
        "data_retention": {
          "telemetry_days": 180,
          "logs_days": 60,
          "alerts_days": 180
        }
      },
      "updated_at": "2024-07-23T15:45:00Z"
    }
  ]
}

Code Examples

JavaScript/TypeScript:

const { data: organization, error } = await supabase
  .from('organizations')
  .update({
    name: 'Acme Corporation Ltd',
    settings: {
      timezone: 'America/New_York',
      alert_defaults: {
        email_notifications: true,
        sms_notifications: true
      }
    }
  })
  .eq('id', organizationId)
  .select()
  .single()

if (error) throw error
console.log('Updated organization:', organization)

Delete Organization

Delete an organization and all associated data. This action is irreversible.

DELETE /rest/v1/organizations?id=eq.{organization_id}

Response

{
  "data": [],
  "status": 204,
  "statusText": "No Content"
}

⚠️ Warning

Deleting an organization will permanently remove:

  • All users and their profiles
  • All IoT agents and configurations
  • All telemetry data
  • All alerts and rules
  • All integration settings

Code Examples

JavaScript/TypeScript:

const { error } = await supabase
  .from('organizations')
  .delete()
  .eq('id', organizationId)

if (error) throw error
console.log('Organization deleted successfully')

Organization Statistics

Get Organization Statistics

Retrieve comprehensive statistics for an organization.

GET /functions/v1/organization-stats?organization_id={organization_id}

Response

{
  "organization_id": "550e8400-e29b-41d4-a716-446655440000",
  "stats": {
    "agents": {
      "total": 245,
      "active": 238,
      "inactive": 7,
      "by_type": {
        "sensor": 180,
        "gateway": 45,
        "controller": 20
      }
    },
    "users": {
      "total": 12,
      "active": 11,
      "by_role": {
        "admin": 2,
        "user": 8,
        "viewer": 2
      }
    },
    "telemetry": {
      "last_24h": 125000,
      "last_7d": 875000,
      "last_30d": 3750000
    },
    "alerts": {
      "active": 3,
      "acknowledged": 15,
      "resolved": 892
    },
    "storage": {
      "used_gb": 145.2,
      "limit_gb": 1024,
      "usage_percentage": 14.2
    }
  },
  "generated_at": "2024-07-23T16:00:00Z"
}

Error Responses

Common Error Codes

HTTP Code Error Code Description
400 VALIDATION_ERROR Invalid request parameters or body
401 UNAUTHORIZED Missing or invalid JWT token
403 FORBIDDEN Insufficient permissions for organization
404 NOT_FOUND Organization not found
409 CONFLICT Organization slug already exists
422 UNPROCESSABLE_ENTITY Invalid organization data
429 RATE_LIMIT_EXCEEDED Too many requests

Example Error Response

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Organization slug must be unique",
    "details": {
      "field": "slug",
      "value": "acme-corp",
      "reason": "Slug 'acme-corp' is already in use"
    }
  },
  "status": 409
}

Webhooks

Organizations can be configured to send webhook notifications for various events:

Available Events

  • organization.created - New organization created
  • organization.updated - Organization details updated
  • organization.deleted - Organization deleted
  • organization.user_added - New user added to organization
  • organization.user_removed - User removed from organization

Webhook Payload Example

{
  "event": "organization.updated",
  "timestamp": "2024-07-23T16:00:00Z",
  "organization_id": "550e8400-e29b-41d4-a716-446655440000",
  "data": {
    "organization": {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "name": "Acme Corporation Ltd",
      "slug": "acme-corp",
      "changes": {
        "name": {
          "old": "Acme Corporation",
          "new": "Acme Corporation Ltd"
        }
      }
    }
  }
}

Best Practices

Organization Design

  1. Naming Conventions: Use clear, descriptive names that reflect your business structure
  2. Slug Selection: Choose URL-friendly slugs that won't need to change
  3. Settings Configuration: Set appropriate defaults for your use case
  4. Data Retention: Configure retention policies based on compliance requirements

Performance Optimization

  1. Pagination: Always use pagination for large result sets
  2. Field Selection: Use the select parameter to limit returned fields
  3. Caching: Cache organization data that doesn't change frequently
  4. Batch Operations: Use bulk operations for multiple updates

Security Considerations

  1. Access Control: Verify user permissions before organization operations
  2. Data Validation: Always validate input data before processing
  3. Audit Logging: Enable audit logging for organization changes
  4. Regular Reviews: Periodically review organization access and settings

Related Resources

  • [Users API](API-Users.md) - Managing organization users and roles
  • [IoT Agents API](API-IoT-Agents.md) - Managing organization's IoT agents
  • [Authentication](API-Authentication.md) - Organization-scoped authentication
  • [Audit Logs API](API-Audit-Logs.md) - Organization activity tracking

Rate Limits

Operation Rate Limit Window
List Organizations 100 requests 1 minute
Get Organization 200 requests 1 minute
Create Organization 5 requests 1 minute
Update Organization 30 requests 1 minute
Delete Organization 2 requests 1 minute
Statistics 50 requests 1 minute

Rate limits are per authenticated user per organization.

⚠️ **GitHub.com Fallback** ⚠️