Table of Contents
< All Topics

EDMO Agent Builder API

version: “1.0.0”
description: The Edmo Agent Builder API lets you manage AI voice/chat agents, tools, phone
numbers and call analytics used by the Edmo platform.

It is designed so that:
- **Non-technical stakeholders** can read the summaries and examples to understand
  what the system does.
- **Developers** can rely on the schemas and status codes to integrate with the
  backend services.

All endpoints in this spec are served from the `/api` prefix of the main Edmo
web application (see the `servers` section below).

servers:

  • url: https://agents.goedmo.com/api
    description: Production Edmo deployment
  • url: http://localhost:3000/api
    description: Local development

tags:

  • name: Auth
    description: Authentication and current-user endpoints.
  • name: Assistants
    description: Manage AI agents (assistants) used for calls and chat.
  • name: Tools
    description: Manage integrations and tools that assistants can call.
  • name: Phone Numbers
    description: Manage phone numbers that can be attached to assistants.
  • name: Analytics
    description: Read-only analytics and conversation insights.
  • name: Chat
    description: Simple text chat interface to an assistant.

x-tagGroups:

  • name: Authentication tags:
    • Auth
  • name: Assistants tags:
    • Assistants
  • name: Tools tags:
    • Tools
  • name: Phone Numbers tags:
    • Phone Numbers
  • name: Analytics tags:
    • Analytics
  • name: Chat tags:
    • Chat

components:
securitySchemes:
CookieAuth:
type: apiKey
in: cookie
name: auth-token
description: |
Authentication is handled via an auth-token HTTP-only cookie set by the
/auth/login endpoint.

    - In a **browser**, you typically call `/auth/login` once and the cookie will
      be stored and automatically sent on subsequent API requests.
    - In **API tools** (Postman, curl, etc.) you can manually capture the cookie
      from the `Set-Cookie` header or configure cookie handling.

    This spec models the cookie using `apiKey`-style auth for documentation
    purposes.

AnalyticsApiKey:
  type: apiKey
  in: header
  name: X-API-Key
  description: |
    API key used to access the public analytics endpoints.

    The value must match the `ANALYTICS_API_KEY` environment variable
    configured on the server. This is intended for external analytics
    dashboards and reporting tools, not for the main Edmo dashboard UI.

schemas:
# —————————-
# Generic / shared structures
# —————————-
ErrorResponse:
type: object
description: Standard error response envelope.
properties:
error:
type: string
description: Human-readable error message.
required:
– error
example:
error: Failed to load agents. Please try again.

PaginationMeta:
  type: object
  description: Optional paging metadata returned by some list endpoints.
  properties:
    total:
      type: integer
      example: 125
    limit:
      type: integer
      example: 50
    offset:
      type: integer
      example: 0

# ----------------------------
# Auth & user-related schemas
# ----------------------------
LoginRequest:
  type: object
  description: Credentials used to sign into the Edmo dashboard and API.
  properties:
    email:
      type: string
      format: email
      example: user@example.edu
    password:
      type: string
      format: password
      example: "strong-password-123"
  required:
    - email
    - password

LoginResponse:
  type: object
  description: Successful login response. The auth cookie is sent via `Set-Cookie` header.
  properties:
    message:
      type: string
      example: Login successful
    user:
      $ref: "#/components/schemas/User"
  required:
    - message
    - user

User:
  type: object
  description: Basic user information for the currently authenticated user.
  properties:
    id:
      type: string
      description: Internal user identifier.
    email:
      type: string
      format: email
    name:
      type: string
      nullable: true
    role:
      type: string
      description: High-level role for permissions (e.g., ADMIN, EDITOR, VIEWER).
    disabled:
      type: boolean
      description: Whether the account is disabled.
    permissions:
      type: object
      nullable: true
      additionalProperties:
        type: array
        items:
          type: string
      description: Fine-grained permission map used internally.
  required:
    - id
    - email
    - role
    - disabled

CurrentUserResponse:
  type: object
  description: Envelope used by `/auth/me` to return the current user.
  properties:
    user:
      $ref: "#/components/schemas/User"
  required:
    - user

# ----------------------------
# Assistant-related schemas
# ----------------------------
ModelConfig:
  type: object
  description: |
    Configuration for the underlying language model (OpenAI / Anthropic).

    For non-technical readers, you can think of this as picking which "brain"
    the agent uses and how creative it should be.
  properties:
    provider:
      type: string
      enum:
        - openai
        - anthropic
    model:
      type: string
      description: Model name from the chosen provider.
      example: gpt-4o
    temperature:
      type: number
      description: |
        Controls creativity. Lower values are more deterministic, higher values
        more creative and varied.
      minimum: 0
      maximum: 2
      example: 0.7
    maxTokens:
      type: integer
      description: Maximum number of tokens the model can generate for a response.
      example: 1024
  required:
    - provider
    - model

VoiceConfig:
  type: object
  description: Voice configuration for spoken responses when used in calls.
  properties:
    provider:
      type: string
      description: Voice provider identifier.
      enum:
        - 11labs
        - azure
        - cartesia
        - deepgram
        - playht
        - openai
        - edmo
    voiceId:
      type: string
      description: Voice identifier within the chosen provider.
      example: alloy

TranscriberConfig:
  type: object
  description: Speech-to-text configuration used to transcribe calls.
  properties:
    provider:
      type: string
      enum:
        - deepgram
        - assemblyai
        - whisper
    model:
      type: string
      nullable: true
      description: Optional model identifier, depending on the provider.

Assistant:
  type: object
  description: |
    A voice/chat agent configuration that defines how the assistant behaves and
    which model, voice and tools it uses.
  properties:
    id:
      type: string
      description: Assistant identifier.
    orgId:
      type: string
      description: Owning organization identifier.
    createdAt:
      type: string
      format: date-time
    updatedAt:
      type: string
      format: date-time
    name:
      type: string
      nullable: true
      description: Human-friendly assistant name shown in the dashboard.
    firstMessage:
      type: string
      nullable: true
      description: First message sent by the assistant when a call/chat starts.
    firstMessageMode:
      type: string
      nullable: true
      enum:
        - assistant-speaks-first
        - assistant-waits-for-user
        - assistant-speaks-first-with-model-generated-message
    model:
      $ref: "#/components/schemas/ModelConfig"
    voice:
      $ref: "#/components/schemas/VoiceConfig"
    transcriber:
      $ref: "#/components/schemas/TranscriberConfig"
    voicemailMessage:
      type: string
      nullable: true
    endCallMessage:
      type: string
      nullable: true
    endCallPhrases:
      type: array
      items:
        type: string
      nullable: true
    metadata:
      type: object
      nullable: true
      additionalProperties: true
    maxDurationSeconds:
      type: integer
      nullable: true
  required:
    - id
    - orgId
    - createdAt
    - updatedAt
    - model
    - voice
  example:
    id: asst_123
    orgId: org_abc
    createdAt: "2024-01-01T10:00:00.000Z"
    updatedAt: "2024-01-02T12:00:00.000Z"
    name: Enrollment Assistant
    firstMessage: "Hi, I'm here to help with your enrollment questions."
    firstMessageMode: assistant-speaks-first
    model:
      provider: openai
      model: gpt-4o
      temperature: 0.7
    voice:
      provider: openai
      voiceId: alloy
    maxDurationSeconds: 1800

CreateAssistantRequest:
  type: object
  description: Payload used to create a new assistant.
  properties:
    name:
      type: string
      description: Assistant display name.
    firstMessage:
      type: string
      nullable: true
    firstMessageMode:
      type: string
      nullable: true
      enum:
        - assistant-speaks-first
        - assistant-waits-for-user
        - assistant-speaks-first-with-model-generated-message
    model:
      $ref: "#/components/schemas/ModelConfig"
    voice:
      $ref: "#/components/schemas/VoiceConfig"
    transcriber:
      $ref: "#/components/schemas/TranscriberConfig"
    voicemailMessage:
      type: string
      nullable: true
    endCallMessage:
      type: string
      nullable: true
    endCallPhrases:
      type: array
      items:
        type: string
      nullable: true
    metadata:
      type: object
      nullable: true
      additionalProperties: true
    maxDurationSeconds:
      type: integer
      nullable: true
  required:
    - model
    - voice
  example:
    name: Enrollment Assistant
    firstMessage: "Hi, I'm your enrollment assistant. How can I help today?"
    firstMessageMode: assistant-speaks-first
    model:
      provider: openai
      model: gpt-4o
      temperature: 0.6
    voice:
      provider: openai
      voiceId: alloy
    maxDurationSeconds: 1800

UpdateAssistantRequest:
  allOf:
    - $ref: "#/components/schemas/CreateAssistantRequest"
  description: Partial update payload for an existing assistant. All fields are optional.

# ----------------------------
# Tool-related schemas
# ----------------------------
ToolMessage:
  type: object
  description: |
    Optional user-facing status messages spoken or displayed while a tool runs.
  properties:
    type:
      type: string
      enum:
        - request-start
        - request-complete
        - request-failed
        - request-response-delayed
    content:
      type: string
      description: Message text.
  required:
    - type
    - content

ToolParameter:
  type: object
  description: JSON Schema-style description of a single input field.
  properties:
    type:
      type: string
      enum:
        - string
        - number
        - boolean
        - object
        - array
    description:
      type: string
    enum:
      type: array
      items:
        type: string
    items:
      $ref: "#/components/schemas/ToolParameter"
    properties:
      type: object
      additionalProperties:
        $ref: "#/components/schemas/ToolParameter"
  required:
    - type

BaseTool:
  type: object
  description: Common metadata shared by all tool types.
  properties:
    id:
      type: string
    orgId:
      type: string
    createdAt:
      type: string
      format: date-time
    updatedAt:
      type: string
      format: date-time
    type:
      type: string
      enum:
        - function
        - apiRequest
        - mcp
    async:
      type: boolean
      nullable: true
    messages:
      type: array
      items:
        $ref: "#/components/schemas/ToolMessage"
      nullable: true

FunctionTool:
  allOf:
    - $ref: "#/components/schemas/BaseTool"
    - type: object
      properties:
        type:
          type: string
          enum:
            - function
        function:
          type: object
          properties:
            name:
              type: string
            description:
              type: string
            parameters:
              type: object
              properties:
                type:
                  type: string
                  enum:
                    - object
                properties:
                  type: object
                  additionalProperties:
                    $ref: "#/components/schemas/ToolParameter"
                required:
                  type: array
                  items:
                    type: string
          required:
            - name
            - description
            - parameters
        server:
          type: object
          nullable: true
          properties:
            url:
              type: string
              format: uri
            secret:
              type: string
              nullable: true
            timeoutSeconds:
              type: integer
              nullable: true

ApiRequestTool:
  allOf:
    - $ref: "#/components/schemas/BaseTool"
    - type: object
      properties:
        type:
          type: string
          enum:
            - apiRequest
        name:
          type: string
        description:
          type: string
          nullable: true
        method:
          type: string
          enum:
            - GET
            - POST
            - PUT
            - PATCH
            - DELETE
        url:
          type: string
        timeoutSeconds:
          type: integer
          nullable: true

McpTool:
  allOf:
    - $ref: "#/components/schemas/BaseTool"
    - type: object
      properties:
        type:
          type: string
          enum:
            - mcp
        name:
          type: string
          nullable: true
        metadata:
          type: object
          nullable: true
        server:
          type: object
          properties:
            url:
              type: string
              format: uri
          required:
            - url

Tool:
  oneOf:
    - $ref: "#/components/schemas/FunctionTool"
    - $ref: "#/components/schemas/ApiRequestTool"
    - $ref: "#/components/schemas/McpTool"
  discriminator:
    propertyName: type
  description: Union type covering all supported tool configurations.

ToolWithProvider:
  allOf:
    - $ref: "#/components/schemas/Tool"
    - type: object
      properties:
        provider:
          type: string
          nullable: true
          description: Optional source/provider of the tool (e.g., "salesforce", "workday").

CreateToolRequest:
  type: object
  description: Payload used to create a new tool.
  properties:
    provider:
      type: string
      nullable: true
      description: Optional logical provider label for grouping tools (stored locally).
    type:
      type: string
      enum:
        - function
        - apiRequest
        - mcp
    # Remaining properties mirror the underlying tool request bodies.
  required:
    - type
  example:
    provider: salesforce
    type: apiRequest

# ----------------------------
# Phone number schemas
# ----------------------------
PhoneNumber:
  type: object
  description: A phone number managed by the Edmo platform, optionally attached to an assistant.
  properties:
    id:
      type: string
    provider:
      type: string
      description: Source of the number (edmo, twilio, vonage, etc.).
    number:
      type: string
      description: E.164 formatted phone number.
      example: "+17865550123"
    assistantId:
      type: string
      nullable: true
  required:
    - id
    - provider
    - number

CreatePhoneNumberRequest:
  type: object
  description: |
    Request to create or import a phone number from a provider.

    This payload is flexible and mirrors the app's conditional logic for
    different telephony providers.
  properties:
    provider:
      type: string
      enum:
        - edmo
        - twilio
        - vonage
    assistantId:
      type: string
      nullable: true
    numberDesiredAreaCode:
      type: string
      description: Used for Edmo-provided numbers.
      example: "786"
    twilioPhoneNumber:
      type: string
      description: Existing Twilio number to import.
    twilioAccountSid:
      type: string
    twilioAuthToken:
      type: string
    vonageApiKey:
      type: string
    vonageApiSecret:
      type: string
    vonagePhoneNumber:
      type: string
  required:
    - provider
  example:
    provider: edmo
    numberDesiredAreaCode: "786"
    assistantId: asst_123

# ----------------------------
# Analytics schemas
# ----------------------------
AnalyticsConversationCustomer:
  type: object
  description: Basic customer information for an analytics conversation.
  properties:
    number:
      type: string
      nullable: true
      description: Customer phone number if available.

AnalyticsConversationAnalysis:
  type: object
  description: High-level analysis for a conversation.
  properties:
    summary:
      type: string
      nullable: true
      description: Short natural-language summary of the conversation.
    successEvaluation:
      type: string
      nullable: true
      description: Whether the conversation was considered successful (`\"true\"` or `\"false\"`).

AnalyticsConversation:
  type: object
  description: Analytics view of a single conversation/call.
  properties:
    id:
      type: string
      description: Conversation/call identifier.
    timestamp:
      type: string
      format: date-time
      description: When the conversation record was created.
    timestampFormatted:
      type: string
      nullable: true
      description: Human-friendly formatted timestamp.
    type:
      type: string
      description: Internal call type (e.g., webCall, inboundPhoneCall, outboundPhoneCall).
    channel:
      type: string
      enum:
        - web
        - phone
      description: High-level channel for the conversation.
    status:
      type: string
      description: Current status of the call (e.g., completed).
    endedReason:
      type: string
      nullable: true
      description: Reason the call ended (assistant-ended-call, customer-ended-call, etc.).
    durationSeconds:
      type: integer
      description: Total duration of the conversation in seconds.
    durationFormatted:
      type: string
      description: Human-readable duration (for example, "3m 20s").
    sentiment:
      type: string
      enum:
        - positive
        - neutral
        - negative
      description: Overall sentiment classification.
    resolution:
      type: string
      enum:
        - resolved
        - escalated
        - failed
      description: High-level outcome classification.
    assistantId:
      type: string
      nullable: true
      description: Assistant associated with this conversation, if any.
    phoneNumberId:
      type: string
      nullable: true
      description: Phone number associated with this conversation, if any.
    customer:
      $ref: "#/components/schemas/AnalyticsConversationCustomer"
    analysis:
      $ref: "#/components/schemas/AnalyticsConversationAnalysis"

AnalyticsMeta:
  type: object
  description: Metadata describing the analytics query that produced the results.
  properties:
    timeRangeDays:
      type: integer
      enum:
        - 7
        - 30
        - 90
      description: Number of days included in the analytics window.
    channel:
      type: string
      enum:
        - all
        - web
        - phone
      description: Channel filter applied to the analytics query.
    sentiment:
      type: string
      enum:
        - all
        - positive
        - neutral
        - negative
      description: Sentiment filter applied to the analytics query.
    resolution:
      type: string
      enum:
        - all
        - resolved
        - escalated
        - failed
      description: Resolution filter applied to the analytics query.
    assistantId:
      type: string
      nullable: true
      description: Assistant filter applied, if any.
    phoneNumberId:
      type: string
      nullable: true
      description: Phone number filter applied, if any.
    totalConversationsReturned:
      type: integer
      description: Number of conversations returned after filtering.

AnalyticsSummaryByChannel:
  type: object
  description: Conversation counts broken down by channel.
  properties:
    web:
      type: integer
      description: Number of web conversations.
    phone:
      type: integer
      description: Number of phone conversations.

AnalyticsSummaryKnowledgeGaps:
  type: object
  description: Knowledge gap statistics derived from the knowledge base.
  properties:
    totalGaps:
      type: integer
      description: Total number of pending knowledge gaps.
    highPriorityGaps:
      type: integer
      description: Number of high-priority pending knowledge gaps.

AnalyticsSummary:
  type: object
  description: Aggregated summary metrics for the analytics query.
  properties:
    totalConversations:
      type: integer
      description: Total number of conversations in the period.
    successfulConversations:
      type: integer
      description: Number of conversations considered resolved.
    failedConversations:
      type: integer
      description: Number of conversations that failed.
    successRatePercent:
      type: integer
      description: Percentage of conversations that were successful.
    totalDurationSeconds:
      type: integer
      description: Total duration of all conversations in seconds.
    avgDurationSeconds:
      type: integer
      description: Average duration per conversation in seconds.
    escalatedConversations:
      type: integer
      description: Number of escalated conversations.
    escalationRatePercent:
      type: integer
      description: Percentage of conversations that were escalated.
    timeSavedHours:
      type: integer
      description: Estimated hours saved compared to human-handled calls.
    byChannel:
      $ref: "#/components/schemas/AnalyticsSummaryByChannel"
    knowledgeGaps:
      $ref: "#/components/schemas/AnalyticsSummaryKnowledgeGaps"

AnalyticsResponse:
  type: object
  description: Response envelope for the analytics overview endpoint.
  properties:
    meta:
      $ref: "#/components/schemas/AnalyticsMeta"
    summary:
      $ref: "#/components/schemas/AnalyticsSummary"
    conversations:
      type: array
      items:
        $ref: "#/components/schemas/AnalyticsConversation"

ConversationDetailMessage:
  type: object
  description: Single message within a conversation transcript.
  properties:
    role:
      type: string
      enum:
        - user
        - assistant
      description: Who sent the message.
    message:
      type: string
      description: Message text content.

ConversationDetailResponse:
  type: object
  description: Full details for a single conversation.
  properties:
    id:
      type: string
      description: Conversation/call identifier.
    type:
      type: string
      description: Internal call type (e.g., webCall, inboundPhoneCall, outboundPhoneCall).
    channel:
      type: string
      enum:
        - web
        - phone
      description: High-level channel for the conversation.
    status:
      type: string
      description: Current status of the call.
    endedReason:
      type: string
      nullable: true
      description: Reason the call ended.
    startedAt:
      type: string
      format: date-time
      nullable: true
    endedAt:
      type: string
      format: date-time
      nullable: true
    createdAt:
      type: string
      format: date-time
    durationSeconds:
      type: integer
      description: Total duration of the conversation in seconds.
    durationFormatted:
      type: string
      description: Human-readable duration (for example, "3m 20s").
    sentiment:
      type: string
      enum:
        - positive
        - neutral
        - negative
    resolution:
      type: string
      enum:
        - resolved
        - escalated
        - failed
    customer:
      type: object
      description: Customer information.
      properties:
        number:
          type: string
          nullable: true
    assistant:
      type: object
      description: Assistant information.
      properties:
        id:
          type: string
          nullable: true
    analysis:
      $ref: "#/components/schemas/AnalyticsConversationAnalysis"
    transcript:
      type: string
      nullable: true
      description: Raw transcript text, if available.
    messages:
      type: array
      description: Parsed or structured messages making up the transcript.
      items:
        $ref: "#/components/schemas/ConversationDetailMessage"
    recordingUrl:
      type: string
      nullable: true
      description: URL of the mixed-call recording, if available.
    stereoRecordingUrl:
      type: string
      nullable: true
      description: URL of the stereo recording, if available.

# ----------------------------
# Chat schemas
# ----------------------------
ChatRequest:
  type: object
  description: Send a single message to an assistant over text chat.
  properties:
    assistantId:
      type: string
      description: Target assistant identifier.
    message:
      type: string
      description: End-user message text.
    previousChatId:
      type: string
      nullable: true
      description: Optional prior chat ID to maintain context across turns.
  required:
    - assistantId
    - message
  example:
    assistantId: asst_123
    message: "I have a question about my application status."

ChatResponse:
  type: object
  description: Assistant reply and chat metadata.
  properties:
    message:
      type: string
      description: Assistant's reply text.
    chatId:
      type: string
      description: Chat identifier to send as `previousChatId` on the next turn.
    cost:
      type: number
      nullable: true
      description: Optional cost information returned by the underlying provider.
    timestamp:
      type: string
      format: date-time
  required:
    - message
    - chatId
    - timestamp

paths:
# ============================
# Auth
# ============================
/auth/login:
post:
tags:
– Auth
summary: Log in and obtain an auth cookie
description: |
Authenticates a user with email and password.

    - On success, returns basic user information and sets an `auth-token`
      HTTP-only cookie used to authorize subsequent requests.
    - On failure, returns an error message and **does not** set the cookie.
  requestBody:
    required: true
    content:
      application/json:
        schema:
          $ref: "#/components/schemas/LoginRequest"
        examples:
          default:
            value:
              email: admin@example.edu
              password: "strong-password-123"
  responses:
    "200":
      description: Login successful. Auth cookie is set in the response.
      headers:
        Set-Cookie:
          description: Contains the `auth-token` cookie for subsequent requests.
          schema:
            type: string
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/LoginResponse"
    "400":
      description: Missing email or password.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
    "401":
      description: Invalid credentials or account not found.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
    "403":
      description: Account is disabled.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
    "500":
      description: Unexpected server error during login.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"

/auth/me:
get:
tags:
– Auth
summary: Get the currently authenticated user
description: |
Returns information about the currently logged-in user.

    This endpoint is useful for front-end apps to confirm who is signed in and
    what permissions they have. It relies on the `auth-token` cookie set by
    `/auth/login`.
  security:
    - CookieAuth: [ ]
  responses:
    "200":
      description: Authenticated user details.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/CurrentUserResponse"
    "401":
      description: No valid auth cookie was provided.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
    "404":
      description: The user referenced by the token no longer exists.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
    "403":
      description: The user account is disabled.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
    "500":
      description: Unexpected server error.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"

# ============================
# Assistants
# ============================
/assistants:
get:
tags:
– Assistants
summary: List assistants
description: |
Returns all assistants stored in the local database using the standard
assistant representation.

    Use this to populate dashboards or configuration UIs that show available
    agents.
  security:
    - CookieAuth: [ ]
  responses:
    "200":
      description: List of assistants.
      content:
        application/json:
          schema:
            type: array
            items:
              $ref: "#/components/schemas/Assistant"
    "401":
      description: Not authenticated or lacking permission to read agents.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
    "500":
      description: Error listing assistants.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"

post:
  tags:
    - Assistants
  summary: Create a new assistant
  description: |
    Creates a new assistant in the Edmo platform and persists a copy to
    the local database.

    Typical flow:
    1. Your app sends a configuration payload.
    2. Edmo provisions the assistant with the underlying AI/voice providers.
    3. Edmo stores the assistant locally for display and future management.
  security:
    - CookieAuth: [ ]
  requestBody:
    required: true
    content:
      application/json:
        schema:
          $ref: "#/components/schemas/CreateAssistantRequest"
  responses:
    "201":
      description: Assistant created successfully.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Assistant"
    "401":
      description: Not authenticated or lacking permission to create agents.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
    "500":
      description: Creation failed due to configuration or provider issues.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"

/assistants/{id}:
get:
tags:
– Assistants
summary: Get a specific assistant
description: |
Fetches a single assistant from the local database by either its external
provider ID or internal database ID.
security:
– CookieAuth: [ ]
parameters:
– name: id
in: path
required: true
description: Assistant identifier (external provider ID or local DB ID).
schema:
type: string
responses:
“200”:
description: Assistant details.
content:
application/json:
schema:
$ref: “#/components/schemas/Assistant”
“404”:
description: Assistant not found.
content:
application/json:
schema:
$ref: “#/components/schemas/ErrorResponse”
“401”:
description: Not authenticated or lacking permission to read agents.
content:
application/json:
schema:
$ref: “#/components/schemas/ErrorResponse”
“500”:
description: Error fetching assistant.
content:
application/json:
schema:
$ref: “#/components/schemas/ErrorResponse”

patch:
  tags:
    - Assistants
  summary: Update an assistant
  description: |
    Updates an existing assistant in both the external provider and the local
    database using a partial configuration payload.
  security:
    - CookieAuth: [ ]
  parameters:
    - name: id
      in: path
      required: true
      schema:
        type: string
      description: Assistant identifier (external provider ID or local DB ID).
  requestBody:
    required: true
    content:
      application/json:
        schema:
          $ref: "#/components/schemas/UpdateAssistantRequest"
  responses:
    "200":
      description: Assistant updated successfully.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Assistant"
    "404":
      description: Assistant not found.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
    "401":
      description: Not authenticated or lacking permission to update agents.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
    "500":
      description: Error updating assistant or communicating with the external provider.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"

delete:
  tags:
    - Assistants
  summary: Delete an assistant
  description: |
    Deletes an assistant from both the external provider and the local database.

    Use this when an agent is no longer needed.
  security:
    - CookieAuth: [ ]
  parameters:
    - name: id
      in: path
      required: true
      schema:
        type: string
      description: Assistant identifier (external provider ID or local DB ID).
  responses:
    "200":
      description: Assistant deleted successfully.
      content:
        application/json:
          schema:
            type: object
            properties:
              success:
                type: boolean
                example: true
    "404":
      description: Assistant not found.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
    "401":
      description: Not authenticated or lacking permission to delete agents.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
    "500":
      description: Error deleting assistant or communicating with the external provider.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"

# ============================
# Tools
# ============================
/tools:
get:
tags:
– Tools
summary: List tools
description: |
Returns all tools stored in the local database, converted into the
standard tool format and annotated with an optional provider field.

    Tools represent external integrations or custom functions that assistants
    can call (for example, CRM lookups or internal APIs).
  security:
    - CookieAuth: [ ]
  responses:
    "200":
      description: List of tools.
      content:
        application/json:
          schema:
            type: array
            items:
              $ref: "#/components/schemas/ToolWithProvider"
    "401":
      description: Not authenticated or lacking permission to read integrations.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
    "500":
      description: Error listing tools.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"

post:
  tags:
    - Tools
  summary: Create a new tool
  description: |
    Creates a new tool in the Edmo platform and stores it in the local
    database, optionally tagging it with a logical `provider` name.
  security:
    - CookieAuth: [ ]
  requestBody:
    required: true
    content:
      application/json:
        schema:
          $ref: "#/components/schemas/CreateToolRequest"
  responses:
    "201":
      description: Tool created successfully.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ToolWithProvider"
    "401":
      description: Not authenticated or lacking permission to create integrations.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
    "500":
      description: Error creating tool or communicating with the external provider.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"

/tools/{id}:
get:
tags:
– Tools
summary: Get a specific tool
description: |
Fetches a single tool from the local database by its external provider
ID or internal database ID.
security:
– CookieAuth: [ ]
parameters:
– name: id
in: path
required: true
schema:
type: string
description: Tool identifier (external provider ID or local DB ID).
responses:
“200”:
description: Tool details.
content:
application/json:
schema:
$ref: “#/components/schemas/ToolWithProvider”
“404”:
description: Tool not found.
content:
application/json:
schema:
$ref: “#/components/schemas/ErrorResponse”
“401”:
description: Not authenticated or lacking permission to read integrations.
content:
application/json:
schema:
$ref: “#/components/schemas/ErrorResponse”
“500”:
description: Error fetching tool.
content:
application/json:
schema:
$ref: “#/components/schemas/ErrorResponse”

patch:
  tags:
    - Tools
  summary: Update a tool
  description: |
    Updates a tool in the external provider and the local database. The incoming payload may
    include a `provider` field which is stored only locally.
  security:
    - CookieAuth: [ ]
  parameters:
    - name: id
      in: path
      required: true
      schema:
        type: string
      description: Tool identifier (external provider ID or local DB ID).
  requestBody:
    required: true
    content:
      application/json:
        schema:
          type: object
          description: Partial tool configuration matching the underlying tool API.
  responses:
    "200":
      description: Tool updated successfully.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ToolWithProvider"
    "404":
      description: Tool not found.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
    "401":
      description: Not authenticated or lacking permission to update integrations.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
    "500":
      description: Error updating tool or communicating with the external provider.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"

delete:
  tags:
    - Tools
  summary: Delete a tool
  description: |
    Deletes a tool from the external provider and removes its record from the local database.
  security:
    - CookieAuth: [ ]
  parameters:
    - name: id
      in: path
      required: true
      schema:
        type: string
      description: Tool identifier (external provider ID or local DB ID).
  responses:
    "200":
      description: Tool deleted successfully.
      content:
        application/json:
          schema:
            type: object
            properties:
              success:
                type: boolean
                example: true
    "404":
      description: Tool not found.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
    "401":
      description: Not authenticated or lacking permission to delete integrations.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
    "500":
      description: Error deleting tool or communicating with the external provider.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"

# ============================
# Phone numbers
# ============================
/phone-numbers:
get:
tags:
– Phone Numbers
summary: List phone numbers
description: |
Returns all phone numbers available via the telephony provider APIs. These
numbers may be Edmo-provided or imported from external providers like
Twilio or Vonage.
security:
– CookieAuth: [ ]
responses:
“200”:
description: List of phone numbers.
content:
application/json:
schema:
type: array
items:
$ref: “#/components/schemas/PhoneNumber”
“401”:
description: Not authenticated or lacking permission to read phone numbers.
content:
application/json:
schema:
$ref: “#/components/schemas/ErrorResponse”
“500”:
description: Error fetching phone numbers or communicating with telephony providers.
content:
application/json:
schema:
$ref: “#/components/schemas/ErrorResponse”

post:
  tags:
    - Phone Numbers
  summary: Create or import a phone number
  description: |
    Creates or imports a phone number from Edmo, Twilio or Vonage and optionally
    assigns it to an assistant.

    The exact fields required depend on the selected `provider`:
    - `edmo`: Edmo-provided number, requires `numberDesiredAreaCode`.
    - `twilio`: imports an existing Twilio number.
    - `vonage`: attaches a number using Vonage credentials.
  security:
    - CookieAuth: [ ]
  requestBody:
    required: true
    content:
      application/json:
        schema:
          $ref: "#/components/schemas/CreatePhoneNumberRequest"
  responses:
    "201":
      description: Phone number created or imported successfully.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/PhoneNumber"
    "401":
      description: Not authenticated or lacking permission to manage phone numbers.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
    "500":
      description: Error creating phone number or invalid credentials for the selected provider.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"

# ============================
# Analytics
# ============================
/analytics:
get:
tags:
– Analytics
summary: Get analytics overview
description: |
Provides analytics data for recent conversations with flexible filtering options.

    This endpoint is typically used by external dashboards to show conversation
    volumes, success rates, channel mix, and knowledge-gap statistics.
  security:
    - AnalyticsApiKey: [ ]
  parameters:
    - name: timeRangeDays
      in: query
      required: false
      description: Number of days to include in the analytics window.
      schema:
        type: integer
        enum:
          - 7
          - 30
          - 90
        default: 7
    - name: channel
      in: query
      required: false
      description: Filter conversations by channel.
      schema:
        type: string
        enum:
          - all
          - web
          - phone
        default: all
    - name: sentiment
      in: query
      required: false
      description: Filter conversations by overall sentiment.
      schema:
        type: string
        enum:
          - all
          - positive
          - neutral
          - negative
        default: all
    - name: resolution
      in: query
      required: false
      description: Filter conversations by high-level outcome.
      schema:
        type: string
        enum:
          - all
          - resolved
          - escalated
          - failed
        default: all
    - name: assistantId
      in: query
      required: false
      description: Filter conversations by assistant identifier.
      schema:
        type: string
    - name: phoneNumberId
      in: query
      required: false
      description: Filter conversations by phone number identifier.
      schema:
        type: string
  responses:
    "200":
      description: Analytics overview data.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/AnalyticsResponse"
    "401":
      description: Missing or invalid API key.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
    "403":
      description: API key is not permitted to access analytics.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
    "500":
      description: Error fetching analytics data.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"

/analytics/{conversationId}:
get:
tags:
– Analytics
summary: Get conversation details
description: |
Returns full details for a single conversation, including basic metadata,
analysis, transcript, messages, and recording URLs.

    Use this endpoint when a user drills into a specific conversation in an
    analytics dashboard.
  security:
    - AnalyticsApiKey: [ ]
  parameters:
    - name: conversationId
      in: path
      required: true
      description: Conversation or call identifier.
      schema:
        type: string
  responses:
    "200":
      description: Conversation details.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ConversationDetailResponse"
    "400":
      description: Invalid or missing conversationId.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
    "401":
      description: Missing or invalid API key.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
    "403":
      description: API key is not permitted to access analytics.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
    "404":
      description: Conversation not found.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
    "500":
      description: Error fetching conversation details.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"

# ============================
# Chat
# ============================
/chat:
post:
tags:
– Chat
summary: Send a chat message to an assistant
description: |
Sends a single text message to the specified assistant using a chat API
and returns the assistant’s reply.

    For multi-turn conversations:
    1. Call this endpoint and store the returned `chatId`.
    2. Include that `chatId` as `previousChatId` in the next request.
  security:
    - CookieAuth: [ ]
  requestBody:
    required: true
    content:
      application/json:
        schema:
          $ref: "#/components/schemas/ChatRequest"
  responses:
    "200":
      description: Assistant reply message.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ChatResponse"
    "400":
      description: Missing assistant ID or message.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
    "401":
      description: Not authenticated or lacking permission to use agents.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
    "500":
      description: Error calling the underlying chat API.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"

Talk to Connected University's Student Copilot