Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

API Routes - Services & Workflows

This document describes service discovery and workflow (AREA) management endpoints.

Base URL

http://localhost:8080

System Endpoints

GET /

Description: Root endpoint for the application server.

Authentication: Not required

Success Response (200 OK):

Nibba

Example:

curl http://localhost:8080/

GET /health

Description: Health check endpoint for monitoring and deployment. Returns the status of the server, database, and scheduler.

Authentication: Not required

Success Response (200 OK):

{
  "status": "healthy",
  "database": "connected",
  "scheduler": "enabled",
  "services": {
    "scheduler_interval": "1 minutes",
    "active_count": 8
  }
}

Response Fields:

FieldTypeDescription
statusstringOverall health status (“healthy” or “unhealthy”)
databasestringDatabase connection status (“connected” or error message)
schedulerstringScheduler status (“enabled”, “disabled”, or error message)
services.scheduler_intervalstringHow often the scheduler checks for workflow triggers
services.active_countintegerNumber of active services in the database

Error Response (503 Service Unavailable):

{
  "status": "unhealthy",
  "database": "error: connection refused",
  "scheduler": "enabled",
  "services": {}
}

Example:

curl http://localhost:8080/health

General Endpoints

GET /about.json

Description: Returns information about the server, client, and all available services with their actions and reactions.

Authentication: Not required

Success Response (200 OK):

{
  "client": {
    "host": "string"
  },
  "server": {
    "current_time": 1234567890,
    "services": [
      {
        "name": "string",
        "display_name": "string",
        "description": "string",
        "requires_oauth": boolean,
        "icon_url": "string | null",
        "actions": [
          {
            "name": "string",
            "description": "string"
          }
        ],
        "reactions": [
          {
            "name": "string",
            "description": "string"
          }
        ]
      }
    ]
  }
}

Response Fields:

FieldTypeDescription
client.hoststringIP address of the client making the request
server.current_timeintegerCurrent server time in Unix epoch timestamp format
server.servicesarrayList of all active services available on the server
server.services[].namestringInternal identifier for the service (e.g., “timer”, “gmail”)
server.services[].display_namestringHuman-readable service name (e.g., “Timer”, “Gmail”)
server.services[].descriptionstringBrief description of what the service does
server.services[].requires_oauthbooleanWhether the service requires OAuth2 authentication
server.services[].icon_urlstring/nullURL to the service icon image
server.services[].actionsarrayList of action triggers available for this service
server.services[].actions[].namestringInternal identifier for the action
server.services[].actions[].descriptionstringDescription of when this action triggers
server.services[].reactionsarrayList of reactions available for this service
server.services[].reactions[].namestringInternal identifier for the reaction
server.services[].reactions[].descriptionstringDescription of what this reaction does

Example Response:

{
  "client": {
    "host": "172.20.0.1"
  },
  "server": {
    "current_time": 1763556518,
    "services": [
      {
        "name": "timer",
        "display_name": "Timer",
        "description": "Time-based triggers and actions",
        "requires_oauth": false,
        "icon_url": null,
        "actions": [
          {
            "name": "time_matches",
            "description": "Triggers when current time matches HH:MM pattern"
          },
          {
            "name": "interval_elapsed",
            "description": "Triggers every X minutes"
          }
        ],
        "reactions": []
      }
    ]
  }
}

Example:

curl http://localhost:8080/about.json

Services Endpoints

GET /api/services

Description: List all available services with their actions and reactions.

Authentication: Required (Bearer token)

Request Headers:

Authorization: Bearer <token>

Success Response (200 OK):

{
  "services": [
    {
      "name": "string",
      "display_name": "string",
      "description": "string",
      "requires_oauth": boolean,
      "icon_url": "string | null",
      "actions": [
        {
          "id": integer,
          "name": "string",
          "display_name": "string",
          "description": "string",
          "config_schema": {
            "type": "object",
            "properties": {}
          }
        }
      ],
      "reactions": [
        {
          "id": integer,
          "name": "string",
          "display_name": "string",
          "description": "string",
          "config_schema": {
            "type": "object",
            "properties": {}
          }
        }
      ]
    }
  ]
}

Response Fields:

FieldTypeDescription
servicesarrayList of all active services
services[].namestringInternal identifier for the service
services[].display_namestringHuman-readable service name
services[].descriptionstringBrief description of the service
services[].requires_oauthbooleanWhether OAuth2 authentication is required
services[].icon_urlstring/nullURL to service icon
services[].actionsarrayAvailable action triggers for this service
services[].actions[].idintegerDatabase ID of the action
services[].actions[].namestringInternal action identifier
services[].actions[].display_namestringHuman-readable action name
services[].actions[].descriptionstringDescription of when this action triggers
services[].actions[].config_schemaobjectJSON schema for action configuration
services[].reactionsarrayAvailable reactions for this service
services[].reactions[].idintegerDatabase ID of the reaction
services[].reactions[].namestringInternal reaction identifier
services[].reactions[].display_namestringHuman-readable reaction name
services[].reactions[].descriptionstringDescription of what this reaction does
services[].reactions[].config_schemaobjectJSON schema for reaction configuration

Example Response:

{
  "services": [
    {
      "name": "timer",
      "display_name": "Timer",
      "description": "Time-based triggers and actions",
      "requires_oauth": false,
      "icon_url": null,
      "actions": [
        {
          "id": 1,
          "name": "time_matches",
          "display_name": "Time Matches",
          "description": "Triggers when current time matches HH:MM pattern",
          "config_schema": {
            "type": "object",
            "properties": {
              "time": {
                "type": "string",
                "pattern": "^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$",
                "description": "Time in HH:MM format (e.g., 14:30)"
              }
            },
            "required": ["time"]
          }
        }
      ],
      "reactions": []
    },
    {
      "name": "gmail",
      "display_name": "Gmail",
      "description": "Email detection and monitoring",
      "requires_oauth": true,
      "icon_url": null,
      "actions": [
        {
          "id": 3,
          "name": "email_received_from",
          "display_name": "Email Received From",
          "description": "Triggers when an email is received from a specific sender",
          "config_schema": {
            "type": "object",
            "properties": {
              "sender": {
                "type": "string",
                "description": "Email address of the sender"
              }
            },
            "required": ["sender"]
          }
        }
      ],
      "reactions": []
    }
  ]
}

Error Responses:

StatusErrorDescription
401Authorization token is missingNo Authorization header provided
401Invalid or expired tokenToken is invalid or has expired

Example:

curl -X GET http://localhost:8080/api/services \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

GET /api/connections

Description: List all available services that require OAuth and their connection status for the current user.

Authentication: Required (Bearer token)

Request Headers:

Authorization: Bearer <token>

Success Response (200 OK):

{
  "connections": [
    {
      "service_id": 2,
      "service_name": "gmail",
      "display_name": "Gmail",
      "description": "Email detection and monitoring",
      "is_connected": true,
      "connected_at": "2025-12-15T10:00:00Z"
    },
    {
      "service_id": 3,
      "service_name": "google_drive",
      "display_name": "Google Drive",
      "description": "Cloud storage integration",
      "is_connected": false,
      "connected_at": null
    }
  ]
}

Response Fields:

FieldTypeDescription
connectionsarrayList of all OAuth-enabled services with connection status
connections[].service_idintegerDatabase ID of the service
connections[].service_namestringInternal service identifier
connections[].display_namestringHuman-readable service name
connections[].descriptionstringBrief service description
connections[].is_connectedbooleanWhether user has connected this service
connections[].connected_atstring/nullISO 8601 timestamp of when service was connected, null if not connected

Error Responses:

StatusErrorDescription
401Authorization token is missingNo Authorization header provided
401Invalid or expired tokenToken is invalid or has expired

Example:

curl -X GET http://localhost:8080/api/connections \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

AREA (Workflow) Endpoints

POST /api/areas

Description: Create a new workflow (AREA) that links an Action to a REAction.

Authentication: Required (Bearer token)

Request Headers:

Authorization: Bearer <token>

Request Body:

{
  "name": "string",
  "action_id": integer,
  "reaction_id": integer,
  "action_config": {
    "key": "value"
  },
  "reaction_config": {
    "key": "value"
  },
  "is_active": boolean
}

Request Fields:

FieldTypeRequiredDescription
namestringYesName of the workflow
action_idintegerYesID of the action trigger
reaction_idintegerYesID of the reaction to execute
action_configobjectYesConfiguration for the action (varies by action type)
reaction_configobjectYesConfiguration for the reaction (varies by reaction type)
is_activebooleanNoWhether the workflow is active (default: true)

Success Response (201 Created):

{
  "message": "Workflow created successfully",
  "area": {
    "id": 1,
    "user_id": 1,
    "name": "Daily Email Reminder",
    "description": null,
    "action": {
      "id": 1,
      "name": "time_matches",
      "display_name": "Time Matches",
      "service": "Timer"
    },
    "reaction": {
      "id": 1,
      "name": "send_email",
      "display_name": "Send Email",
      "service": "Email"
    },
    "action_config": {
      "time": "14:00"
    },
    "reaction_config": {
      "to": "user@example.com",
      "subject": "Daily Reminder",
      "body": "This is your daily reminder!"
    },
    "is_active": true,
    "last_triggered": null,
    "created_at": "2025-12-15T10:30:00Z",
    "updated_at": "2025-12-15T10:30:00Z"
  }
}

Error Responses:

StatusErrorDescription
400Missing required field: <field>Required field not provided
401Authorization token is missingNo Authorization header provided
401Invalid or expired tokenToken is invalid or has expired
404Action not foundaction_id doesn’t exist
404Reaction not foundreaction_id doesn’t exist

Example:

curl -X POST http://localhost:8080/api/areas \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Daily Email Reminder",
    "action_id": 1,
    "reaction_id": 1,
    "action_config": {
      "time": "14:00"
    },
    "reaction_config": {
      "to": "user@example.com",
      "subject": "Daily Reminder",
      "body": "This is your daily reminder!"
    },
    "is_active": true
  }'

GET /api/areas

Description: List all workflows for the current authenticated user with pagination and filtering options.

Authentication: Required (Bearer token)

Request Headers:

Authorization: Bearer <token>

Query Parameters:

ParameterTypeRequiredDefaultDescription
pageintegerNo1Page number for pagination
per_pageintegerNo20Number of items per page
is_activestringNo-Filter by active status (“true” or “false”)

Success Response (200 OK):

{
  "areas": [
    {
      "id": 1,
      "user_id": 1,
      "name": "Daily Email Reminder",
      "description": null,
      "action": {
        "id": 1,
        "name": "time_matches",
        "display_name": "Time Matches",
        "service": "Timer"
      },
      "reaction": {
        "id": 1,
        "name": "send_email",
        "display_name": "Send Email",
        "service": "Email"
      },
      "action_config": {
        "time": "14:00"
      },
      "reaction_config": {
        "to": "user@example.com",
        "subject": "Daily Reminder",
        "body": "This is your daily reminder!"
      },
      "is_active": true,
      "last_triggered": "2025-12-15T14:00:05Z",
      "created_at": "2025-12-15T10:30:00Z",
      "updated_at": "2025-12-15T10:30:00Z"
    }
  ],
  "total": 1,
  "page": 1,
  "per_page": 20,
  "total_pages": 1
}

Response Fields:

FieldTypeDescription
areasarrayList of workflows for the current page
totalintegerTotal number of workflows
pageintegerCurrent page number
per_pageintegerNumber of items per page
total_pagesintegerTotal number of pages

Error Responses:

StatusErrorDescription
401Authorization token is missingNo Authorization header provided
401Invalid or expired tokenToken is invalid or has expired

Example:

# Get first page with default pagination
curl -X GET http://localhost:8080/api/areas \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

# Get active workflows only
curl -X GET "http://localhost:8080/api/areas?is_active=true" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

# Get page 2 with 10 items per page
curl -X GET "http://localhost:8080/api/areas?page=2&per_page=10" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

GET /api/areas/<area_id>

Description: Get a specific workflow by its ID.

Authentication: Required (Bearer token)

Request Headers:

Authorization: Bearer <token>

URL Parameters:

ParameterTypeRequiredDescription
area_idintegerYesID of the workflow to retrieve

Success Response (200 OK):

{
  "id": 1,
  "user_id": 1,
  "name": "Daily Email Reminder",
  "description": null,
  "action": {
    "id": 1,
    "name": "time_matches",
    "display_name": "Time Matches",
    "service": "Timer"
  },
  "reaction": {
    "id": 1,
    "name": "send_email",
    "display_name": "Send Email",
    "service": "Email"
  },
  "action_config": {
    "time": "14:00"
  },
  "reaction_config": {
    "to": "user@example.com",
    "subject": "Daily Reminder",
    "body": "This is your daily reminder!"
  },
  "is_active": true,
  "last_triggered": "2025-12-15T14:00:05Z",
  "created_at": "2025-12-15T10:30:00Z",
  "updated_at": "2025-12-15T10:30:00Z"
}

Error Responses:

StatusErrorDescription
401Authorization token is missingNo Authorization header provided
401Invalid or expired tokenToken is invalid or has expired
403Unauthorized access to this workflowUser doesn’t own this workflow
404Workflow not foundWorkflow with given ID doesn’t exist

Example:

curl -X GET http://localhost:8080/api/areas/1 \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

PUT /api/areas/<area_id>

Description: Update an existing workflow. Only the workflow owner can update it.

Authentication: Required (Bearer token)

Request Headers:

Authorization: Bearer <token>

URL Parameters:

ParameterTypeRequiredDescription
area_idintegerYesID of the workflow to update

Request Body:

{
  "name": "string",
  "action_config": {
    "key": "value"
  },
  "reaction_config": {
    "key": "value"
  },
  "is_active": boolean
}

Request Fields:

FieldTypeRequiredDescription
namestringNoNew name for the workflow
action_configobjectNoNew configuration for the action
reaction_configobjectNoNew configuration for the reaction
is_activebooleanNoWhether the workflow is active

Success Response (200 OK):

{
  "message": "Workflow updated successfully",
  "area": {
    "id": 1,
    "user_id": 1,
    "name": "Updated Email Reminder",
    "description": null,
    "action": {
      "id": 1,
      "name": "time_matches",
      "display_name": "Time Matches",
      "service": "Timer"
    },
    "reaction": {
      "id": 1,
      "name": "send_email",
      "display_name": "Send Email",
      "service": "Email"
    },
    "action_config": {
      "time": "15:00"
    },
    "reaction_config": {
      "to": "newemail@example.com",
      "subject": "Updated Reminder",
      "body": "This is an updated reminder!"
    },
    "is_active": true,
    "last_triggered": "2025-12-15T14:00:05Z",
    "created_at": "2025-12-15T10:30:00Z",
    "updated_at": "2025-12-15T15:45:00Z"
  }
}

Error Responses:

StatusErrorDescription
401Authorization token is missingNo Authorization header provided
401Invalid or expired tokenToken is invalid or has expired
403Unauthorized access to this workflowUser doesn’t own this workflow
404Workflow not foundWorkflow with given ID doesn’t exist

Example:

curl -X PUT http://localhost:8080/api/areas/1 \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Updated Email Reminder",
    "action_config": {
      "time": "15:00"
    },
    "reaction_config": {
      "to": "newemail@example.com",
      "subject": "Updated Reminder",
      "body": "This is an updated reminder!"
    }
  }'

PATCH /api/areas/<area_id>

Description: Partial update a workflow. Only updates the fields provided in the request body. Admins can update any workflow.

Authentication: Required (Bearer token)

Request Headers:

Authorization: Bearer <token>

URL Parameters:

ParameterTypeRequiredDescription
area_idintegerYesID of the workflow to update

Request Body:

{
  "name": "string",
  "is_active": boolean,
  "action_config": {
    "key": "value"
  },
  "reaction_config": {
    "key": "value"
  }
}

Request Fields:

FieldTypeRequiredDescription
namestringNoNew name for the workflow
is_activebooleanNoWhether the workflow is active
action_configobjectNoNew configuration for the action
reaction_configobjectNoNew configuration for the reaction

Success Response (200 OK):

{
  "message": "Workflow updated successfully",
  "area": {
    "id": 1,
    "user_id": 1,
    "name": "Updated Workflow Name",
    "action": {
      "id": 1,
      "name": "time_matches",
      "display_name": "Time Matches",
      "service": "Timer"
    },
    "reaction": {
      "id": 1,
      "name": "send_email",
      "display_name": "Send Email",
      "service": "Email"
    },
    "action_config": {
      "time": "14:00"
    },
    "reaction_config": {
      "to": "user@example.com",
      "subject": "Reminder",
      "body": "This is a reminder!"
    },
    "is_active": true,
    "last_triggered": null,
    "created_at": "2025-12-15T10:30:00Z",
    "updated_at": "2025-12-15T15:45:00Z"
  }
}

Error Responses:

StatusErrorDescription
401Authorization token is missingNo Authorization header provided
401Invalid or expired tokenToken is invalid or has expired
403Unauthorized access to this workflowUser doesn’t own this workflow (and is not admin)
404Workflow not foundWorkflow with given ID doesn’t exist

Example:

curl -X PATCH http://localhost:8080/api/areas/1 \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Updated Workflow Name",
    "is_active": false
  }'

PATCH /api/areas/<area_id>/toggle

Description: Toggle the active status of a workflow (enable/disable). Only the workflow owner can toggle it.

Authentication: Required (Bearer token)

Request Headers:

Authorization: Bearer <token>

URL Parameters:

ParameterTypeRequiredDescription
area_idintegerYesID of the workflow to toggle

Request Body: None required

Success Response (200 OK):

{
  "message": "Workflow enabled successfully",
  "area": {
    "id": 1,
    "user_id": 1,
    "name": "Daily Email Reminder",
    "description": null,
    "action": {
      "id": 1,
      "name": "time_matches",
      "display_name": "Time Matches",
      "service": "Timer"
    },
    "reaction": {
      "id": 1,
      "name": "send_email",
      "display_name": "Send Email",
      "service": "Email"
    },
    "action_config": {
      "time": "14:00"
    },
    "reaction_config": {
      "to": "user@example.com",
      "subject": "Daily Reminder",
      "body": "This is your daily reminder!"
    },
    "is_active": true,
    "last_triggered": "2025-12-15T14:00:05Z",
    "created_at": "2025-12-15T10:30:00Z",
    "updated_at": "2025-12-15T16:00:00Z"
  }
}

Response Fields:

FieldTypeDescription
messagestringSuccess message indicating if workflow was enabled or disabled
areaobjectComplete updated workflow object with toggled is_active status

Error Responses:

StatusErrorDescription
401Authorization token is missingNo Authorization header provided
401Invalid or expired tokenToken is invalid or has expired
403Unauthorized access to this workflowUser doesn’t own this workflow
404Workflow not foundWorkflow with given ID doesn’t exist

Example:

curl -X PATCH http://localhost:8080/api/areas/1/toggle \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

DELETE /api/areas/<area_id>

Description: Delete a workflow permanently. Only the workflow owner can delete it.

Authentication: Required (Bearer token)

Request Headers:

Authorization: Bearer <token>

URL Parameters:

ParameterTypeRequiredDescription
area_idintegerYesID of the workflow to delete

Request Body: None required

Success Response (200 OK):

{
  "message": "Workflow deleted successfully"
}

Error Responses:

StatusErrorDescription
401Authorization token is missingNo Authorization header provided
401Invalid or expired tokenToken is invalid or has expired
403Unauthorized access to this workflowUser doesn’t own this workflow
404Workflow not foundWorkflow with given ID doesn’t exist

Example:

curl -X DELETE http://localhost:8080/api/areas/1 \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

DELETE /api/areas/reset

Description: Delete all workflows for the current user. This also deletes all associated workflow logs.

Authentication: Required (Bearer token)

Request Headers:

Authorization: Bearer <token>

Request Body: None required

Success Response (200 OK):

{
  "message": "Successfully deleted 5 workflow(s)",
  "deleted_count": 5
}

Response Fields:

FieldTypeDescription
messagestringSuccess message with count of deleted workflows
deleted_countintegerNumber of workflows that were deleted

Error Responses:

StatusErrorDescription
401Authorization token is missingNo Authorization header provided
401Invalid or expired tokenToken is invalid or has expired

Example:

curl -X DELETE http://localhost:8080/api/areas/reset \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

GET /api/areas/<area_id>/logs

Description: Get execution logs for a specific workflow with pagination. Shows history of when the workflow was triggered and execution results.

Authentication: Required (Bearer token)

Request Headers:

Authorization: Bearer <token>

URL Parameters:

ParameterTypeRequiredDescription
area_idintegerYesID of the workflow to get logs for

Query Parameters:

ParameterTypeRequiredDefaultDescription
pageintegerNo1Page number for pagination
per_pageintegerNo50Number of log entries per page

Success Response (200 OK):

{
  "logs": [
    {
      "id": 1,
      "area_id": 1,
      "area_name": "Daily Email Reminder",
      "status": "success",
      "message": "Email sent successfully",
      "triggered_at": "2025-12-15T14:00:05Z",
      "execution_time_ms": 245
    },
    {
      "id": 2,
      "area_id": 1,
      "area_name": "Daily Email Reminder",
      "status": "failed",
      "message": "SMTP connection failed",
      "triggered_at": "2025-12-14T14:00:03Z",
      "execution_time_ms": 1520
    }
  ],
  "total": 2,
  "page": 1,
  "per_page": 50,
  "total_pages": 1
}

Response Fields:

FieldTypeDescription
logsarrayList of execution logs for the current page
logs[].idintegerLog entry ID
logs[].area_idintegerWorkflow ID
logs[].area_namestringName of the workflow
logs[].statusstringExecution status: “success”, “failed”, or “error”
logs[].messagestringExecution message or error description
logs[].triggered_atstringISO 8601 timestamp of when workflow was triggered
logs[].execution_time_msintegerExecution time in milliseconds
totalintegerTotal number of log entries
pageintegerCurrent page number
per_pageintegerNumber of items per page
total_pagesintegerTotal number of pages

Error Responses:

StatusErrorDescription
401Authorization token is missingNo Authorization header provided
401Invalid or expired tokenToken is invalid or has expired
403Unauthorized access to this workflowUser doesn’t own this workflow
404Workflow not foundWorkflow with given ID doesn’t exist

Example:

# Get first page with default pagination
curl -X GET http://localhost:8080/api/areas/1/logs \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

# Get page 2 with 20 logs per page
curl -X GET "http://localhost:8080/api/areas/1/logs?page=2&per_page=20" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

Admin Endpoints

GET /api/admin/users

Description: Get all users with their workflows. Only accessible by the admin user (user ID 1).

Authentication: Required (Bearer token - Admin only)

Request Headers:

Authorization: Bearer <token>

Success Response (200 OK):

{
  "users": [
    {
      "id": 1,
      "username": "admin",
      "email": "admin@example.com",
      "oauth_provider": null,
      "created_at": "2025-11-27T17:54:14.738713",
      "workflow_count": 3,
      "workflows": [
        {
          "id": 1,
          "name": "Daily Reminder",
          "action": {
            "id": 1,
            "name": "time_matches",
            "display_name": "Time Matches",
            "service": "Timer"
          },
          "reaction": {
            "id": 1,
            "name": "send_email",
            "display_name": "Send Email",
            "service": "Email"
          },
          "is_active": true,
          "last_triggered": "2025-12-15T14:00:05Z",
          "created_at": "2025-12-15T10:30:00Z"
        }
      ]
    },
    {
      "id": 2,
      "username": "alice",
      "email": "alice@example.com",
      "oauth_provider": "google",
      "created_at": "2025-12-01T09:00:00.000000",
      "workflow_count": 2,
      "workflows": []
    }
  ]
}

Response Fields:

FieldTypeDescription
usersarrayList of all users in the system
users[].idintegerUser database ID
users[].usernamestringUser’s username
users[].emailstringUser’s email address
users[].oauth_providerstring/nullOAuth provider if user registered via OAuth (“google”, “facebook”, or null)
users[].created_atstringISO 8601 timestamp of account creation
users[].workflow_countintegerNumber of workflows this user has
users[].workflowsarrayList of user’s workflows with full details

Error Responses:

StatusErrorDescription
401Authorization token is missingNo Authorization header provided
401Invalid or expired tokenToken is invalid or has expired
403Admin access requiredUser is not the admin

Example:

curl -X GET http://localhost:8080/api/admin/users \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."