Skip to content

Superadmin BE - #10

Open
nikhilgosavi-josh wants to merge 1 commit into
feat/db_setupfrom
feat/superadmin-api
Open

Superadmin BE#10
nikhilgosavi-josh wants to merge 1 commit into
feat/db_setupfrom
feat/superadmin-api

Conversation

@nikhilgosavi-josh

Copy link
Copy Markdown
Collaborator

EZScreen Super Admin APIs — Request & Response
Base URL: /api/v1
Auth: Authorization: Bearer <access_token>
Refresh cookie: ezscreen_refresh (httpOnly, path=/api/v1/auth)

================================================================================
AUTH

  1. POST /api/v1/auth/login
    Auth: none

Request:
{
"email": "admin@ezscreen.io",
"password": "your-password"
}

Response 200:
{
"access_token": "eyJhbGciOiJIUzI1NiIs...",
"token_type": "bearer",
"expires_in": 3600,
"user": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"organization_id": null,
"role": "super_admin",
"email": "admin@ezscreen.io",
"first_name": "Platform",
"last_name": "Admin",
"phone": null,
"status": "active"
}
}
Also sets cookie: ezscreen_refresh

  1. POST /api/v1/auth/refresh
    Auth: refresh cookie only

Request: (no body)

Response 200:
{
"access_token": "eyJhbGciOiJIUzI1NiIs...",
"token_type": "bearer",
"expires_in": 3600
}
Also rotates cookie: ezscreen_refresh

  1. GET /api/v1/auth/me
    Auth: Bearer

Request: (no body)

Response 200:
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"organization_id": null,
"role": "super_admin",
"email": "admin@ezscreen.io",
"first_name": "Platform",
"last_name": "Admin",
"phone": null,
"status": "active"
}

  1. POST /api/v1/auth/logout
    Auth: Bearer

Request:
{}

Response 200:
{
"message": "Successfully logged out"
}
Also clears cookie: ezscreen_refresh

  1. GET /api/v1/auth/super-admin/check
    Auth: Bearer (super_admin only)

Request: (no body)

Response 200:
{
"message": "Super admin access confirmed"
}

================================================================================
ORGANIZATIONS

  1. GET /api/v1/organizations
    Auth: Bearer (super_admin)
    Query: page=1&limit=20&q=acme&status=active

Request: (no body)

Response 200:
[
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "Acme Corp",
"domain": "acme",
"logo_url": null,
"is_active": true,
"created_at": "2026-08-12T10:00:00+00:00",
"user_count": 3,
"job_count": 12,
"application_count": 45
}
]

  1. POST /api/v1/organizations
    Auth: Bearer (super_admin)

Request:
{
"name": "Acme Corp",
"domain": "acme",
"logo_url": "https://cdn.example.com/acme.png"
}

Response 201:
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "Acme Corp",
"domain": "acme",
"logo_url": "https://cdn.example.com/acme.png",
"is_active": true,
"created_at": "2026-08-12T10:00:00+00:00",
"user_count": 0,
"job_count": 0,
"application_count": 0
}

  1. GET /api/v1/organizations/{organization_id}
    Auth: Bearer (super_admin or org_admin for own org)

Request: (no body)

Response 200:
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "Acme Corp",
"domain": "acme",
"logo_url": null,
"is_active": true,
"created_at": "2026-08-12T10:00:00+00:00",
"user_count": 3,
"job_count": 12,
"application_count": 45
}

  1. PUT /api/v1/organizations/{organization_id}
    Auth: Bearer (super_admin or org_admin for own org)

Request (all fields optional):
{
"name": "Acme Corporation",
"domain": "acme-corp",
"logo_url": "https://cdn.example.com/new-logo.png",
"is_active": true
}

Response 200:
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "Acme Corporation",
"domain": "acme-corp",
"logo_url": "https://cdn.example.com/new-logo.png",
"is_active": true,
"created_at": "2026-08-12T10:00:00+00:00",
"user_count": 3,
"job_count": 12,
"application_count": 45
}

  1. DELETE /api/v1/organizations/{organization_id}
    Auth: Bearer (super_admin)

Request: (no body)

Response 200:
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"is_active": false,
"message": "Organization deactivated"
}

  1. GET /api/v1/organizations/{organization_id}/users
    Auth: Bearer (super_admin or org_admin for own org)

Request: (no body)

Response 200:
[
{
"id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"organization_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"role": "organization_admin",
"email": "admin@acme.com",
"first_name": "Jane",
"last_name": "Doe",
"phone": null,
"status": "active",
"temporary_password": null
}
]

  1. POST /api/v1/organizations/{organization_id}/users
    Auth: Bearer (super_admin or org_admin for own org)

Request:
{
"email": "hr@acme.com",
"password": "OptionalMin8Chars",
"first_name": "Jane",
"last_name": "Doe",
"phone": "+91-9876543210",
"role": "organization_admin"
}

Notes:

  • password is optional (min 8 if provided). If omitted, server auto-generates one.
  • role must be organization_admin or hr (default: organization_admin)

Response 201:
{
"id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"organization_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"role": "organization_admin",
"email": "hr@acme.com",
"first_name": "Jane",
"last_name": "Doe",
"phone": "+91-9876543210",
"status": "active",
"temporary_password": "xK9#mP2qL8nR"
}

Note: temporary_password is set only when password was auto-generated.

================================================================================
SYSTEM

  1. GET /api/v1/system/health
    Auth: none

Request: (no body)

Response 200:
{
"status": "healthy",
"service": "core-api",
"database_url_configured": true,
"jwt_configured": true
}

  1. GET /api/v1/system/health/detailed
    Auth: Bearer (super_admin)

Request: (no body)

Response 200:
{
"status": "healthy",
"service": "core-api",
"database": {
"name": "PostgreSQL",
"detail": "primary database",
"status": "healthy"
},
"api": {
"name": "API gateway",
"detail": "core-api local",
"status": "healthy"
},
"parse_workers": {
"name": "Parse workers (JD / resume)",
"detail": "Workers and Attendee bot are not deployed yet — shown as pending/healthy stub.",
"status": "healthy"
},
"screening_bot": {
"name": "Screening bot dispatch",
"detail": "Attendee integration not configured",
"status": "degraded"
},
"object_storage": {
"name": "Object storage (S3)",
"detail": "MinIO / S3 not required for platform ops API",
"status": "healthy"
},
"stats": {
"organizations": 5,
"users": 42,
"jobs": 18,
"applications": 120,
"uptime_seconds": 8642,
"jwt_ttl_minutes": 60
},
"recent_events": [
{
"time": "14:30",
"message": "Health check · 5 orgs · 42 users"
},
{
"time": "12:00",
"message": "Core API process started"
}
]
}

  1. GET /api/v1/system/settings
    Auth: Bearer (super_admin)

Request: (no body)

Response 200:
{
"platform_name": "EZScreen",
"support_email": "support@ezscreen.io",
"timezone": "Asia/Kolkata",
"extraction_model": "gemma-parse-v2",
"screening_model": "gemma-screen-v3",
"auto_retry_failed_jobs": true,
"require_mfa_super_admin": true,
"invite_expiry_days": 7
}

  1. PUT /api/v1/system/settings
    Auth: Bearer (super_admin)

Request (all fields optional):
{
"platform_name": "EZScreen",
"support_email": "support@ezscreen.io",
"timezone": "UTC",
"extraction_model": "gemma-parse-v2",
"screening_model": "gemma-screen-v3",
"auto_retry_failed_jobs": true,
"require_mfa_super_admin": false,
"invite_expiry_days": 14
}

Response 200:
{
"platform_name": "EZScreen",
"support_email": "support@ezscreen.io",
"timezone": "UTC",
"extraction_model": "gemma-parse-v2",
"screening_model": "gemma-screen-v3",
"auto_retry_failed_jobs": true,
"require_mfa_super_admin": false,
"invite_expiry_days": 14
}

@nikhilgosavi-josh
nikhilgosavi-josh changed the base branch from main to feat/db_setup August 14, 2026 06:04
Add organizations, user provisioning, system health/settings endpoints,
JWT access tokens with httpOnly refresh cookies and revocation table,
and merge refresh_token_revocations into the initial Alembic migration.

Co-authored-by: Cursor <cursoragent@cursor.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant