{
  "openapi": "3.1.0",
  "info": {
    "title": "FlowEQ - Legacy API",
    "description": "FlowEQ Legacy REST API",
    "version": "1.0",
    "contact": {
      "name": "FlowEQ",
      "url": "https://www.floweq.com",
      "email": "support@floweq.com"
    }
  },
  "servers": [
    {
      "url": "https://next.floweq.com/api/v1"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "components": {
    "schemas": {
      "EventsListResponse": {
        "type": "object",
        "properties": {
          "count": {
            "type": "integer",
            "description": "Number of events retrieved in request."
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Event"
            },
            "description": "List of matching events."
          }
        },
        "required": [
          "count",
          "results"
        ]
      },
      "Event": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique event identifier."
          },
          "company_id": {
            "type": "string",
            "description": "Company ID the event belongs to."
          },
          "connection_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "ID of the associated connection."
          },
          "connection_key": {
            "type": [
              "string",
              "null"
            ],
            "description": "Key of the associated Sidekick connection."
          },
          "created_at": {
            "type": "string",
            "description": "ISO 8601 creation timestamp."
          },
          "excluded": {
            "type": "boolean",
            "description": "Whether the event is excluded from reporting."
          },
          "flow_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "ID of the associated flow."
          },
          "flow_key": {
            "type": [
              "string",
              "null"
            ],
            "description": "Key of the associated flow."
          },
          "flow_session": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Flow session number."
          },
          "like_value": {
            "type": [
              "number",
              "null"
            ],
            "description": "Like value for the event."
          },
          "seconds_active": {
            "type": [
              "number",
              "null"
            ],
            "description": "Seconds the user was active during the event."
          },
          "seconds_running": {
            "type": [
              "number",
              "null"
            ],
            "description": "Total seconds the event was running."
          },
          "selected_decision": {
            "type": [
              "string",
              "null"
            ],
            "description": "Title of the decision branch selected on a Decision step."
          },
          "step_key": {
            "type": [
              "string",
              "null"
            ],
            "description": "Key of the associated step."
          },
          "text": {
            "type": [
              "string",
              "null"
            ],
            "description": "Text content associated with the event."
          },
          "type": {
            "type": "string",
            "description": "Event type (e.g. user_flow_session_started)."
          },
          "updated_at": {
            "type": "string",
            "description": "ISO 8601 last updated timestamp."
          },
          "user_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "UUID of the user the event is related to."
          },
          "version_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "ID of the associated flow version."
          },
          "version_key": {
            "type": [
              "string",
              "null"
            ],
            "description": "Key of the associated flow version."
          },
          "version_object": {
            "description": "Snapshot of the flow version object at the time of the event."
          }
        },
        "required": [
          "id",
          "company_id",
          "connection_id",
          "connection_key",
          "created_at",
          "excluded",
          "flow_id",
          "flow_key",
          "flow_session",
          "like_value",
          "seconds_active",
          "seconds_running",
          "selected_decision",
          "step_key",
          "text",
          "type",
          "updated_at",
          "user_id",
          "version_id",
          "version_key"
        ]
      },
      "RecordsListResponse": {
        "type": "object",
        "properties": {
          "count": {
            "type": "integer",
            "description": "Number of records retrieved in request. Limited to 100."
          },
          "next": {
            "type": [
              "string",
              "null"
            ],
            "description": "URL to fetch the next batch of records."
          },
          "prev": {
            "type": [
              "string",
              "null"
            ],
            "description": "URL to fetch the previous batch of records."
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Record"
            },
            "description": "List of matching records."
          }
        },
        "required": [
          "count",
          "next",
          "prev",
          "results"
        ]
      },
      "Record": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique record identifier."
          },
          "record_type": {
            "type": "string",
            "description": "Record type identifier (e.g., 'uccfiling', 'custom', 'infoleaseasset')."
          },
          "uid": {
            "description": "Record type definition UID."
          },
          "status": {
            "type": "string",
            "description": "Current status of the record."
          },
          "parent_record": {
            "description": "Parent record object, or null if none."
          },
          "child_records": {
            "type": "array",
            "items": {},
            "description": "List of child record objects."
          },
          "instance": {
            "description": "The underlying instance object (InfoleaseAsset, UCCFiling, or PurchasedLabel), if applicable."
          },
          "fields": {
            "type": "object",
            "additionalProperties": {},
            "description": "Custom field values keyed by field name."
          },
          "linked": {
            "type": "object",
            "additionalProperties": {
              "type": "object",
              "additionalProperties": {}
            },
            "description": "Linked external objects, keyed by source then object name."
          },
          "created_at": {
            "type": "string",
            "description": "ISO 8601 creation timestamp."
          },
          "updated_at": {
            "type": "string",
            "description": "ISO 8601 last updated timestamp."
          },
          "views": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "List of view IDs this record belongs to."
          }
        },
        "required": [
          "record_type",
          "status",
          "child_records",
          "created_at",
          "updated_at",
          "views"
        ]
      },
      "CreateRecordValidationError": {
        "type": "object",
        "properties": {
          "message": {
            "type": "string",
            "description": "Human-readable error description."
          },
          "invalid_fields": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Field IDs not recognised for this record type."
          },
          "required_fields": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "uid": {
                  "type": "string"
                },
                "field_name": {
                  "type": "string"
                }
              },
              "required": [
                "uid",
                "field_name"
              ]
            },
            "description": "Required fields that were not provided."
          },
          "type_errors": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "uid": {
                  "type": "string"
                },
                "field_name": {
                  "type": "string"
                },
                "expected": {
                  "type": "string",
                  "description": "Expected type, e.g. 'boolean', 'number', 'date (YYYY-MM-DD)', 'string'."
                }
              },
              "required": [
                "uid",
                "field_name",
                "expected"
              ]
            },
            "description": "Fields whose submitted value did not match the expected type."
          }
        },
        "required": [
          "message"
        ]
      },
      "ErrorResponse": {
        "type": "object",
        "properties": {
          "message": {
            "type": "string",
            "description": "Human-readable error description."
          }
        },
        "required": [
          "message"
        ]
      },
      "CreateRecordBody": {
        "type": "object",
        "additionalProperties": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "number"
            },
            {
              "type": "string"
            }
          ]
        },
        "description": "Map of custom field UIDs to their values. Date fields must be formatted as YYYY-MM-DD strings.",
        "example": {
          "293ce860-4667-4ab8-a1a8-99c63f2a601d": "This is a text field",
          "970bf74e-9350-42ff-b722-64da9c0134a3": true,
          "a7e644fc-bcad-4344-b9da-819fbda53554": "2026-01-30",
          "a90de5ec-3773-46ab-b41b-02791cf9e552": 42,
          "04d1460d-8cee-497a-b7ee-71116bb035c2": "This is a required field"
        }
      },
      "RecordPatchBody": {
        "type": "object",
        "additionalProperties": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "number"
            },
            {
              "type": "string"
            }
          ]
        }
      },
      "RecordTokenResponse": {
        "type": "object",
        "properties": {
          "company_id": {
            "type": "string",
            "description": "Company ID associated with the token."
          },
          "companyId": {
            "type": "string",
            "description": "Alias for company_id."
          },
          "created_at": {
            "type": "string",
            "description": "ISO 8601 timestamp of token creation."
          },
          "expires_at": {
            "type": "string",
            "description": "ISO 8601 timestamp of token expiration."
          },
          "key": {
            "type": "string",
            "description": "Firestore document ID used as the token key."
          },
          "record_id": {
            "type": "string",
            "description": "The record ID this token grants access to."
          },
          "type": {
            "type": "string",
            "enum": [
              "record"
            ],
            "description": "Token type identifier."
          },
          "user_id": {
            "type": "string",
            "description": "User ID that minted the token."
          },
          "userId": {
            "type": "string",
            "description": "Alias for user_id."
          },
          "createdAt": {
            "description": "Firebase Timestamp of creation."
          },
          "token": {
            "type": "string",
            "description": "The signed JWT token string."
          }
        },
        "required": [
          "company_id",
          "created_at",
          "expires_at",
          "key",
          "record_id",
          "type",
          "user_id",
          "token"
        ]
      },
      "RecordTokenRequest": {
        "type": "object",
        "properties": {
          "expires_in": {
            "type": "integer",
            "maximum": 2592000,
            "description": "Seconds until the token expires. Maximum 2,592,000 (30 days). Defaults to 86,400 (1 day)."
          }
        }
      },
      "RecordStepResponse": {
        "type": "object",
        "properties": {
          "message": {
            "type": "string",
            "description": "Step execution result message."
          },
          "details": {
            "description": "Step-specific output details."
          }
        },
        "required": [
          "message"
        ]
      },
      "RecordStepRequest": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "pdf_create"
            ],
            "description": "The step type to run. Currently only 'pdf_create' is supported."
          },
          "inputs": {
            "type": "object",
            "properties": {
              "pdf_filename": {
                "type": "string",
                "description": "Output filename for the generated PDF."
              },
              "template_id": {
                "type": "string",
                "description": "ID of the template to use for PDF generation."
              }
            },
            "required": [
              "pdf_filename",
              "template_id"
            ],
            "description": "Step-specific input parameters."
          }
        },
        "required": [
          "type",
          "inputs"
        ]
      }
    },
    "parameters": {}
  },
  "paths": {
    "/events": {
      "get": {
        "summary": "List Events",
        "description": "Retrieve a list of events matching the criteria set by the query parameter. If no query parameters are set, all events affiliated with the company ID in the JWT authorization token will match the criteria.",
        "tags": [
          "Events"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "Filter by the Sidekick connection key. Supports operators: `__contains`, `__gt`, `__gte`, `__lt`, `__lte`."
            },
            "required": false,
            "description": "Filter by the Sidekick connection key. Supports operators: `__contains`, `__gt`, `__gte`, `__lt`, `__lte`.",
            "name": "connection_key",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Filter by event type.",
              "example": "user_flow_session_started"
            },
            "required": false,
            "description": "Filter by event type.",
            "name": "type",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Filter by the flow key associated with the event. Supports operators: `__contains`, `__gt`, `__gte`, `__lt`, `__lte`."
            },
            "required": false,
            "description": "Filter by the flow key associated with the event. Supports operators: `__contains`, `__gt`, `__gte`, `__lt`, `__lte`.",
            "name": "flow_key",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Filter by flow session number. Supports operators: `__gt`, `__gte`, `__lt`, `__lte`."
            },
            "required": false,
            "description": "Filter by flow session number. Supports operators: `__gt`, `__gte`, `__lt`, `__lte`.",
            "name": "flow_session",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Filter by the step key associated with the event. Supports operators: `__contains`, `__gt`, `__gte`, `__lt`, `__lte`."
            },
            "required": false,
            "description": "Filter by the step key associated with the event. Supports operators: `__contains`, `__gt`, `__gte`, `__lt`, `__lte`.",
            "name": "step_key",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Filter by the title of the decision branch selected on a Decision step."
            },
            "required": false,
            "description": "Filter by the title of the decision branch selected on a Decision step.",
            "name": "selected_decision",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Filter by the UUID of the user the event is related to."
            },
            "required": false,
            "description": "Filter by the UUID of the user the event is related to.",
            "name": "user_id",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Alias for user_id."
            },
            "required": false,
            "description": "Alias for user_id.",
            "name": "user_key",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Filter by the flow version key. Supports operators: `__contains`, `__gt`, `__gte`, `__lt`, `__lte`."
            },
            "required": false,
            "description": "Filter by the flow version key. Supports operators: `__contains`, `__gt`, `__gte`, `__lt`, `__lte`.",
            "name": "version_key",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Number of events to return. Defaults to 100, maximum 10,000."
            },
            "required": false,
            "description": "Number of events to return. Defaults to 100, maximum 10,000.",
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Page number for paginated results."
            },
            "required": false,
            "description": "Page number for paginated results.",
            "name": "page",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Field name to order results by."
            },
            "required": false,
            "description": "Field name to order results by.",
            "name": "order_by",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EventsListResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad request — invalid query parameters or limit exceeded"
          },
          "401": {
            "description": "Unauthorized"
          }
        }
      }
    },
    "/records": {
      "get": {
        "summary": "List Records",
        "description": "Retrieve a list of records matching the criteria set by the query parameter.",
        "tags": [
          "Records"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "Filter records by creation timestamp. Only one timestamp filter may be used per request."
            },
            "required": false,
            "description": "Filter records by creation timestamp. Only one timestamp filter may be used per request.",
            "name": "created_after",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Alias for created_after."
            },
            "required": false,
            "description": "Alias for created_after.",
            "name": "createdAfter",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Filter records by creation timestamp. Only one timestamp filter may be used per request."
            },
            "required": false,
            "description": "Filter records by creation timestamp. Only one timestamp filter may be used per request.",
            "name": "created_before",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Alias for created_before."
            },
            "required": false,
            "description": "Alias for created_before.",
            "name": "createdBefore",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Filter records by last updated timestamp. Only one timestamp filter may be used per request."
            },
            "required": false,
            "description": "Filter records by last updated timestamp. Only one timestamp filter may be used per request.",
            "name": "updated_after",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Alias for updated_after."
            },
            "required": false,
            "description": "Alias for updated_after.",
            "name": "updatedAfter",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Filter records by last updated timestamp. Only one timestamp filter may be used per request."
            },
            "required": false,
            "description": "Filter records by last updated timestamp. Only one timestamp filter may be used per request.",
            "name": "updated_before",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Alias for updated_before."
            },
            "required": false,
            "description": "Alias for updated_before.",
            "name": "updatedBefore",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Firestore cursor ID to fetch the next page of records. Cannot be used with prev."
            },
            "required": false,
            "description": "Firestore cursor ID to fetch the next page of records. Cannot be used with prev.",
            "name": "next",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Firestore cursor ID to fetch the previous page of records. Cannot be used with next."
            },
            "required": false,
            "description": "Firestore cursor ID to fetch the previous page of records. Cannot be used with next.",
            "name": "prev",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Filter records by type (e.g., 'uccfiling', 'custom')."
            },
            "required": false,
            "description": "Filter records by type (e.g., 'uccfiling', 'custom').",
            "name": "record_type",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Alias for record_type."
            },
            "required": false,
            "description": "Alias for record_type.",
            "name": "recordType",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Filter records by the unique ID of a view (bucket)."
            },
            "required": false,
            "description": "Filter records by the unique ID of a view (bucket).",
            "name": "view_id",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Alias for view_id."
            },
            "required": false,
            "description": "Alias for view_id.",
            "name": "viewId",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RecordsListResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad request — invalid or unsupported query parameters"
          },
          "401": {
            "description": "Unauthorized"
          }
        }
      }
    },
    "/records/{typeId}": {
      "post": {
        "summary": "Create Record",
        "description": "Create a new workboard record of the given custom record type.",
        "tags": [
          "Records"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "Custom record type ID."
            },
            "required": true,
            "description": "Custom record type ID.",
            "name": "typeId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateRecordBody"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Record created successfully.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Record"
                }
              }
            }
          },
          "400": {
            "description": "Bad request — field IDs invalid, required fields missing, or value type mismatch.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateRecordValidationError"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Record type not found for the given typeId.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/records/{record}": {
      "get": {
        "summary": "Retrieve a Record",
        "description": "Retrieve a Workboard record with the specified record ID.",
        "tags": [
          "Records"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The Workboard record ID."
            },
            "required": true,
            "description": "The Workboard record ID.",
            "name": "record",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "The requested record.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Record"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "404": {
            "description": "Record not found"
          }
        }
      },
      "patch": {
        "summary": "Update a Record",
        "description": "Update a specific Workboard record with the specified record ID.",
        "tags": [
          "Records"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The Workboard record ID."
            },
            "required": true,
            "description": "The Workboard record ID.",
            "name": "record",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RecordPatchBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Details of the updated record.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Record"
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Unauthorized"
          }
        }
      }
    },
    "/records/{record}/tokens": {
      "post": {
        "summary": "Generate a Temporary Token",
        "description": "Create a temporary access token that may be used to update a single Workboard record.",
        "tags": [
          "Records"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The Workboard record ID."
            },
            "required": true,
            "description": "The Workboard record ID.",
            "name": "record",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RecordTokenRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Temporary record token created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RecordTokenResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Unauthorized"
          },
          "404": {
            "description": "Record not found"
          }
        }
      }
    },
    "/records/{record}/actions": {
      "post": {
        "summary": "Generate a Temporary Token (deprecated alias)",
        "description": "Alias for POST /api/v1/records/{record}/tokens. Use that endpoint instead.",
        "tags": [
          "Records"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The Workboard record ID."
            },
            "required": true,
            "description": "The Workboard record ID.",
            "name": "record",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RecordTokenRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Temporary record token created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RecordTokenResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Unauthorized"
          },
          "404": {
            "description": "Record not found"
          }
        }
      }
    },
    "/records/{record}/steps": {
      "put": {
        "summary": "Run a Step",
        "description": "Run a specific FlowEQ step against a specific Workboard record.",
        "tags": [
          "Records"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "The Workboard record ID."
            },
            "required": true,
            "description": "The Workboard record ID.",
            "name": "record",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RecordStepRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Step executed successfully.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RecordStepResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad request or unsupported step type"
          },
          "401": {
            "description": "Unauthorized"
          },
          "404": {
            "description": "Record not found"
          }
        }
      }
    }
  },
  "webhooks": {}
}