swagger: '2.0'
info:
  title: AppDynamics IoT Device API
  description: API for IoT devices to communicate with AppDynamics
  version: "4.5.0.0"
host: iot-col.eum-appdynamics.com
schemes:
  - https
basePath: /eumcollector/iot/v1
paths:
  /application/{appKey}/beacons:
    post:
      summary: Post beacons
      description: |
        Post beacons from your IoT device to this endpoint.
        This accepts Content-Encoding gzip and identity.
        If Content-Encoding header is not specified, identity is assumed.
      consumes:
        - application/json
      parameters:
        - name: appKey
          in: path
          description: Application Key for your AppDynamics App
          required: true
          type: string
        - name: beacons
          in: body
          description: |
            The beacons for all devices being reported. A single beacon can hold upto 200 events of
            each event type (CustomEvent, NetworkRequestEvent, and ErrorEvent). Often you will have 
            only one beacon if your IoT device can directly transmit to the AppDynamics endpoint.
            You would have multiple beacons if you have more than 200 events of an event type from a single device, 
            or more than one device sending beacons via an intermediate hub.
          required: true
          schema:
            type: array
            minItems: 1
            maxItems: 200
            items:
              $ref: '#/definitions/Beacon'
      responses:
        202: # ACCEPTED
          description: |
            Beacons queued for ingestion.  This does not mean that the beacon is valid.
        400: # BAD REQUEST
          description: |
            The request was malformed.  Likely due to an invalid Content-Encoding.
        402: # PAYMENT REQUIRED
          description: |
            The IoT license associated with this app key is expired
        403: # FORBIDDEN
          description: |
            This application is disabled or non-existent, this agent should stop sending beacons.
            Your IoT device may want to check the endpoint periodically, since you may have re-enabled
            the application through your AppDynamics Controller
        429: # TOO MANY REQUESTS
          description: |
            This application is over its license limit, stop sending beacons until the next calendar month.

  /application/{appKey}/validate-beacons:
    post:
      summary: Validate beacons
      description: |
        Post beacons for validation.  These beacons do not get ingested.  This endpoint
        should be used only for debug purposes during development.
      consumes:
        - application/json
      parameters:
        - name: appKey
          in: path
          description: Application Key for your AppDynamics App
          required: true
          type: string
        - name: beacons
          in: body
          description: The beacons to validate
          required: true
          schema:
            type: array
            minItems: 1
            maxItems: 200
            items:
              $ref: '#/definitions/Beacon'
      responses:
        200: # OK
          description: |
            Beacons are valid
        400: # BAD REQUEST
          description: |
            The request was malformed and could not be read.
            This could be from an invalid encoding or unreadable json.
            The reason will be in the response body.
          schema:
            $ref: '#/definitions/ValidationError'
        402: # PAYMENT REQUIRED
          description: |
            The IoT license associated with this app key is expired
        403: # FORBIDDEN
          description: |
            This application is disabled or non-existent, you should stop sending beacons.
        422: # UNPROCESSABLE ENTITY
          description: |
            One or more beacons are invalid
          schema:
            $ref: '#/definitions/ValidationError'
        429: # TOO MANY REQUESTS
          description: |
            This endpoint is rate limited. You can call it at least once per minute per app key,
            but any more and you may get this response code.

  /application/{appKey}/enabled:
    get:
      summary: Check if AppKey is enabled
      description: |
        Checks if the supplied AppKey is valid and enabled. This can be used by apps after being
        disabled to easily check if the agent should get re-enabled.
      consumes:
        - application/json
      parameters:
        - name: appKey
          in: path
          description: Application Key for your AppDynamics App
          required: true
          type: string
      responses:
        200: # OK
          description: |
            App key is enabled
        403: # FORBIDDEN
          description: |
            This application is disabled or non-existent, you should stop sending beacons.

definitions:
  Beacon:
    description: |
      All of the event data from one device.  At least one event should be
      populated in one of the event arrays, if all of those arrays are empty,
      this beacon is meaningless.
    type: object
    required:
      - deviceInfo
    properties:
      deviceInfo:
        $ref: '#/definitions/DeviceInfo'
      versionInfo:
        $ref: '#/definitions/VersionInfo'
      customEvents:
        description: |
          The custom events from this device.
        type: array
        minItems: 0
        maxItems: 200
        items:
          $ref: '#/definitions/CustomEvent'
      networkRequestEvents:
        description: |
          The network request events from this device.
        type: array
        minItems: 0
        maxItems: 200
        items:
          $ref: '#/definitions/NetworkRequestEvent'
      errorEvents:
        description: |
          The error events from this device.
        type: array
        minItems: 0
        maxItems: 200
        items:
          $ref: '#/definitions/ErrorEvent'

  DeviceInfo:
    type: object
    required:
      - deviceType
      - deviceId
    properties:
      deviceName:
        type: string
        description: |
          Human readable name of the device. This is not required and does not need to be unique.
          Valid Examples: "Thermostat in room 1302", "Vehicle 1532312"
        maxLength: 80
      deviceType:
        type: string
        description: |
          Type of the device.
          Cannot contain the pipe character '|'.
          Valid Examples: "Thermostat", "Wind Turbine", "Camera"
        maxLength: 24
        minLength: 1
      deviceId:
        type: string
        description: |
          Unique ID for this device.
          Valid Examples: "1877837d-66a9-4bfb-b6e8-6dd4ac62ea38", "CA 5UMH719"
        maxLength: 128
        minLength: 1

  VersionInfo:
    type: object
    properties:
      hardwareVersion:
        type: string
        description: |
          The hardware version of this device.
          Valid Example: "Board Rev. 13A"
        maxLength: 80
        minLength: 1
      firmwareVersion:
        type: string
        description: |
          The firmware version of this device.
          Valid Example: "123.5.31"
        maxLength: 80
        minLength: 1
      softwareVersion:
        type: string
        description: |
          The software version of the embedded application being monitored.
          Valid Example: "9.1.3"
        maxLength: 80
        minLength: 1
      operatingSystemVersion:
        type: string
        description: |
          The operating system version of this device.
          Valid Example: "Linux 13.4"
        maxLength: 80
        minLength: 1

  Event:
    description: |
      The base definition that all event objects inherit from.  This includes
      a timestamp, duration, and some additional typed property maps.
    type: object
    required:
      - timestamp
    additionalProperties: true
    properties:
      timestamp:
        type: integer
        format: int64
        description: The start time of this event in milliseconds epoch time.
      duration:
        type: integer
        format: int64
        minimum: 0
        description: |
          The duration of this event in milliseconds.
          If unpopulated, the duration is assumed to be 0.
      stringProperties:
        description: |
          A map of the string properties of this event.
          There cannot be more than 16 string properties per event.
          Entry keys have a max length of 24 characters.
          Entry values have a max length of 128 characters.
          Entry keys cannot contain the pipe character '|'.
          Valid Examples: { "username": "john.doe" }
        type: object
      longProperties:
        description: |
          A map of the long properties of this event.
          There cannot be more than 16 long properties per event.
          Entry keys have a max length of 24 characters.
          Entry keys cannot contain the pipe character '|'.
          Valid Examples: { "buttonId": 123 }
        type: object
      booleanProperties:
        description: |
          A map of the boolean properties of this event.
          There cannot be more than 16 boolean properties per event.
          Entry keys have a max length of 24 characters.
          Entry keys cannot contain the pipe character '|'.
          Valid Examples: { "error": false }
        type: object
      doubleProperties:
        description: |
          A map of the double properties of this event.
          There cannot be more than 16 double properties per event.
          Entry keys have a max length of 24 characters.
          Entry keys cannot contain the pipe character '|'.
          Valid Examples: { "Fahrenheit": 98.2 }
        type: object
      datetimeProperties:
        description: |
          A map of the datetime properties of this event, in millisecond epoch time.
          There cannot be more than 16 datetime properties per event.
          Entry keys have a max length of 24 characters.
          Entry keys cannot contain the pipe character '|'.
          Valid Examples: { "bootTime": 1487119625012 }
        type: object

  CustomEvent:
    description: |
      An event that doesn't fit into the other event definitions. All of the
      analytics tools will still be available, but some widgets will not be
      automatically generated for these events. In addition to the 'timestamp'
      property, you must specify the 'eventType' property,
      which describes the type of this event for the 'deviceType', and the
      'eventSummary' property, which is a human readable summary of the event.
    allOf:
      - $ref: '#/definitions/Event'
      - additionalProperties: true
        required:
          - eventType
          - eventSummary
        properties:
          eventType:
            type: string
            maxLength: 24
            minLength: 1
            description: |
              The type of this event.
              Cannot contain the pipe character '|'.
              Valid Examples: "Temperature Reading", "Motion Detected",
          eventSummary:
            type: string
            maxLength: 64
            minLength: 1
            description: |
              The summary of this event. Appears in the Activity stream.
              Should be human readable and informative to someone
              reading through events looking for a specific one.
              Valid Examples: "Door closed", "Light turned on", "Switch to gear 4"

  NetworkRequestEvent:
    description: |
      A network request event.  Should always populate timestamp, duration,
      url, and either networkError or statusCode.  Other fields are included
      for ease of use.
    allOf:
      - $ref: '#/definitions/Event'
      - additionalProperties: true
        required:
          - url
        properties:
          url:
            type: string
            minLength: 1
            maxLength: 2048
            description: |
              The URL of the request.  Must be a valid URL.
              Valid Example: "http://www.appdynamics.com"
          statusCode:
            type: integer
            description: |
              The HTTP response status code returned.  Should be defined
              if the 'networkError' is not defined.
              Valid Example: 200
          networkError:
            type: string
            minLength: 1
            maxLength: 1024
            description: |
              If a network error occured (such as socket timeout), which caused
              the network request to fail without response/status.
              Valid Example: "Connection Interrupted", "ERR_NAME_NOT_RESOLVED"
          requestContentLength:
            type: integer
            format: int64
            minimum: 0
            description: |
              The length in bytes of the http request body.
              Valid Example: 5432
          responseContentLength:
            type: integer
            format: int64
            minimum: 0
            description: |
              The length in bytes of the http response body.
              Valid Example: 6123
          responseHeaders:
            type: object
            description: |
              HTTP response headers provided as a list of {"key": ["values"]} pairs. To enable BT correlation,
              add the headers {"ADRUM": "isAjax:true"} and {"ADRUM_1": "isMobile:true"} to your HTTP request.
              Attach all the response headers which will include BT headers in case your backend application
              is instrumented with AppDynamics APM Agent.

  ErrorEvent:
    description: |
      An error event.  Use this event to report errors and issues that
      you want to monitor.  The only required fields are 'timestamp'
      and 'name'.  AppDynamics will group errors based on many
      heuristics, but if you only include the minimum of 'name', then
      that is all that we can group on.  Providing more information
      allows AppDynamics to group more intelligently.
    allOf:
      - $ref: '#/definitions/Event'
      - additionalProperties: true
        required:
          - name
        properties:
          name:
            type: string
            minLength: 1
            maxLength: 64
            description: |
              The name of the error. This should be a short human readable
              name.
              Valid Examples: "SIGINT", "NullPointerException"
          message:
            type: string
            minLength: 1
            maxLength: 2048
            description: |
              A longer description of the error.
              Valid Examples: "Tried to call open() before socket was initialized",
                              "Max heap memory exceeded"
          stackTraces:
            type: array
            maxLength: 32
            description: |
              The StackTraces at the time of this error.
              The StackTrace that contained the error is the most important one,
              so be sure to populate errorStackTraceIndex if you include multiple
              StackTraces.
            items:
              $ref: '#/definitions/StackTrace'
          errorStackTraceIndex:
            type: integer
            minimum: 0
            description: |
              The index into the stackTraces array that caused the error.
              This is not required, but if there is more than one stackTrace, then
              it is highly recommended. If empty, the default is 0. If outside of the
              range of the stackTraces array, it is defaulted to 0.
          severity:
            type: string
            description: |
              The severity of the error.
              "alert" means that there was an error that didn't cause any issues.
              "critical" means that there was an error that caused issues.
              "fatal" means that there was an error that killed your app.
              The default is "critical"
            enum: [ "alert", "critical", "fatal" ]


  StackTrace:
    description: |
      A set of stack frames
    properties:
      thread:
        type: string
        minLength: 1
        maxLength: 32
        description: |
          The name of the thread that this stack trace was on.
          Examples: "0", "Main-1", "UI", "Network Processor"
      runtime:
        type: string
        description: |
          The runtime of the stack trace.
          This is purely used to format the UI nicely.
          By default this is "native", so no need to populate it
          if you are happy with that format.
        enum: [ "native", "java" ]
      stackFrames:
        type: array
        maxItems: 256
        description: |
          All of the stack frames in this stack trace.
        items:
          $ref: '#/definitions/StackFrame'

  StackFrame:
    description: |
      A platform agnostic view of a single stack frame.
      It is likely that you will not be able to populate all
      of the fields here.
    properties:
      symbolName:
        type: string
        maxLength: 128
        description: |
          The symbol of the frame. For C, this is the method name.
          For Java, this is the class name and method name.
          Valid Examples: "malloc()", "Utils.openFile()", "[Application load]"
      packageName:
        type: string
        maxLength: 256
        description: |
          The package that contains the symbol. For C, this is the
          library or executable. For Java, this is the package of the class.
          Valid Examples: "CoreFoundation", "com.my.app", "libFoo.so"
      filePath:
        type: string
        maxLength: 4096
        description: |
          The path to the file that contains the symbol.  Can be just the file name
          Valid Examples: "Main.java", "Util.c", "/home/code/myproject/src/foo.c"
      lineNumber:
        type: integer
        description: |
          The line number of the code in the symbol.
          Valid Examples: 42, 138
      absoluteAddress:
        type: integer
        format: int64
        description: |
          The absolute address of the instruction.
      imageOffset:
        type: integer
        format: int64
        description: |
          The offset of the instruction from the start of the image
      symbolOffset:
        type: integer
        format: int64
        description: |
          The offset of the instruction from the start of the symbol

  ValidationError:
    type: object
    properties:
      message:
        description: A human readable description of the validation error.
        type: array
        items:
            type: string
