swagger: "2.0"
info:
  title: Ellipsend API
  description: |
    # ![Ellipsend Logo](https://ellipsend.com/Public/images/Ellipsend-LOGO-SOCIAL-GRADIENT.svg)

    API for managing statuses, labels, assignees, and contacts.

    ## Authentication
    All endpoints require OAuth2 authentication. Login through the /auth/login endpoint to get started.

    ## Rate Limits
    - Global rate limit: 100 requests per second
    - Auth endpoints (/auth/*): 10 requests per minute
    - All other endpoints follow the global rate limit
  version: 1.1.0
  x-logo:
    url: 'https://ellipsend.com/Public/images/ellipsend%20Final%20Logos_LOGOMARK-BLACK.svg'
    backgroundColor: '#FFFFFF'
    altText: 'Ellipsend Logo'

host: api.ellipsend.com
basePath: /v1
schemes:
  - https

tags:
  - name: Auth
    description: Authentication endpoints
  - name: Activity Type
    description: Manage activity types and input fields
  - name: Activity
    description: Manage user activities
  - name: Product
    description: Manage users products
  - name: Assignee
    description: Manage contact assignees
  - name: Contact
    description: Update contact information
  - name: Label
    description: Manage contact labels
  - name: Status
    description: Manage contact statuses
  - name: System
    description: System endpoints

x-tagGroups:
  - name: Authentication
    tags:
      - Auth
  - name: Activities
    tags:
      - Activity
      - Activity Type
  - name: Products
    tags:
      - Product
  - name: Contact Management
    tags:
      - Assignee
      - Contact
      - Label
      - Status
  - name: System
    tags:
      - System

securityDefinitions:
  OAuth2:
    type: oauth2
    description: >
      Use the OAuth 2.0 Client Credentials Grant flow to obtain an access token for API access.
      Provide your `client_id` and `client_secret` in the request body. All calls are rate limited to 100 calls per second except for authorization.
    flow: application
    tokenUrl: /v1/auth/token
    scopes:
      read: Grants read access.
      write: Grants write access.

security:
  - OAuth2:
      - read
      - write

paths:
  /v1/auth/register:
    post:
      tags:
        - Auth
      summary: Register a new API user. Rate limit to 10 calls per minute.
      description: Registers a new API user by creating an account and issuing a client ID and client secret for API access.
      consumes:
        - application/json
      produces:
        - application/json
      parameters:
        - in: body
          name: user
          required: true
          description: The email, password, and organization ID of the user to register.
          schema:
            type: object
            required:
              - email
              - password
            properties:
              email:
                type: string
                format: email
                description: The email address of the new user.
              password:
                type: string
                format: password
                description: The password for the new user.
              organization_id:
                type: string
                description: The organization ID to associate with the user (optional).
      responses:
        201:
          description: User registered successfully.
          schema:
            type: object
            properties:
              message:
                type: string
                example: "User registered successfully! Save these credentials securely as you will not be able to access them again. Treat them as sensitive access keys."
              client_id:
                type: string
                description: The generated client ID for API access.
              client_secret:
                type: string
                description: The generated client secret for API access.
        400:
          description: Email already registered or invalid input.
          schema:
            type: object
            properties:
              error:
                type: string
                example: "Email already registered"
        500:
          description: Server error.
          schema:
            type: object
            properties:
              error:
                type: string
                example: "Registration failed"

  /v1/auth/token:
    post:
      tags:
        - Auth
      summary: Obtain an OAuth2 access token. Tokens last 365 days you must refresh the token before that time for you application to continue to function. Rate limit to 10 calls per minute.
      description: Login using the client ID and client secret to receive an access token for API requests.
      consumes:
        - application/json
      produces:
        - application/json
      parameters:
        - in: body
          name: body
          required: true
          description: Client credentials for obtaining an access token.
          schema:
            type: object
            required:
              - client_id
              - client_secret
            properties:
              client_id:
                type: string
                description: Unique identifier for the client.
              client_secret:
                type: string
                description: Confidential key for the client.
      responses:
        200:
          description: Access token generated successfully.
          schema:
            type: object
            properties:
              access_token:
                type: string
                description: The JWT token to be used for subsequent API requests.
              token_type:
                type: string
                example: "Bearer"
                description: The type of the token issued.
              expires_in:
                type: integer
                example: 3600
                description: Time in seconds until the token expires.
        400:
          description: Missing or invalid parameters.
          schema:
            type: object
            properties:
              error:
                type: string
                example: "Client id and client secret are required"
        401:
          description: Invalid client credentials.
          schema:
            type: object
            properties:
              error:
                type: string
                example: "Invalid email or password"
        500:
          description: Internal server error.
          schema:
            type: object
            properties:
              error:
                type: string
                example: "Login failed"

  /v1/auth/refresh:
    post:
      tags:
        - Auth
      summary: Refresh an OAuth2 access token. Rate limit to 10 calls per minute.
      description: |
        Use the refresh token to obtain a new access token. The refresh token must be valid and unexpired.
      consumes:
        - application/json
      produces:
        - application/json
      parameters:
        - in: body
          name: body
          required: true
          description: The refresh token for generating a new access token.
          schema:
            type: object
            required:
              - refresh_token
            properties:
              refresh_token:
                type: string
                description: The refresh token issued during login.
      responses:
        200:
          description: New access token generated successfully.
          schema:
            type: object
            properties:
              access_token:
                type: string
                description: The new JWT token for API access.
              token_type:
                type: string
                example: "Bearer"
                description: The type of token issued.
              expires_in:
                type: integer
                example: 3600
                description: Time in seconds until the access token expires.
        400:
          description: Invalid or missing refresh token.
          schema:
            type: object
            properties:
              error:
                type: string
                example: "Invalid refresh token"
        401:
          description: Expired refresh token.
          schema:
            type: object
            properties:
              error:
                type: string
                example: "Refresh token has expired"
        404:
          description: User associated with the token does not exist.
          schema:
            type: object
            properties:
              error:
                type: string
                example: "User associated with the token does not exist"
        500:
          description: Server error.
          schema:
            type: object
            properties:
              error:
                type: string
                example: "Token refresh failed"

  /v1/company:
    get:
      summary: Get Company Name
      description: Get Basic information about the Company.
      tags: [ Company ]
      responses:
        200:
          description: A Company name and Id
          schema:
            type: array
            items:
              $ref: '#/definitions/Company'
        401:
          description: Unauthorized
        500:
          description: Server error

  /v1/activity-type:
    get:
      summary: List all activity types
      description: Retrieves all activity types for the current organization.
      tags: [Activity Type]
      responses:
        200:
          description: A list of activity types
          schema:
            type: array
            items:
              $ref: '#/definitions/ActivityType'
        401:
          description: Unauthorized
        500:
          description: Server error
  
  /v1/activity-type/{activity_type_id}:
    get:
      summary: Get a specific activity type
      description: Retrieves details of an activity type, including its fields.
      tags: [Activity Type]
      parameters:
        - in: path
          name: activity_type_id
          type: string
          required: true
          description: ID of the activity type to retrieve
      responses:
        200:
          description: The requested activity type
          schema:
            $ref: '#/definitions/ActivityType'
        401:
          description: Unauthorized
        404:
          description: Activity type not found
        500:
          description: Server error

  /v1/activity:
    post:
      summary: Create activity
      description: Creates a new activity entry.  Field keys may be the Field Name or ID.
      tags: [Activity]
      parameters:
        - in: body
          name: body
          required: true
          schema:
            type: object
            required:
              - token
              - activity_type_id
              - fields
            properties:
              token:
                type: string
                description: Ellipsend Token
              activity_type_id:
                type: int
                description: The activity type
              fields:
                type: object
                description: Key/value pairs of Fields for the activity
                example: [
                              {"FieldName": "Favorite color", "Value": "Blue"},
                              {"FieldName": "Product", "Value": 12},
                              {"FieldName": "Phone", "Value": "0000000000"},
                              {"FieldName": "Your Email", "Value": "hello@ellipsend.com"}
                          ]
      responses:
        201:
          description: activity created successfully
          schema:
            $ref: '#/definitions/Activity'
        400:
          description: Invalid input
          schema:
            type: object
            properties:
              error:
                type: string
                example: "Invalid input"
        404:
          description: Activity type not found
          schema:
            type: object
            properties:
              error:
                type: string
                example: "Activity type not found"
        500:
          description: Server error
          schema:
            type: object
            properties:
              error:
                type: string
                example: "Server error"

  /v1/activity/{activity_id}:
    get:
      summary: Get activity by id
      description: Retrieves the activity by it's id.
      tags: [Activity]
      produces:
        - application/json
      parameters:
        - in: path
          name: activity_id
          required: true
          type: string
          description: ID of the activity
      responses:
        200:
          description: activity retrieved successfully
          schema:
            type: array
            items:
              $ref: '#/definitions/Activity'
        404:
          description: Activity type not found
          schema:
            type: object
            properties:
              error:
                type: string
                example: "Activity type not found"
        500:
          description: Server error
          schema:
            type: object
            properties:
              error:
                type: string
                example: "Server error"

  /v1/product:
    get:
      tags:
        - Product
      summary: Get all products
      produces:
        - application/json
      responses:
        200:
          description: A list of products for the organization
          schema:
            type: array
            items:
              $ref: '#/definitions/Product'
        500:
          description: Server error

    post:
      tags:
        - Product
      summary: Create a new product
      consumes:
        - application/json
      produces:
        - application/json
      parameters:
        - in: body
          name: product
          required: true
          schema:
            type: object
            required:
              - product
              - price
            properties:
              product:
                type: string
              price:
                type: number
      responses:
        201:
          description: Product created
          schema:
            $ref: '#/definitions/Product'
        400:
          description: Missing required fields
        500:
          description: Server error

  /v1/product/{product_id}:
    get:
      tags:
        - Product
      summary: Get a specific product
      produces:
        - application/json
      parameters:
        - in: path
          name: product_id
          required: true
          type: string
      responses:
        200:
          description: Product retrieved
          schema:
            $ref: '#/definitions/Product'
        404:
          description: Product not found
        500:
          description: Server error

  /health:
    get:
      tags:
        - System
      summary: Health check endpoint
      produces:
        - application/json
      responses:
        200:
          description: System is healthy
          schema:
            type: object
            properties:
              status:
                type: string
                example: "healthy"
              database:
                type: string
                example: "connected"
              timestamp:
                type: string
                format: date-time
              version:
                type: string
                example: "1.0.0"
        500:
          description: System is unhealthy
          schema:
            type: object
            properties:
              status:
                type: string
                example: "unhealthy"
              error:
                type: string
              timestamp:
                type: string
                format: date-time

  /assignee:
    get:
      tags:
        - Assignee
      summary: Returns a list of assignees for the organization
      produces:
        - application/json
      responses:
        200:
          description: OK
          schema:
            type: array
            items:
              $ref: '#/definitions/Assignee'
        500:
          description: Server error

  /assignee/{assignee_id}:
    get:
      tags:
        - Assignee
      summary: Get a specific assignee
      produces:
        - application/json
      parameters:
        - in: path
          name: assignee_id
          required: true
          type: integer
      responses:
        200:
          description: OK
          schema:
            $ref: '#/definitions/Assignee'
        404:
          description: Assignee not found
        500:
          description: Server error

  /contact/{token}:
    put:
      tags:
        - Contact
      summary: Update contact information
      description: Update a contact's status, label, and/or assignee
      produces:
        - application/json
      parameters:
        - in: path
          name: token
          required: true
          type: string
          description: Ellipsend Token
        - in: body
          name: contact
          required: true
          description: The fields to update for the contact
          schema:
            $ref: '#/definitions/ContactUpdate'
      responses:
        200:
          description: Contact updated successfully
          schema:
            type: object
            properties:
              message:
                type: string
                example: "Contact updated successfully"
        404:
          description: Contact not found or access denied
          schema:
            type: object
            properties:
              error:
                type: string
                example: "Contact not found"
        400:
          description: Invalid input or no fields to update
          schema:
            type: object
            properties:
              error:
                type: string
                example: "Invalid input"
        500:
          description: Server error
          schema:
            type: object
            properties:
              error:
                type: string
                example: "Server error"

  /status:
    get:
      tags:
        - Status
      summary: Returns a list of statuses
      produces:
        - application/json
      responses:
        200:
          description: OK
          schema:
            type: array
            items:
              $ref: '#/definitions/Status'
        500:
          description: Server error
    post:
      tags:
        - Status
      summary: Create a new status
      produces:
        - application/json
      parameters:
        - in: body
          name: status
          required: true
          schema:
            type: object
            required:
              - status
            properties:
              status:
                type: string
      responses:
        201:
          description: Status created successfully
          schema:
            $ref: '#/definitions/Status'
        400:
          description: Invalid input
        500:
          description: Server error

  /status/{status_id}:
    get:
      tags:
        - Status
      summary: Get a specific status
      produces:
        - application/json
      parameters:
        - in: path
          name: status_id
          required: true
          type: integer
      responses:
        200:
          description: OK
          schema:
            $ref: '#/definitions/Status'
        404:
          description: Status not found
        500:
          description: Server error
    put:
      tags:
        - Status
      summary: Update a specific status
      produces:
        - application/json
      parameters:
        - in: path
          name: status_id
          required: true
          type: integer
        - in: body
          name: status
          required: true
          schema:
            type: object
            required:
              - status
            properties:
              status:
                type: string
      responses:
        200:
          description: Status updated successfully
          schema:
            $ref: '#/definitions/Status'
        404:
          description: Status not found
        500:
          description: Server error
    delete:
      tags:
        - Status
      summary: Delete a specific status
      produces:
        - application/json
      parameters:
        - in: path
          name: status_id
          required: true
          type: integer
      responses:
        200:
          description: Status deleted successfully
          schema:
            type: object
            properties:
              message:
                type: string
        404:
          description: Status not found
        500:
          description: Server error

  /label:
    get:
      tags:
        - Label
      summary: Returns a list of labels
      produces:
        - application/json
      responses:
        200:
          description: OK
          schema:
            type: array
            items:
              $ref: '#/definitions/Label'
        500:
          description: Server error
    post:
      tags:
        - Label
      summary: Create a new label
      produces:
        - application/json
      parameters:
        - in: body
          name: label
          required: true
          schema:
            type: object
            required:
              - label
            properties:
              label:
                type: string
      responses:
        201:
          description: Label created successfully
          schema:
            $ref: '#/definitions/Label'
        400:
          description: Invalid input
        500:
          description: Server error

  /label/{label_id}:
    get:
      tags:
        - Label
      summary: Get a specific label
      produces:
        - application/json
      parameters:
        - in: path
          name: label_id
          required: true
          type: integer
      responses:
        200:
          description: OK
          schema:
            $ref: '#/definitions/Label'
        404:
          description: Label not found
        500:
          description: Server error
    put:
      tags:
        - Label
      summary: Update a specific label
      produces:
        - application/json
      parameters:
        - in: path
          name: label_id
          required: true
          type: integer
        - in: body
          name: label
          required: true
          schema:
            type: object
            required:
              - label
            properties:
              label:
                type: string
      responses:
        200:
          description: Label updated successfully
          schema:
            $ref: '#/definitions/Label'
        404:
          description: Label not found
        500:
          description: Server error
    delete:
      tags:
        - Label
      summary: Delete a specific label
      produces:
        - application/json
      parameters:
        - in: path
          name: label_id
          required: true
          type: integer
      responses:
        200:
          description: Label deleted successfully
          schema:
            type: object
            properties:
              message:
                type: string
        404:
          description: Label not found
        500:
          description: Server error

  /:
    get:
      tags:
        - System
      summary: Redirect to API documentation
      responses:
        302:
          description: Redirect to /v1/docs

  /v1:
    get:
      tags:
        - System
      summary: Redirect to API documentation
      responses:
        302:
          description: Redirect to /v1/docs

  /docs:
    get:
      tags:
        - System
      summary: Redirect to API documentation
      responses:
        302:
          description: Redirect to /v1/docs

  /v1/docs:
    get:
      tags:
        - System
      summary: Serve API documentation UI
      responses:
        200:
          description: HTML documentation page

definitions:
  ActivityType:
    type: object
    properties:
      id:
        type: integer
      name:
        type: string
      sort_order:
        type: integer
      created_on:
        type: string
        format: date-time
      last_updated_on:
        type: string
        format: date-time
      created_by_user_id:
        type: integer
      last_updated_by_user_id:
        type: integer
      activity_id:
        type: integer
      activity_name:
        type: string
      fields:
        type: array
        items:
          $ref: '#/definitions/ActivityTypeField'
    example:
      id: 99
      name: "Campaign Type"
      sort_order: 10
      created_on: "2024-01-15T10:00:00Z"
      last_updated_on: "2024-03-01T09:30:00Z"
      created_by_user_id: 123
      last_updated_by_user_id: 456
      activity_id: 456
      activity_name: "Marketing Campaign"
      fields:
        - id: 1
          field_name: "Location"
          field_type: "Text"
          default_value: ""
          required: 1
          options: "{'Label': 'Location', 'Input Tag': 'text-location', 'Placeholder': ''}"
        - id: 2
          field_name: "Capacity"
          field_type: "Number"
          default_value: "50"
          required: 0
          options: "{'Label': 'Capacity', 'Input Tag': 'number-capacity', 'Placeholder': ''}"

  ActivityTypeField:
    type: object
    properties:
      id:
        type: integer
      field_name:
        type: string
      field_type:
        type: string
      default_value:
        type: string
      required:
        type: integer
      options:
        type: array
        items:
          type: string
    example:
      id: 1234
      field_name: "Capacity"
      field_type: "Number"
      default_value: "100"
      required: 1
      options: {"Label": "Your Field Label", "Input Tag": "text-your-field-label", "Placeholder": ""}

  Activity:
    type: object
    description: activity entry. Field keys may be the Field Name or ID.
    properties:
      id:
        type: integer
        description: ID of the activity entry
        example: 123
      contact_id:
        type: integer
        description: Meta ID of the contact
        example: 456
      activity_type_name:
        type: string
        description: Name of the activity type
        example: "Purchased"
      post_id:
        type: string
        description: ID of Post
        example: "123_533553"
      automation_name:
        type: string
        description: Name of the Automation
        example: "Comment Reply Join Now"
      campaign_name:
        type: string
        description: Name of the Campaign
        example: "March Madness"
      fields:
        type: object
        description: Key/Value pairs of fields for the activity
        example: {"Location": "New York", "Capacity": 100}
      last_updated_on:
        type: string
        format: date-time
        description: Last updated timestamp
      created_on:
        type: string
        format: date-time
        description: Created timestamp

  Product:
    type: object
    properties:
      id:
        type: integer
      name:
        type: string
      price:
        type: number
      created_on:
        type: string
        format: date-time
      last_updated_on:
        type: string
        format: date-time
    example:
      id: 123
      name: "Sample Product"
      price: 19.99
      created_on: "2024-01-15T10:00:00Z"
      last_updated_on: "2024-02-01T09:30:00Z"

  Assignee:
    type: object
    properties:
      id:
        type: integer
      assignee:
        type: string

  Label:
    type: object
    properties:
      id:
        type: integer
      label:
        type: string

  Status:
    type: object
    properties:
      id:
        type: integer
      status:
        type: string

  ContactUpdate:
    type: object
    properties:
      status_id:
        type: integer
        description: |
          ID of the status to assign.
          Use GET /status to retrieve available status IDs.
      label_id:
        type: integer
        description: |
          ID of the label to assign.
          Use GET /label to retrieve available label IDs.
      assignee_id:
        type: integer
        description: |
          ID of the assignee to assign.
          Must be a valid user ID in your organization.
          Use GET /assignee to retrieve available assignee IDs.
      first_name:
        type: string
        description: Contact's first name
      last_name:
        type: string
        description: Contact's last name
      email:
        type: string
        format: email
        description: Contact's email address
      phone:
        type: string
        description: Contact's phone number
      address:
        type: string
        description: Contact's physical address
      city:
        type: string
        description: Contact's city
      state:
        type: string
        description: Contact's state/province
      postal_code:
        type: string
        description: Contact's postal/zip code
      country:
        type: string
        description: Contact's country
      company:
        type: string
        description: Contact's company name
      title:
        type: string
        description: Contact's job title
      custom_fields:
        type: object
        description: Any additional custom fields defined for the contact
        additionalProperties: true
    example:
      status_id: 1
      label_id: 2
      assignee_id: 3
      first_name: "John"
      last_name: "Doe"
      email: "john.doe@example.com"
      phone: "+1-555-123-4567"
      company: "Acme Corp"
      title: "Sales Manager"
      custom_fields:
        lead_source: "Website"
        last_interaction: "2024-01-15"

  Contact:
    type: object
    properties:
      id:
        type: integer
      status_id:
        type: integer
      label_id:
        type: integer
      assignee_id:
        type: integer

  Company:
    type: object
    properties:
      id:
        type: integer
      name:
        type: string

# x-tagGroups:
#   - name: Contact Management
#     tags:
#       - Assignee
#       - Contact
#       - Label
#       - Status
#   - name: System
#     tags:
#       - Auth
#       - System
#   - name: Activities
#     tags:
#       - Activity
#       - Activity Type

responses:
  UnauthorizedError:
    description: Authentication is required to access this resource
    schema:
      type: object
      properties:
        error:
          type: string
          example: "Unauthorized"
        message:
          type: string
          example: "Authentication is required to access this resource"

  ForbiddenError:
    description: You do not have permission to access this resource
    schema:
      type: object
      properties:
        error:
          type: string
          example: "Forbidden"
        message:
          type: string
          example: "You do not have permission to access this resource"

  TooManyRequestsError:
    description: Rate limit exceeded
    schema:
      type: object
      properties:
        error:
          type: string
          example: "Too Many Requests"
        message:
          type: string
          example: "You have exceeded the allowed rate limit. Please try again later."
