{
  "openapi": "3.0.3",
  "info": {
    "title": "Integration Toolkit API",
    "version": "1.5.3",
    "description": "API for integrating with external systems in a standardised way."
  },
  "tags": [
    {
      "name": "erp",
      "description": "ERP integration endpoints"
    },
    {
      "name": "trigger",
      "description": "Endpoints to trigger ERP related actions"
    },
    {
      "name": "integrations",
      "description": "Integration and Use Case management endpoints"
    },
    {
      "name": "monitoring",
      "description": "Monitoring and analytics endpoints"
    },
    {
      "name": "managed-call",
      "description": "Managed call endpoints for synchronous external API calls"
    },
    {
      "name": "proxy",
      "description": "Secure proxy endpoints"
    }
  ],
  "servers": [
    {
      "url": "https://integration-toolkit.sls.epilot.io"
    }
  ],
  "security": [
    {
      "EpilotAuth": []
    }
  ],
  "paths": {
    "/v1/erp/tracking/acknowledgement": {
      "post": {
        "operationId": "acknowledgeTracking",
        "summary": "acknowledgeTracking",
        "description": "Acknowledges an ERP tracking record by removing it from the tracking table, requires public authentication",
        "tags": [
          "erp"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "ack_id"
                ],
                "properties": {
                  "ack_id": {
                    "type": "string",
                    "description": "Unique identifier of the ERP tracking record to acknowledge"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Acknowledgment successful",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request - missing ack_id"
          },
          "401": {
            "description": "Unauthorized - invalid or missing token"
          },
          "404": {
            "description": "Record not found"
          },
          "500": {
            "description": "Server error processing the request"
          }
        }
      }
    },
    "/v1/erp/trigger": {
      "post": {
        "operationId": "triggerErp",
        "summary": "triggerErp",
        "description": "Triggers the ERP integration process",
        "tags": [
          "erp",
          "trigger"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TriggerErpActionRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/TriggerWebhookResponse"
          },
          "400": {
            "description": "Bad request - invalid or missing parameters"
          },
          "401": {
            "description": "Unauthorized - invalid or missing token"
          },
          "500": {
            "description": "Server error processing the request"
          }
        }
      }
    },
    "/v1/erp/updates/events": {
      "post": {
        "deprecated": true,
        "operationId": "processErpUpdatesEvents",
        "summary": "processErpUpdatesEvents",
        "description": "Handles updates from ERP systems and tracks them appropriately",
        "tags": [
          "erp"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "app_id",
                  "component_id",
                  "meta",
                  "events"
                ],
                "properties": {
                  "app_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "UUID that identifies the specific integration app instance"
                  },
                  "component_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "UUID that identifies the specific integration app component instance"
                  },
                  "meta": {
                    "type": "object",
                    "description": "Metadata to be passed along with the events",
                    "additionalProperties": true,
                    "properties": {
                      "correlation_id": {
                        "type": "string",
                        "description": "ID that identifies the specific request for debugging purposes"
                      }
                    }
                  },
                  "events": {
                    "type": "array",
                    "description": "List of ERP events to process",
                    "items": {
                      "$ref": "#/components/schemas/ErpEvent"
                    }
                  }
                }
              },
              "example": {
                "app_id": "123e4567-e89b-12d3-a456-426614174000",
                "component_id": "123e4567-e89b-12d3-a456-426614174000",
                "meta": {
                  "correlation_id": "req-789e4567-e89b-12d3-a456-426614174000"
                },
                "events": [
                  {
                    "event_type": "CREATE",
                    "object_type": "business_partner",
                    "timestamp": "2025-05-01T08:30:00Z",
                    "format": "json",
                    "payload": "{\"id\":\"BP10001\",\"name\":\"Acme Corporation\",\"type\":\"organization\",\"tax_id\":\"DE123456789\",\"status\":\"active\"}",
                    "deduplication_id": "bp-create-20250501-083000-001"
                  },
                  {
                    "event_type": "UPDATE",
                    "object_type": "contract_account",
                    "timestamp": "2025-05-01T08:35:00Z",
                    "format": "json",
                    "payload": "{\"id\":\"CA20001\",\"business_partner_id\":\"BP10001\",\"status\":\"active\",\"payment_method\":\"direct_debit\"}",
                    "deduplication_id": "ca-update-20250501-083500-001"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/ERPUpdatesResponse"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/v2/erp/updates/events": {
      "post": {
        "deprecated": true,
        "operationId": "processErpUpdatesEventsV2",
        "summary": "processErpUpdatesEventsV2",
        "description": "Handles updates from ERP systems using integration_id directly.\nThis is the v2 version that simplifies the API by accepting integration_id\ninstead of app_id and component_id.\n",
        "tags": [
          "erp"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ErpUpdatesEventsV2Request"
              },
              "example": {
                "integration_id": "123e4567-e89b-12d3-a456-426614174000",
                "correlation_id": "req-789e4567-e89b-12d3-a456-426614174000",
                "events": [
                  {
                    "event_type": "CREATE",
                    "object_type": "business_partner",
                    "timestamp": "2025-05-01T08:30:00Z",
                    "format": "json",
                    "payload": "{\"id\":\"BP10001\",\"name\":\"Acme Corporation\",\"type\":\"organization\",\"tax_id\":\"DE123456789\",\"status\":\"active\"}",
                    "deduplication_id": "bp-create-20250501-083000-001"
                  },
                  {
                    "event_type": "UPDATE",
                    "object_type": "contract_account",
                    "timestamp": "2025-05-01T08:35:00Z",
                    "format": "json",
                    "payload": "{\"id\":\"CA20001\",\"business_partner_id\":\"BP10001\",\"status\":\"active\",\"payment_method\":\"direct_debit\"}",
                    "deduplication_id": "ca-update-20250501-083500-001"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/ERPUpdatesResponse"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/v3/erp/updates/events": {
      "post": {
        "operationId": "processErpUpdatesEventsV3",
        "summary": "processErpUpdatesEventsV3",
        "description": "Handles updates from ERP systems using integration_id directly.\nThis is the v3 version that removes the unused event_type field and renames object_type to event_name\nto align with the integration UI naming.\n",
        "tags": [
          "erp"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ErpUpdatesEventsV3Request"
              },
              "example": {
                "integration_id": "123e4567-e89b-12d3-a456-426614174000",
                "correlation_id": "req-789e4567-e89b-12d3-a456-426614174000",
                "events": [
                  {
                    "event_name": "business_partner",
                    "timestamp": "2025-05-01T08:30:00Z",
                    "format": "json",
                    "payload": "{\"id\":\"BP10001\",\"name\":\"Acme Corporation\",\"type\":\"organization\",\"tax_id\":\"DE123456789\",\"status\":\"active\"}",
                    "deduplication_id": "bp-create-20250501-083000-001"
                  },
                  {
                    "event_name": "contract_account",
                    "timestamp": "2025-05-01T08:35:00Z",
                    "format": "json",
                    "payload": "{\"id\":\"CA20001\",\"business_partner_id\":\"BP10001\",\"status\":\"active\",\"payment_method\":\"direct_debit\"}",
                    "deduplication_id": "ca-update-20250501-083500-001"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/ERPUpdatesResponse"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/v2/erp/updates/mapping_simulation": {
      "post": {
        "operationId": "simulateMappingV2",
        "summary": "simulateMappingV2",
        "description": "Test v2.0 mapping configuration by transforming a payload using the provided mapping rules without persisting data.\n\nThis endpoint accepts the same configuration format that is stored in the integration use case resource,\nmaking it easier to test configurations before saving them to a use case.\n\nSee documentation at /docs/MAPPING_V2.md for detailed v2.0 format specification.\n",
        "tags": [
          "erp"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MappingSimulationV2Request"
              },
              "examples": {
                "simple": {
                  "summary": "Simple Example",
                  "value": {
                    "event_configuration": {
                      "entities": [
                        {
                          "entity_schema": "contact",
                          "unique_ids": [
                            "customer_number"
                          ],
                          "fields": [
                            {
                              "attribute": "customer_number",
                              "field": "customerId"
                            },
                            {
                              "attribute": "first_name",
                              "field": "firstName"
                            },
                            {
                              "attribute": "last_name",
                              "field": "lastName"
                            },
                            {
                              "attribute": "email",
                              "field": "email"
                            },
                            {
                              "attribute": "source",
                              "constant": "ERP"
                            }
                          ]
                        }
                      ]
                    },
                    "format": "json",
                    "payload": "{\"customerId\":\"12345\",\"firstName\":\"Anna\",\"lastName\":\"Schmidt\",\"email\":\"anna@example.com\"}"
                  }
                },
                "advanced_with_relations": {
                  "summary": "Advanced with Relations",
                  "value": {
                    "event_configuration": {
                      "entities": [
                        {
                          "entity_schema": "contract",
                          "unique_ids": [
                            "contract_number"
                          ],
                          "fields": [
                            {
                              "attribute": "contract_number",
                              "field": "number"
                            },
                            {
                              "attribute": "display_name",
                              "field": "displayName"
                            },
                            {
                              "attribute": "billing_account",
                              "relations": {
                                "operation": "_set",
                                "items": [
                                  {
                                    "entity_schema": "billing_account",
                                    "_tags": [
                                      "PRIMARY"
                                    ],
                                    "unique_ids": [
                                      {
                                        "attribute": "external_id",
                                        "field": "customerAccountId"
                                      }
                                    ]
                                  }
                                ]
                              }
                            }
                          ]
                        },
                        {
                          "entity_schema": "meter",
                          "unique_ids": [
                            "meter_number"
                          ],
                          "jsonataExpression": "meters.{\"number\": number, \"type\": meterType}",
                          "fields": [
                            {
                              "attribute": "meter_number",
                              "field": "number"
                            },
                            {
                              "attribute": "meter_type",
                              "field": "type"
                            }
                          ]
                        }
                      ]
                    },
                    "format": "json",
                    "payload": "{\"number\":\"CTR-001\",\"displayName\":\"Premium Contract\",\"customerAccountId\":\"ACC-999\",\"meters\":[{\"number\":\"M-001\",\"meterType\":\"electricity\"},{\"number\":\"M-002\",\"meterType\":\"gas\"}]}"
                  }
                },
                "with_meter_readings": {
                  "summary": "With Meter Readings",
                  "value": {
                    "event_configuration": {
                      "entities": [
                        {
                          "entity_schema": "contract",
                          "unique_ids": [
                            "contract_number"
                          ],
                          "fields": [
                            {
                              "attribute": "contract_number",
                              "field": "number"
                            },
                            {
                              "attribute": "display_name",
                              "field": "name"
                            }
                          ]
                        }
                      ],
                      "meter_readings": [
                        {
                          "jsonataExpression": "$.readings",
                          "meter": {
                            "unique_ids": [
                              {
                                "attribute": "external_id",
                                "field": "meter_id"
                              }
                            ]
                          },
                          "fields": [
                            {
                              "attribute": "external_id",
                              "field": "reading_id"
                            },
                            {
                              "attribute": "timestamp",
                              "field": "read_at"
                            },
                            {
                              "attribute": "source",
                              "constant": "ERP"
                            },
                            {
                              "attribute": "value",
                              "field": "value"
                            }
                          ]
                        }
                      ]
                    },
                    "format": "json",
                    "payload": "{\"number\":\"CTR-001\",\"name\":\"Main Contract\",\"readings\":[{\"meter_id\":\"M-001\",\"reading_id\":\"R-001\",\"read_at\":\"2025-01-15T10:00:00Z\",\"value\":12345.6}]}"
                  }
                },
                "conditional_fields": {
                  "summary": "Conditional Field Processing",
                  "description": "Example showing how to conditionally enable/disable individual field mappings",
                  "value": {
                    "event_configuration": {
                      "entities": [
                        {
                          "entity_schema": "contact",
                          "unique_ids": [
                            "customer_number"
                          ],
                          "fields": [
                            {
                              "attribute": "customer_number",
                              "field": "customerId"
                            },
                            {
                              "attribute": "email",
                              "field": "email",
                              "enabled": "$exists(email) and email != ''"
                            },
                            {
                              "attribute": "phone",
                              "field": "phone",
                              "enabled": "$exists(phone) and phone != ''"
                            },
                            {
                              "attribute": "vip_status",
                              "constant": "VIP",
                              "enabled": "vipFlag = true"
                            },
                            {
                              "attribute": "billing_account",
                              "enabled": "$exists(billingAccountId)",
                              "relations": {
                                "operation": "_set",
                                "items": [
                                  {
                                    "entity_schema": "billing_account",
                                    "unique_ids": [
                                      {
                                        "attribute": "external_id",
                                        "field": "billingAccountId"
                                      }
                                    ]
                                  }
                                ]
                              }
                            }
                          ]
                        }
                      ]
                    },
                    "format": "json",
                    "payload": "{\"customerId\":\"12345\",\"email\":\"user@example.com\",\"phone\":\"\",\"vipFlag\":true,\"billingAccountId\":\"ACC-999\"}"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successfully simulated mapping",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MappingSimulationResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "422": {
            "description": "Unprocessable entity - mapping configuration or payload validation failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponseBase"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/v1/erp/updates/mapping_simulation": {
      "post": {
        "operationId": "simulateMapping",
        "summary": "simulateMapping",
        "description": "Test mapping configuration by transforming a payload using the provided mapping rules without persisting data.\n\nSupports both v1.0 (object-based) and v2.0 (event-based) mapping formats.\nSee documentation at /docs/MAPPING_V2.md for detailed v2.0 format specification.\n",
        "tags": [
          "erp"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MappingSimulationRequest"
              },
              "examples": {
                "v1_example": {
                  "summary": "Version 1.0 Example",
                  "value": {
                    "mapping_configuration": {
                      "version": "1.0",
                      "mapping": {
                        "objects": {
                          "business_partner": {
                            "unique_ids": {
                              "contact": {
                                "partner_id": "_id"
                              }
                            },
                            "fields": [
                              {
                                "entity": "contact",
                                "attribute": "first_name",
                                "field": "firstName"
                              },
                              {
                                "entity": "contact",
                                "attribute": "last_name",
                                "field": "lastName"
                              }
                            ]
                          }
                        }
                      }
                    },
                    "object_type": "business_partner",
                    "format": "json",
                    "payload": "{\"partner_id\":\"BP10001\",\"firstName\":\"John\",\"lastName\":\"Doe\"}"
                  }
                },
                "v2_simple": {
                  "summary": "Version 2.0 - Simple Example",
                  "value": {
                    "mapping_configuration": {
                      "version": "2.0",
                      "mapping": {
                        "events": {
                          "CustomerChanged": {
                            "entities": [
                              {
                                "entity_schema": "contact",
                                "unique_ids": [
                                  "customer_number"
                                ],
                                "fields": [
                                  {
                                    "attribute": "customer_number",
                                    "field": "customerId"
                                  },
                                  {
                                    "attribute": "first_name",
                                    "field": "firstName"
                                  },
                                  {
                                    "attribute": "last_name",
                                    "field": "lastName"
                                  },
                                  {
                                    "attribute": "email",
                                    "field": "email"
                                  },
                                  {
                                    "attribute": "source",
                                    "constant": "ERP"
                                  }
                                ]
                              }
                            ]
                          }
                        }
                      }
                    },
                    "object_type": "CustomerChanged",
                    "format": "json",
                    "payload": "{\"customerId\":\"12345\",\"firstName\":\"Anna\",\"lastName\":\"Schmidt\",\"email\":\"anna@example.com\"}"
                  }
                },
                "v2_advanced": {
                  "summary": "Version 2.0 - Advanced with Relations",
                  "value": {
                    "mapping_configuration": {
                      "version": "2.0",
                      "mapping": {
                        "events": {
                          "ContractChanged": {
                            "entities": [
                              {
                                "entity_schema": "contract",
                                "unique_ids": [
                                  "contract_number"
                                ],
                                "fields": [
                                  {
                                    "attribute": "contract_number",
                                    "field": "number"
                                  },
                                  {
                                    "attribute": "display_name",
                                    "field": "displayName"
                                  },
                                  {
                                    "attribute": "billing_account",
                                    "relations": {
                                      "operation": "_set",
                                      "items": [
                                        {
                                          "entity_schema": "billing_account",
                                          "_tags": [
                                            "PRIMARY"
                                          ],
                                          "unique_ids": [
                                            {
                                              "attribute": "external_id",
                                              "field": "customerAccountId"
                                            }
                                          ]
                                        }
                                      ]
                                    }
                                  }
                                ]
                              },
                              {
                                "entity_schema": "meter",
                                "unique_ids": [
                                  "meter_number"
                                ],
                                "jsonataExpression": "meters.{\"number\": number, \"type\": meterType}",
                                "fields": [
                                  {
                                    "attribute": "meter_number",
                                    "field": "number"
                                  },
                                  {
                                    "attribute": "meter_type",
                                    "field": "type"
                                  }
                                ]
                              }
                            ]
                          }
                        }
                      }
                    },
                    "object_type": "ContractChanged",
                    "format": "json",
                    "payload": "{\"number\":\"CTR-001\",\"displayName\":\"Premium Contract\",\"customerAccountId\":\"ACC-999\",\"meters\":[{\"number\":\"M-001\",\"meterType\":\"electricity\"},{\"number\":\"M-002\",\"meterType\":\"gas\"}]}"
                  }
                },
                "v2_append_operation": {
                  "summary": "Version 2.0 - Using _append Operation",
                  "description": "Example showing how to use _append to add relations to existing entities",
                  "value": {
                    "mapping_configuration": {
                      "version": "2.0",
                      "mapping": {
                        "events": {
                          "ContactAdded": {
                            "entities": [
                              {
                                "entity_schema": "contract",
                                "unique_ids": [
                                  "contract_number"
                                ],
                                "fields": [
                                  {
                                    "attribute": "contract_number",
                                    "field": "contractNumber"
                                  },
                                  {
                                    "attribute": "additional_contacts",
                                    "relations": {
                                      "operation": "_append",
                                      "items": [
                                        {
                                          "entity_schema": "contact",
                                          "_tags": [
                                            "ADDITIONAL"
                                          ],
                                          "unique_ids": [
                                            {
                                              "attribute": "email",
                                              "field": "contactEmail"
                                            }
                                          ]
                                        }
                                      ]
                                    }
                                  }
                                ]
                              }
                            ]
                          }
                        }
                      }
                    },
                    "object_type": "ContactAdded",
                    "format": "json",
                    "payload": "{\"contractNumber\":\"CTR-001\",\"contactEmail\":\"new.contact@example.com\"}"
                  }
                },
                "v2_field_enabled": {
                  "summary": "Version 2.0 - Field-Level Conditional Processing",
                  "description": "Example showing how to conditionally enable/disable individual field mappings using the enabled property",
                  "value": {
                    "mapping_configuration": {
                      "version": "2.0",
                      "mapping": {
                        "events": {
                          "CustomerChanged": {
                            "entities": [
                              {
                                "entity_schema": "contact",
                                "unique_ids": [
                                  "customer_number"
                                ],
                                "fields": [
                                  {
                                    "attribute": "customer_number",
                                    "field": "customerId"
                                  },
                                  {
                                    "attribute": "email",
                                    "field": "email",
                                    "enabled": true
                                  },
                                  {
                                    "attribute": "phone",
                                    "field": "phone",
                                    "enabled": "$exists(phone) and phone != ''"
                                  },
                                  {
                                    "attribute": "mobile",
                                    "field": "mobile",
                                    "enabled": "$exists(mobile)"
                                  },
                                  {
                                    "attribute": "vip_status",
                                    "constant": "VIP",
                                    "enabled": "vipFlag = true"
                                  },
                                  {
                                    "attribute": "internal_notes",
                                    "field": "notes",
                                    "enabled": false
                                  },
                                  {
                                    "attribute": "billing_account",
                                    "enabled": "$exists(billingAccountId)",
                                    "relations": {
                                      "operation": "_set",
                                      "items": [
                                        {
                                          "entity_schema": "billing_account",
                                          "unique_ids": [
                                            {
                                              "attribute": "external_id",
                                              "field": "billingAccountId"
                                            }
                                          ]
                                        }
                                      ]
                                    }
                                  }
                                ]
                              }
                            ]
                          }
                        }
                      }
                    },
                    "object_type": "CustomerChanged",
                    "format": "json",
                    "payload": "{\"customerId\":\"12345\",\"email\":\"user@example.com\",\"phone\":\"\",\"mobile\":\"555-1234\",\"vipFlag\":true,\"notes\":\"Internal only\",\"billingAccountId\":\"ACC-999\"}"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successfully simulated mapping",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MappingSimulationResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "422": {
            "description": "Unprocessable entity - mapping configuration or payload validation failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponseBase"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/v1/integrations": {
      "get": {
        "operationId": "listIntegrations",
        "summary": "listIntegrations",
        "description": "Retrieve all integrations for the authenticated organization",
        "tags": [
          "integrations"
        ],
        "responses": {
          "200": {
            "description": "Successfully retrieved integrations",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "integrations"
                  ],
                  "properties": {
                    "integrations": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Integration"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      },
      "post": {
        "operationId": "createIntegration",
        "summary": "createIntegration",
        "description": "Create a new integration configuration",
        "tags": [
          "integrations"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateIntegrationRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Integration created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Integration"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/v1/integrations/{integrationId}": {
      "get": {
        "operationId": "getIntegration",
        "summary": "getIntegration",
        "description": "Retrieve a specific integration by its ID",
        "tags": [
          "integrations"
        ],
        "parameters": [
          {
            "name": "integrationId",
            "in": "path",
            "required": true,
            "description": "The integration ID",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successfully retrieved integration",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Integration"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "Integration not found"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      },
      "put": {
        "operationId": "updateIntegration",
        "summary": "updateIntegration",
        "description": "Update an existing integration configuration",
        "tags": [
          "integrations"
        ],
        "parameters": [
          {
            "name": "integrationId",
            "in": "path",
            "required": true,
            "description": "The integration ID",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateIntegrationRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Integration updated successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Integration"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "Integration not found"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      },
      "delete": {
        "operationId": "deleteIntegration",
        "summary": "deleteIntegration",
        "description": "Delete an integration and all its use cases",
        "tags": [
          "integrations"
        ],
        "parameters": [
          {
            "name": "integrationId",
            "in": "path",
            "required": true,
            "description": "The integration ID",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Integration deleted successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "Integration not found"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/v1/integrations/{integrationId}/events": {
      "post": {
        "operationId": "queryEvents",
        "summary": "queryEvents",
        "description": "Query events for a specific integration",
        "tags": [
          "integrations"
        ],
        "parameters": [
          {
            "name": "integrationId",
            "in": "path",
            "required": true,
            "description": "The integration ID",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/QueryEventsRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/QueryEventsResponse"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/v1/integrations/{integrationId}/events/replay": {
      "post": {
        "operationId": "replayEvents",
        "summary": "replayEvents",
        "description": "Replay one or more events for a specific integration. Events will be re-processed with their original payloads but with a new correlation ID for traceability.",
        "tags": [
          "integrations"
        ],
        "parameters": [
          {
            "name": "integrationId",
            "in": "path",
            "required": true,
            "description": "The integration ID",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReplayEventsRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/ReplayEventsResponse"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/v1/integrations/{integrationId}/use-cases": {
      "get": {
        "operationId": "listUseCases",
        "summary": "listUseCases",
        "description": "Retrieve all use cases for a specific integration",
        "tags": [
          "integrations"
        ],
        "parameters": [
          {
            "name": "integrationId",
            "in": "path",
            "required": true,
            "description": "The integration ID",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successfully retrieved use cases",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "use_cases"
                  ],
                  "properties": {
                    "use_cases": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/UseCase"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      },
      "post": {
        "operationId": "createUseCase",
        "summary": "createUseCase",
        "description": "Create a new use case for an integration",
        "tags": [
          "integrations"
        ],
        "parameters": [
          {
            "name": "integrationId",
            "in": "path",
            "required": true,
            "description": "The integration ID",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateUseCaseRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Use case created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UseCase"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "Integration not found"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/v1/integrations/{integrationId}/use-cases/{useCaseId}": {
      "get": {
        "operationId": "getUseCase",
        "summary": "getUseCase",
        "description": "Retrieve a specific use case by its ID",
        "tags": [
          "integrations"
        ],
        "parameters": [
          {
            "name": "integrationId",
            "in": "path",
            "required": true,
            "description": "The integration ID",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "useCaseId",
            "in": "path",
            "required": true,
            "description": "The use case ID",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successfully retrieved use case",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UseCase"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "Use case not found"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      },
      "put": {
        "operationId": "updateUseCase",
        "summary": "updateUseCase",
        "description": "Update an existing use case configuration",
        "tags": [
          "integrations"
        ],
        "parameters": [
          {
            "name": "integrationId",
            "in": "path",
            "required": true,
            "description": "The integration ID",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "useCaseId",
            "in": "path",
            "required": true,
            "description": "The use case ID",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateUseCaseRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Use case updated successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UseCase"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "Use case not found"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      },
      "delete": {
        "operationId": "deleteUseCase",
        "summary": "deleteUseCase",
        "description": "Delete a use case from an integration",
        "tags": [
          "integrations"
        ],
        "parameters": [
          {
            "name": "integrationId",
            "in": "path",
            "required": true,
            "description": "The integration ID",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "useCaseId",
            "in": "path",
            "required": true,
            "description": "The use case ID",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Use case deleted successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "Use case not found"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/v1/integrations/{integrationId}/use-cases/{useCaseId}/history": {
      "get": {
        "operationId": "listUseCaseHistory",
        "summary": "listUseCaseHistory",
        "description": "Retrieve historical versions of a use case's configuration.\nHistory entries are returned in reverse chronological order (newest first).\nUse the 'cursor' parameter for pagination to fetch additional entries.\n",
        "tags": [
          "integrations"
        ],
        "parameters": [
          {
            "name": "integrationId",
            "in": "path",
            "required": true,
            "description": "The integration ID",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "useCaseId",
            "in": "path",
            "required": true,
            "description": "The use case ID",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Opaque pagination cursor. Pass the 'next_cursor' value from a previous\nresponse to fetch the next page of results.\n",
            "schema": {
              "type": "string"
            },
            "example": "eyJwayI6Ik9SRyMxMjM0NSIsInNrIjoiSU5URUdSQVRJT04jLi4uIn0="
          }
        ],
        "responses": {
          "200": {
            "description": "Successfully retrieved use case history",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "history"
                  ],
                  "properties": {
                    "history": {
                      "type": "array",
                      "description": "History entries in reverse chronological order (newest first)",
                      "items": {
                        "$ref": "#/components/schemas/UseCaseHistoryEntry"
                      }
                    },
                    "next_cursor": {
                      "type": "string",
                      "description": "Opaque cursor for fetching the next page. Absent if no more pages."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "Use case not found"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/v2/integrations": {
      "get": {
        "operationId": "listIntegrationsV2",
        "summary": "listIntegrationsV2",
        "description": "Retrieve all integrations with embedded use cases for the authenticated organization",
        "tags": [
          "integrations"
        ],
        "responses": {
          "200": {
            "description": "Successfully retrieved integrations with use cases",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "integrations"
                  ],
                  "properties": {
                    "integrations": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/IntegrationWithUseCases"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      },
      "post": {
        "operationId": "createIntegrationV2",
        "summary": "createIntegrationV2",
        "description": "Create a new integration with embedded use cases.\n",
        "tags": [
          "integrations"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpsertIntegrationWithUseCasesRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Integration created successfully with use cases",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IntegrationWithUseCases"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/v2/integrations/{integrationId}": {
      "get": {
        "operationId": "getIntegrationV2",
        "summary": "getIntegrationV2",
        "description": "Retrieve a specific integration with all its embedded use cases",
        "tags": [
          "integrations"
        ],
        "parameters": [
          {
            "name": "integrationId",
            "in": "path",
            "required": true,
            "description": "The integration ID",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successfully retrieved integration with use cases",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IntegrationWithUseCases"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "Integration not found"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      },
      "put": {
        "operationId": "updateIntegrationV2",
        "summary": "updateIntegrationV2",
        "description": "Update an existing integration with embedded use cases.\nThe integration must already exist.\nUse cases are updated declaratively:\n- Use cases in the request with matching IDs are updated\n- Use cases in the request without matching IDs are created\n- Existing use cases not in the request are deleted\n",
        "tags": [
          "integrations"
        ],
        "parameters": [
          {
            "name": "integrationId",
            "in": "path",
            "required": true,
            "description": "The integration ID (client-provided)",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpsertIntegrationWithUseCasesRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Integration updated successfully with use cases",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IntegrationWithUseCases"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "Integration not found"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      },
      "delete": {
        "operationId": "deleteIntegrationV2",
        "summary": "deleteIntegrationV2",
        "description": "Delete an integration and all its use cases",
        "tags": [
          "integrations"
        ],
        "parameters": [
          {
            "name": "integrationId",
            "in": "path",
            "required": true,
            "description": "The integration ID",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Integration deleted successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "Integration not found"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/v2/integrations/{integrationId}/notifications/history": {
      "get": {
        "operationId": "listNotificationHistory",
        "summary": "listNotificationHistory",
        "description": "Returns the cursor-paginated, newest-first notification history for an\nintegration (every real notification decision — both fired and suppressed).\nRequires the `integration:view` permission on the integration's organization.\n",
        "tags": [
          "integrations"
        ],
        "security": [
          {
            "EpilotAuth": []
          }
        ],
        "parameters": [
          {
            "name": "integrationId",
            "in": "path",
            "required": true,
            "description": "The integration ID",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Opaque base64 pagination cursor returned as `next_cursor` by a prior page.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of items to return (clamped to 100).",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "Optional notification type filter (e.g. `critical_error`, `error_threshold`).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Cursor-paginated notification history (newest first)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotificationHistoryResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/v2/integrations/{integrationId}/notifications/test": {
      "post": {
        "operationId": "testSendNotification",
        "summary": "testSendNotification",
        "description": "Renders and sends ONE representative notification of the requested kind/type to\nthe CALLING USER ONLY (never any other recipient), so an operator can preview how\na notification looks. A test send does NOT write to the notification history.\nRequires the `integration:manage` permission on the integration's organization.\n",
        "tags": [
          "integrations"
        ],
        "security": [
          {
            "EpilotAuth": []
          }
        ],
        "parameters": [
          {
            "name": "integrationId",
            "in": "path",
            "required": true,
            "description": "The integration ID",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TestNotificationRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Test notification accepted for delivery to the calling user (sent is true)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TestNotificationResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "502": {
            "description": "The downstream notification service rejected or failed the test send.\nThe body uses TestNotificationResponse with sent set to false so the\noperator sees the real (failed) delivery outcome.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TestNotificationResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v2/integrations/{integrationId}/notifications/status": {
      "get": {
        "operationId": "getNotificationStatus",
        "summary": "getNotificationStatus",
        "description": "Returns the live per-rule alert state and (for 'auto' rules) the current\nhour-of-week baseline band for an integration's notification monitoring.\nReflects the latest 5-minute sweep — near-real-time, not live.\nRequires the `integration:view` permission on the integration's organization.\n",
        "tags": [
          "integrations"
        ],
        "security": [
          {
            "EpilotAuth": []
          }
        ],
        "parameters": [
          {
            "name": "integrationId",
            "in": "path",
            "required": true,
            "description": "The integration ID",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "include",
            "in": "query",
            "required": false,
            "description": "Add `baseline_series` to also return all 168 hour-of-week buckets per\n'auto' rule (heavier; omit for just the current-bucket markers).\n",
            "schema": {
              "type": "string",
              "enum": [
                "baseline_series"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Live notification status",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotificationStatusResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/v2/integrations/{integrationId}/use-cases/{useCaseId}/secure-proxy-whitelist": {
      "get": {
        "operationId": "getSecureProxyWhitelist",
        "summary": "Get secure_proxy whitelist (admin portal only)",
        "description": "Returns the current allowed_domains, allowed_ips, and vpc_mode for a secure_proxy use case.\nStaff-only — gated by internal-auth issuer AND admin-portal Cognito user pool membership.\nRejects Login-As tokens.\n",
        "tags": [
          "integrations",
          "proxy"
        ],
        "security": [
          {
            "EpilotAuth": []
          }
        ],
        "parameters": [
          {
            "name": "integrationId",
            "in": "path",
            "required": true,
            "description": "The integration ID",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "useCaseId",
            "in": "path",
            "required": true,
            "description": "The use case ID",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Current whitelist",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SecureProxyWhitelist"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "Use case not found or not of type secure_proxy"
          }
        }
      },
      "put": {
        "operationId": "updateSecureProxyWhitelist",
        "summary": "Update secure_proxy whitelist (admin portal only)",
        "description": "Replaces allowed_domains and/or allowed_ips on a secure_proxy use case.\nAt least one of the two fields is required. Validation mirrors the CLI's\n`validateDomainPatterns` / `validateCidrs`. Writes a USECASE_HISTORY row\nwith the admin user's email as `changed_by`.\n\nUpdate semantics per field:\n  - **omitted** — field is not modified; the stored value is preserved.\n  - **non-empty array** — the stored value is replaced with the supplied list.\n  - **empty array (`[]`)** — the list is cleared (stored as `[]`). This is\n    the canonical way to remove all entries. `null` is not accepted.\n\nStaff-only — same auth gates as GET.\n",
        "tags": [
          "integrations",
          "proxy"
        ],
        "security": [
          {
            "EpilotAuth": []
          }
        ],
        "parameters": [
          {
            "name": "integrationId",
            "in": "path",
            "required": true,
            "description": "The integration ID",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "useCaseId",
            "in": "path",
            "required": true,
            "description": "The use case ID",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SecureProxyWhitelistUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated whitelist (same shape as GET)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SecureProxyWhitelist"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "Use case not found or not of type secure_proxy"
          }
        }
      }
    },
    "/v2/integrations/{integrationId}/use-cases/{useCaseId}/secure-proxy-whitelist/history": {
      "get": {
        "operationId": "listSecureProxyWhitelistHistory",
        "summary": "List secure_proxy whitelist change history (admin portal only)",
        "description": "Returns the most recent USECASE_HISTORY entries for a secure_proxy use case,\nin reverse chronological order (newest first). Each entry includes the\nactor email (`changed_by`), the ISO-8601 timestamp (`history_created_at`),\nthe `change_description` (free-text action), and the full `configuration`\nsnapshot — from which UI-08 computes a before/after diff between consecutive\nentries.\n\nStaff-only — gated by internal-auth issuer AND admin-portal Cognito user pool\nmembership. Rejects Login-As tokens (same auth gate as the GET / PUT\nsecure-proxy-whitelist operations).\n\nThin wrapper over the service-layer `listUseCaseHistory` that powers\n`GET /v1/integrations/{integrationId}/use-cases/{useCaseId}/history` — the\nseparate path exists because the /v1 variant is tenant-gated and admin-portal\ninternal-auth tokens do not carry tenant permissions.\n",
        "tags": [
          "integrations",
          "proxy"
        ],
        "security": [
          {
            "EpilotAuth": []
          }
        ],
        "parameters": [
          {
            "name": "integrationId",
            "in": "path",
            "required": true,
            "description": "The integration ID",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "useCaseId",
            "in": "path",
            "required": true,
            "description": "The use case ID (must be of type secure_proxy)",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of history entries to return. Default 10, max 50.\nCapped at the service-layer page size (20) so `limit > 20` is silently\nclamped to 20. UI-08 requests 5-10 for the panel view.\n",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 10
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successfully retrieved secure_proxy history",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "history"
                  ],
                  "properties": {
                    "history": {
                      "type": "array",
                      "description": "Entries are `SecureProxyUseCaseHistoryEntry` in reverse\nchronological order (newest first). Entries older than the\nrequested `limit` are not returned.\n",
                      "items": {
                        "$ref": "#/components/schemas/SecureProxyUseCaseHistoryEntry"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "Use case not found or not of type secure_proxy"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/v1/integrations/{integrationId}/app-mapping": {
      "put": {
        "operationId": "setIntegrationAppMapping",
        "summary": "setIntegrationAppMapping",
        "description": "Creates or updates a mapping from an app/component to an integration.\nThis allows ERP updates sent via app_id and component_id to be associated\nwith a specific integration configuration.\n",
        "tags": [
          "integrations"
        ],
        "parameters": [
          {
            "name": "integrationId",
            "in": "path",
            "required": true,
            "description": "The integration ID to map to",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SetIntegrationAppMappingRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "App mapping set successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IntegrationAppMapping"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "Integration not found"
          },
          "409": {
            "description": "Mapping already exists (use overwrite=true to replace)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponseBase"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      },
      "delete": {
        "operationId": "deleteIntegrationAppMapping",
        "summary": "deleteIntegrationAppMapping",
        "description": "Removes a mapping from an app/component to an integration.\n",
        "tags": [
          "integrations"
        ],
        "parameters": [
          {
            "name": "integrationId",
            "in": "path",
            "required": true,
            "description": "The integration ID (used for authorization, must match the mapping)",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DeleteIntegrationAppMappingRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "App mapping deleted successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "App mapping not found"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/v1/integrations/{integrationId}/monitoring/inbound-events": {
      "post": {
        "operationId": "queryInboundMonitoringEvents",
        "summary": "queryInboundMonitoringEvents",
        "description": "Query inbound monitoring events for a specific integration.\nReturns detailed information about inbound sync events from ERP systems,\nincluding success rates, error breakdowns, and processing metrics.\n",
        "tags": [
          "monitoring",
          "integrations"
        ],
        "parameters": [
          {
            "name": "integrationId",
            "in": "path",
            "required": true,
            "description": "The integration ID",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/QueryInboundMonitoringEventsRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/QueryInboundMonitoringEventsResponse"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/v1/integrations/{integrationId}/monitoring/stats": {
      "post": {
        "operationId": "getMonitoringStats",
        "summary": "getMonitoringStats",
        "description": "Get aggregated statistics for both inbound and outbound monitoring events for a specific integration.\nReturns summary metrics for inbound (ERP sync) and outbound (webhook delivery) events,\nincluding success/error counts and optional breakdowns.\n",
        "tags": [
          "monitoring",
          "integrations"
        ],
        "parameters": [
          {
            "name": "integrationId",
            "in": "path",
            "required": true,
            "description": "The integration ID",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GetMonitoringStatsRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/GetMonitoringStatsResponse"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/v1/integrations/{integrationId}/monitoring/timeseries": {
      "post": {
        "operationId": "getMonitoringTimeSeries",
        "summary": "getMonitoringTimeSeries",
        "description": "Get time-series aggregated event counts for monitoring charts.\nReturns pre-bucketed counts at configurable intervals for both inbound and outbound events.\nMaximum of 200 buckets per request. Returns 400 if the time range and interval would exceed this limit.\n",
        "tags": [
          "monitoring",
          "integrations"
        ],
        "parameters": [
          {
            "name": "integrationId",
            "in": "path",
            "required": true,
            "description": "The integration ID",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GetMonitoringTimeSeriesRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/GetMonitoringTimeSeriesResponse"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/v1/integrations/{integrationId}/outbound-status": {
      "get": {
        "operationId": "getOutboundStatus",
        "summary": "getOutboundStatus",
        "description": "Get the status of all outbound use cases for a specific integration.\nReturns conflict information when events or webhooks are disabled but the use case is enabled.\n",
        "tags": [
          "integrations"
        ],
        "parameters": [
          {
            "name": "integrationId",
            "in": "path",
            "required": true,
            "description": "The integration ID",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successfully retrieved outbound status",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OutboundStatusResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/v1/integrations/{integrationId}/outbound/messages/poll": {
      "post": {
        "operationId": "pollOutboundMessages",
        "summary": "pollOutboundMessages",
        "description": "Poll outbound messages for an integration's poll-mode use cases.\nTakes a lease on the head-of-line batch of the integration's FIFO stream:\nthe returned messages stay invisible to subsequent polls until they are\nacknowledged or the visibility timeout elapses. POST because taking a\nlease mutates server state — auto-retrying middleware must not burn\nleases. One in-flight batch per stream: while a lease is active (or\nanother poll wins the race), the response is an empty batch\n(`messages: []`), not an error. Requires the `integration:consume` grant.\n",
        "tags": [
          "integrations"
        ],
        "security": [
          {
            "EpilotAuth": []
          }
        ],
        "parameters": [
          {
            "name": "integrationId",
            "in": "path",
            "required": true,
            "description": "The integration ID",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PollOutboundMessagesRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Leased batch of outbound messages (possibly empty)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PollOutboundMessagesResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/v1/integrations/{integrationId}/outbound/messages/ack": {
      "post": {
        "operationId": "ackOutboundMessages",
        "summary": "ackOutboundMessages",
        "description": "Acknowledge polled outbound messages. Acks are validated against the\nactive lease and committed as a prefix-contiguous cursor advance:\nmessages must be acknowledged in stream order. Out-of-order acks past\nthe first gap are rejected per id (`out_of_order`), acks with an\noutdated lease token are rejected (`stale_lease`), and unknown ids are\nrejected (`not_found`). Acknowledged messages are never delivered\nagain. Requires the `integration:consume` grant.\n",
        "tags": [
          "integrations"
        ],
        "security": [
          {
            "EpilotAuth": []
          }
        ],
        "parameters": [
          {
            "name": "integrationId",
            "in": "path",
            "required": true,
            "description": "The integration ID",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AckOutboundMessagesRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Per-id acknowledgement results",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AckOutboundMessagesResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/v1/integrations/{integrationId}/outbound/messages/dlq": {
      "get": {
        "operationId": "listOutboundDlqMessages",
        "summary": "listOutboundDlqMessages",
        "description": "List an integration's dead-lettered outbound queue messages\n(poison_policy enforcement and operator skips move messages here).\nOperator endpoint — requires the `integration:manage` grant. Message\npayloads are NOT included in listings: entries are keyed by the\nopaque message id and carry delivery metadata only. Paginated via an\nopaque `next_token`.\n",
        "tags": [
          "integrations"
        ],
        "security": [
          {
            "EpilotAuth": []
          }
        ],
        "parameters": [
          {
            "name": "integrationId",
            "in": "path",
            "required": true,
            "description": "The integration ID",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of DLQ entries to return",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            }
          },
          {
            "name": "next_token",
            "in": "query",
            "required": false,
            "description": "Opaque pagination token from a previous response",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of dead-lettered messages",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OutboundDlqListResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/v1/integrations/{integrationId}/outbound/messages/dlq/redrive": {
      "post": {
        "operationId": "redriveOutboundDlqMessages",
        "summary": "redriveOutboundDlqMessages",
        "description": "Redrive selected dead-lettered messages back into the live stream.\nOperator endpoint — requires the `integration:manage` grant.\nA redriven message is re-enqueued at the tail with a new id and\nsequence — it is delivered out of its original per-entity order (the\nstream has moved on); this is inherent to redrive and matches SQS DLQ\nsemantics. The redriven copy starts with zero delivery attempts and a\nfresh retention window; the original DLQ entry is removed. Per-id\nresults report `redriven` or `not_found` (unknown ids, or entries\nconcurrently redriven/expired).\n",
        "tags": [
          "integrations"
        ],
        "security": [
          {
            "EpilotAuth": []
          }
        ],
        "parameters": [
          {
            "name": "integrationId",
            "in": "path",
            "required": true,
            "description": "The integration ID",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RedriveOutboundDlqRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Per-id redrive results",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RedriveOutboundDlqResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/v1/integrations/{integrationId}/outbound/messages/unblock": {
      "post": {
        "operationId": "unblockOutboundStream",
        "summary": "unblockOutboundStream",
        "description": "Unblock an integration's outbound stream halted by the `block`\npoison policy: skips (dead-letters) the current blocked head message,\nemitting MSG_DEAD_LETTERED and letting the next message become the\nhead. Operator endpoint — requires the `integration:manage` grant.\nReturns `unblocked: false` as a no-op when the stream is not\ncurrently blocked (or the state moved concurrently) — safe to retry.\n",
        "tags": [
          "integrations"
        ],
        "security": [
          {
            "EpilotAuth": []
          }
        ],
        "parameters": [
          {
            "name": "integrationId",
            "in": "path",
            "required": true,
            "description": "The integration ID",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UnblockOutboundStreamRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Unblock outcome",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UnblockOutboundStreamResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/v1/integrations/{integrationId}/monitoring/access-logs": {
      "post": {
        "operationId": "queryAccessLogs",
        "summary": "queryAccessLogs",
        "description": "Query API access logs for a specific integration's organization.\nReturns access token usage analytics filtered by user_id (access token).\nSupports infinite scroll pagination with cursor-based navigation.\n",
        "tags": [
          "monitoring",
          "integrations"
        ],
        "parameters": [
          {
            "name": "integrationId",
            "in": "path",
            "required": true,
            "description": "The integration ID (used for tenant authorization)",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/QueryAccessLogsRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/QueryAccessLogsResponse"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/v1/integrations/{integrationId}/monitoring/outbound-events": {
      "post": {
        "operationId": "queryOutboundMonitoringEvents",
        "summary": "queryOutboundMonitoringEvents",
        "description": "Query outbound monitoring events for a specific integration.\nReturns detailed information about outbound event deliveries,\nfiltered by event_name (event_catalog_event) linked to the integration's outbound use cases.\n",
        "tags": [
          "monitoring",
          "integrations"
        ],
        "parameters": [
          {
            "name": "integrationId",
            "in": "path",
            "required": true,
            "description": "The integration ID",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/QueryOutboundMonitoringEventsRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/QueryOutboundMonitoringEventsResponse"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/v2/integrations/{integrationId}/monitoring/events": {
      "post": {
        "operationId": "queryMonitoringEventsV2",
        "summary": "queryMonitoringEventsV2",
        "description": "Query monitoring events from the unified erp_monitoring_v2 table.\nReturns all event types (inbound, outbound, file_proxy, etc.) in a single list.\nReplaces the separate v1 inbound-events and outbound-events endpoints.\n",
        "tags": [
          "monitoring",
          "integrations"
        ],
        "parameters": [
          {
            "name": "integrationId",
            "in": "path",
            "required": true,
            "description": "The integration ID",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/QueryMonitoringEventsV2Request"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/QueryMonitoringEventsV2Response"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/v2/integrations/{integrationId}/monitoring/stats": {
      "post": {
        "operationId": "getMonitoringStatsV2",
        "summary": "getMonitoringStatsV2",
        "description": "Get aggregated statistics from the unified erp_monitoring_v2 table.\nReturns combined metrics for all event types with optional breakdowns.\n",
        "tags": [
          "monitoring",
          "integrations"
        ],
        "parameters": [
          {
            "name": "integrationId",
            "in": "path",
            "required": true,
            "description": "The integration ID",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GetMonitoringStatsV2Request"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/GetMonitoringStatsV2Response"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/v2/integrations/{integrationId}/monitoring/time-series": {
      "post": {
        "operationId": "getMonitoringTimeSeriesV2",
        "summary": "getMonitoringTimeSeriesV2",
        "description": "Get time-series aggregated event counts from the unified erp_monitoring_v2 table.\nReturns bucketed counts for chart rendering.\n",
        "tags": [
          "monitoring",
          "integrations"
        ],
        "parameters": [
          {
            "name": "integrationId",
            "in": "path",
            "required": true,
            "description": "The integration ID",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GetMonitoringTimeSeriesV2Request"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/GetMonitoringTimeSeriesV2Response"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/v2/integrations/{integrationId}/monitoring/events/{eventId}/associated": {
      "get": {
        "operationId": "getAssociatedMonitoringEvents",
        "summary": "getAssociatedMonitoringEvents",
        "description": "Returns all monitoring events sharing the same event_id, ordered chronologically.\nAlso includes the original inbound event payload from erp_incoming_events if available.\nUsed to display a full event trace/timeline.\n",
        "tags": [
          "monitoring",
          "integrations"
        ],
        "parameters": [
          {
            "name": "integrationId",
            "in": "path",
            "required": true,
            "description": "The integration ID",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "eventId",
            "in": "path",
            "required": true,
            "description": "The event ID to get associated events for",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/GetAssociatedMonitoringEventsResponse"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/v1/integrations/secure-proxies": {
      "get": {
        "operationId": "listSecureProxies",
        "summary": "List all secure proxy use cases",
        "description": "Lists all secure_proxy use cases across all integrations for the authenticated organization.\nReturns minimal data suitable for dropdowns and selection UIs.\n",
        "tags": [
          "integrations"
        ],
        "security": [
          {
            "EpilotAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successfully retrieved secure proxy use cases",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "secure_proxies"
                  ],
                  "properties": {
                    "secure_proxies": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/SecureProxySummary"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/v1/secure-proxy": {
      "post": {
        "operationId": "secureProxy",
        "summary": "Proxy HTTP request through secure VPC",
        "description": "Routes an HTTP request through a VPC with either static IP egress or VPN secure link access.\nThe VPC mode is determined by the referenced secure_proxy use case configuration.\nFor secure_link mode, the target URL must match the use case's allowed_domains whitelist.\n",
        "tags": [
          "proxy"
        ],
        "security": [
          {
            "EpilotAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SecureProxyRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Proxied response from the target URL",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SecureProxyResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "Forbidden - insufficient permissions or target domain not whitelisted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponseBase"
                }
              }
            }
          },
          "502": {
            "description": "Upstream failure: epilot could not obtain an HTTP response from the proxied target\n(e.g. TLS handshake failure, connection refused/reset, DNS failure or timeout).\nThe body's `code`/`reason` identify the underlying cause, distinguishing a\nremote-side problem from an epilot-side one. When the target *does* answer with\nits own status, that status and body are passed through unchanged via\n`SecureProxyResponse` instead.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SecureProxyUpstreamError"
                }
              }
            }
          },
          "503": {
            "description": "VPC proxy not available for the requested mode",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponseBase"
                }
              }
            }
          },
          "504": {
            "description": "Upstream timeout",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponseBase"
                }
              }
            }
          }
        }
      }
    },
    "/v1/managed-call/{slug}/execute": {
      "post": {
        "operationId": "managedCallExecute",
        "summary": "Execute a managed call operation",
        "description": "Execute a managed call operation synchronously. The slug in the path acts as the RPC method name.\nCalls an external partner API with JSONata mapping on both request and response.\n",
        "tags": [
          "managed-call"
        ],
        "security": [
          {
            "EpilotAuth": []
          }
        ],
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z0-9][a-z0-9_-]*$"
            },
            "description": "Use case slug (acts as the RPC method name)"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ManagedCallExecuteRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Managed call executed successfully.\nThe response body is the JSONata-mapped result (or raw external API response if no mapping).\nIf inbound routing is configured, check X-Inbound-Event-Id header for tracking.\n",
            "headers": {
              "X-Inbound-Event-Id": {
                "description": "Event ID for tracking inbound pipeline processing (only present when inbound routing is configured)",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ManagedCallExecuteResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad request (e.g., invalid URL blocked by SSRF protection)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ManagedCallErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "502": {
            "description": "External API error (upstream service returned an error)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ManagedCallErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/integrations/{integrationId}/generate-types-preview": {
      "post": {
        "operationId": "generateTypesPreview",
        "summary": "Preview scaffolded types for a connector integration",
        "description": "Analyses the JSONata mappings of all managed-call use cases in the integration and returns scaffolded type descriptors. The frontend uses these to show the type editor modal where developers fill in leaf types.\n",
        "tags": [
          "integrations"
        ],
        "security": [
          {
            "EpilotAuth": []
          }
        ],
        "parameters": [
          {
            "name": "integrationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Scaffolded type preview",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenerateTypesPreviewResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/v1/integrations/{integrationId}/generate-types": {
      "post": {
        "operationId": "generateTypes",
        "summary": "Generate a TypeScript npm package for a connector integration",
        "description": "Generates a complete TypeScript npm package with typed interfaces for all managed-call use cases. This is a stateless operation that does not persist any changes. Use the commit-types endpoint to lock configurations after review.\n",
        "tags": [
          "integrations"
        ],
        "security": [
          {
            "EpilotAuth": []
          }
        ],
        "parameters": [
          {
            "name": "integrationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GenerateTypesRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Generated package",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenerateTypesResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/v1/integrations/{integrationId}/commit-types": {
      "post": {
        "operationId": "commitTypes",
        "summary": "Commit generated types and lock use case configurations",
        "description": "Commits the generated types by locking use case configurations and updating version tracking. Should be called after the user reviews and downloads the generated package.\n",
        "tags": [
          "integrations"
        ],
        "security": [
          {
            "EpilotAuth": []
          }
        ],
        "parameters": [
          {
            "name": "integrationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CommitTypesRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Types committed successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CommitTypesResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "EpilotAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Authorization header with epilot OAuth2 bearer token",
        "bearerFormat": "JWT"
      }
    },
    "schemas": {
      "NotificationHistoryItem": {
        "type": "object",
        "description": "A single notification-history row (one real notification decision).",
        "required": [
          "id",
          "type",
          "severity",
          "title",
          "occurred_at",
          "notified",
          "recipients",
          "context",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Stable history row id (ULID)."
          },
          "type": {
            "type": "string",
            "description": "The notification/rule type (e.g. critical_error, error_threshold, integration_digest)."
          },
          "state_transition": {
            "type": "string",
            "nullable": true,
            "description": "The state transition that produced this decision (e.g. OK->ALERTING), when applicable."
          },
          "severity": {
            "type": "string",
            "enum": [
              "error",
              "warning",
              "info"
            ],
            "description": "Severity of the decision."
          },
          "title": {
            "type": "string",
            "description": "Human-readable title at decision time."
          },
          "occurred_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the decision occurred (newest-first ordering key)."
          },
          "notified": {
            "type": "boolean",
            "description": "Whether the notification was actually sent (true) or suppressed (false)."
          },
          "suppressed_reason": {
            "type": "string",
            "nullable": true,
            "enum": [
              "muted",
              "debounced",
              "recipient_opt_out"
            ],
            "description": "Why the notification was suppressed (only set when notified is false)."
          },
          "recipients": {
            "type": "array",
            "description": "epilot user ids the notification was (or would have been) delivered to.",
            "items": {
              "type": "string"
            }
          },
          "context": {
            "type": "object",
            "additionalProperties": true,
            "description": "Type-specific context captured at decision time."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the history row was written."
          }
        }
      },
      "NotificationHistoryResponse": {
        "type": "object",
        "required": [
          "history"
        ],
        "properties": {
          "history": {
            "type": "array",
            "description": "Notification-history rows, newest first.",
            "items": {
              "$ref": "#/components/schemas/NotificationHistoryItem"
            }
          },
          "next_cursor": {
            "type": "string",
            "nullable": true,
            "description": "Opaque base64 cursor for the next page, or null when there are no more rows."
          }
        }
      },
      "TestNotificationRequest": {
        "type": "object",
        "required": [
          "kind"
        ],
        "properties": {
          "kind": {
            "type": "string",
            "enum": [
              "alert",
              "digest"
            ],
            "description": "The kind of notification to render and send."
          },
          "type": {
            "type": "string",
            "description": "The alert type to render when kind=alert (e.g. critical_error, error_threshold)."
          },
          "channels": {
            "type": "array",
            "description": "Delivery channels to use; defaults to the integration's configured channels.",
            "items": {
              "type": "string",
              "enum": [
                "email",
                "in_app"
              ]
            }
          }
        }
      },
      "TestNotificationResponse": {
        "type": "object",
        "required": [
          "sent",
          "recipient",
          "channels"
        ],
        "properties": {
          "sent": {
            "type": "boolean",
            "description": "Whether the test notification was accepted for delivery."
          },
          "recipient": {
            "type": "string",
            "description": "The calling user id the test was sent to (the only recipient)."
          },
          "channels": {
            "type": "array",
            "description": "The channels the test was delivered on.",
            "items": {
              "type": "string"
            }
          },
          "notification_id": {
            "type": "string",
            "nullable": true,
            "description": "The svc-notification-api message id, or null when not returned."
          }
        }
      },
      "NotificationStatusResponse": {
        "type": "object",
        "required": [
          "health",
          "rules"
        ],
        "properties": {
          "health": {
            "type": "string",
            "enum": [
              "healthy",
              "alerting",
              "muted"
            ],
            "description": "Rolled-up live status: `muted` when muteUntil is in the future; else `alerting` if any rule is currently ALERTING; else `healthy`.\n"
          },
          "evaluated_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Most recent per-rule evaluation instant (max lastEvaluatedAt), or null when no rule has been evaluated. Updates on the 5-minute sweep tick.\n"
          },
          "rules": {
            "type": "array",
            "description": "Per-rule status, one entry per configured rule.",
            "items": {
              "$ref": "#/components/schemas/NotificationRuleStatus"
            }
          }
        }
      },
      "NotificationRuleStatus": {
        "type": "object",
        "required": [
          "rule_id",
          "state"
        ],
        "properties": {
          "rule_id": {
            "type": "string",
            "description": "The rule's stable id (matches the configured rule id)."
          },
          "state": {
            "type": "string",
            "enum": [
              "ok",
              "alerting",
              "recovered"
            ],
            "description": "The rule's live AlertState (defaults to `ok` when never evaluated)."
          },
          "last_fired_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "ISO instant the rule last entered ALERTING."
          },
          "last_cleared_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "ISO instant the rule last cleared back to OK."
          },
          "baseline": {
            "nullable": true,
            "description": "Present only for enabled 'auto'-threshold rules; null otherwise.",
            "allOf": [
              {
                "$ref": "#/components/schemas/RuleBaselineStatus"
              }
            ]
          }
        }
      },
      "RuleBaselineStatus": {
        "type": "object",
        "required": [
          "is_mature"
        ],
        "properties": {
          "is_mature": {
            "type": "boolean",
            "description": "False during cold start; the sweeper uses the static fallbackThreshold until the baseline's history span is mature.\n"
          },
          "computed_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "ISO instant the baseline was last computed."
          },
          "median": {
            "type": "number",
            "nullable": true,
            "description": "Typical in-scope event volume for the current hour-of-week bucket."
          },
          "mad": {
            "type": "number",
            "nullable": true,
            "description": "Median absolute deviation for the current hour-of-week bucket."
          },
          "upper": {
            "type": "number",
            "nullable": true,
            "description": "Dynamic alert threshold (median + k·MAD, k by sensitivity) for the current hour-of-week, or null when the bucket is uncovered.\n"
          },
          "buckets": {
            "type": "array",
            "nullable": true,
            "description": "Full 168-bucket series; only present when ?include=baseline_series.",
            "items": {
              "$ref": "#/components/schemas/RuleBaselineBucket"
            }
          }
        }
      },
      "RuleBaselineBucket": {
        "type": "object",
        "required": [
          "dow",
          "hour",
          "median",
          "mad"
        ],
        "properties": {
          "dow": {
            "type": "integer",
            "minimum": 1,
            "maximum": 7,
            "description": "Day of week, 1=Monday … 7=Sunday."
          },
          "hour": {
            "type": "integer",
            "minimum": 0,
            "maximum": 23,
            "description": "Hour of day, 0 … 23 (UTC)."
          },
          "median": {
            "type": "number"
          },
          "mad": {
            "type": "number"
          }
        }
      },
      "ErrorResponseBase": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "description": "Computer-readable error code"
          },
          "message": {
            "type": "string",
            "description": "Error message"
          }
        }
      },
      "ErpEvent": {
        "type": "object",
        "required": [
          "event_type",
          "object_type",
          "timestamp",
          "format",
          "payload"
        ],
        "properties": {
          "event_type": {
            "type": "string",
            "enum": [
              "CREATE",
              "UPDATE",
              "DELETE"
            ],
            "description": "Type of event (create, update, delete)"
          },
          "object_type": {
            "type": "string",
            "description": "Type of the object being updated (business_partner, contract_account, etc.). Corresponds to \"Event Name\" from the integration UI."
          },
          "timestamp": {
            "type": "string",
            "format": "date-time",
            "description": "Timestamp when the event occurred"
          },
          "format": {
            "type": "string",
            "enum": [
              "json",
              "xml"
            ],
            "default": "json",
            "description": "Format of the payload data"
          },
          "payload": {
            "oneOf": [
              {
                "type": "string",
                "minLength": 2,
                "description": "The serialized object data payload (JSON, XML, etc.) as a string"
              },
              {
                "type": "object",
                "minProperties": 1,
                "description": "Direct JSON object (will be automatically serialized)",
                "additionalProperties": true
              }
            ],
            "description": "The object data payload - can be either a serialized string or a direct JSON object"
          },
          "deduplication_id": {
            "type": "string",
            "pattern": "^[a-zA-Z0-9_-]+$",
            "minLength": 1,
            "maxLength": 255,
            "description": "Optional unique identifier for idempotency - prevents duplicate processing of the same event within 24 hours in context of the same integration. Must contain only alphanumeric characters, hyphens, and underscores.\n",
            "example": "evt-2025-05-01-12345-create-bp"
          },
          "use_case_id": {
            "type": "string",
            "nullable": true,
            "readOnly": true,
            "description": "Resolved use case ID for the inbound event. Null when no use case matched or for events ingested before this field was introduced. Server-populated only — ignored if supplied on inbound requests.\n"
          }
        }
      },
      "ErpUpdatesEventsV2Request": {
        "type": "object",
        "required": [
          "integration_id",
          "events"
        ],
        "properties": {
          "integration_id": {
            "type": "string",
            "format": "uuid",
            "description": "UUID that identifies the integration configuration to use"
          },
          "correlation_id": {
            "type": "string",
            "description": "Optional ID that identifies the specific request for debugging purposes"
          },
          "events": {
            "type": "array",
            "description": "List of ERP events to process",
            "items": {
              "$ref": "#/components/schemas/ErpEvent"
            }
          }
        }
      },
      "ErpEventV3": {
        "type": "object",
        "required": [
          "timestamp",
          "format",
          "payload"
        ],
        "anyOf": [
          {
            "required": [
              "event_name"
            ]
          },
          {
            "required": [
              "use_case_slug"
            ]
          }
        ],
        "properties": {
          "event_name": {
            "type": "string",
            "description": "Event name from integration mapping (e.g., business_partner, contract_account). Required when use_case_slug is not provided.\n",
            "example": "business_partner"
          },
          "timestamp": {
            "type": "string",
            "format": "date-time",
            "description": "Timestamp when the event occurred",
            "example": "2025-05-01T08:30:00Z"
          },
          "format": {
            "type": "string",
            "enum": [
              "json",
              "xml"
            ],
            "default": "json",
            "description": "Format of the payload data",
            "example": "json"
          },
          "payload": {
            "oneOf": [
              {
                "type": "string",
                "minLength": 2,
                "description": "The serialized object data payload (JSON, XML, etc.) as a string"
              },
              {
                "type": "object",
                "minProperties": 1,
                "description": "Direct JSON object (will be automatically serialized)",
                "additionalProperties": true
              }
            ],
            "description": "The object data payload - can be either a serialized string or a direct JSON object",
            "example": "{\"id\":\"BP10001\",\"name\":\"Acme Corporation\",\"type\":\"organization\",\"tax_id\":\"DE123456789\",\"status\":\"active\"}"
          },
          "use_case_slug": {
            "type": "string",
            "pattern": "^[a-z0-9][a-z0-9_-]*$",
            "minLength": 1,
            "maxLength": 255,
            "description": "Recommended. Use case slug for routing this event to the correct use case configuration. If provided, takes precedence over event_name for use case lookup. Preferred over event_name-based routing as slugs are portable across environments.\n",
            "example": "business_partner"
          },
          "deduplication_id": {
            "type": "string",
            "pattern": "^[a-zA-Z0-9_-]+$",
            "minLength": 1,
            "maxLength": 255,
            "description": "Optional unique identifier for idempotency - prevents duplicate processing of the same event within 24 hours in context of the same integration. Must contain only alphanumeric characters, hyphens, and underscores.\n",
            "example": "evt-2025-05-01-12345-bp"
          }
        }
      },
      "ErpUpdatesEventsV3Request": {
        "type": "object",
        "required": [
          "integration_id",
          "events"
        ],
        "properties": {
          "integration_id": {
            "type": "string",
            "format": "uuid",
            "description": "UUID that identifies the integration configuration to use"
          },
          "correlation_id": {
            "type": "string",
            "description": "Optional ID that identifies the specific request for debugging purposes"
          },
          "group_id": {
            "type": "string",
            "description": "Controls ordering and parallelism for this request's events.\n\nBy default, all events for a given `integration_id` are processed\n**strictly in order, one at a time**. For high-volume integrations this\ncan become a throughput bottleneck.\n\nSet `group_id` to opt into **parallel processing**:\n- Events sharing the same `group_id` are processed in the order received.\n- Events with different `group_id` values are processed in parallel.\n\nTypical usage is to derive `group_id` from a logical partition key in\nyour payload — for example the customer ID, contract ID, or meter ID —\nso updates to the same business object remain ordered while unrelated\nobjects are processed concurrently.\n\nNotes:\n- Up to 20 groups per integration are processed concurrently. Using\n  more distinct values than that yields no additional parallelism.\n- Omit this field if strict per-integration ordering is required.\n",
            "maxLength": 128,
            "example": "customer-42"
          },
          "events": {
            "type": "array",
            "description": "List of ERP events to process",
            "items": {
              "$ref": "#/components/schemas/ErpEventV3"
            }
          }
        }
      },
      "TriggerErpActionRequest": {
        "type": "object",
        "required": [
          "execution_id",
          "org_id",
          "webhook_id",
          "flow_id",
          "created_at",
          "action_id",
          "flow_action_id",
          "flow_name",
          "activity_id",
          "entity_id"
        ],
        "properties": {
          "execution_id": {
            "type": "string",
            "description": "Unique identifier of the current automation execution"
          },
          "org_id": {
            "type": "string",
            "description": "Identifier of the organization where the automation is executed"
          },
          "webhook_id": {
            "type": "string",
            "description": "Identifier of the self-service webhook configuration"
          },
          "flow_id": {
            "type": "string",
            "description": "Identifier of the automation flow that triggered the action"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "ISO-8601 timestamp when the webhook event was created"
          },
          "action_id": {
            "type": "string",
            "description": "Identifier of the automation action being executed"
          },
          "flow_action_id": {
            "type": "string",
            "description": "Identifier of the specific automation flow action instance"
          },
          "flow_name": {
            "type": "string",
            "description": "Human readable name of the automation flow"
          },
          "activity_id": {
            "type": "string",
            "description": "Identifier of the entity activity related to this trigger"
          },
          "entity_id": {
            "type": "string",
            "description": "Identifier of the entity referenced by the activity"
          }
        }
      },
      "TriggerWebhookResp": {
        "type": "object",
        "properties": {
          "status_code": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "body": {
            "type": "object"
          },
          "code": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "succeeded",
              "failed"
            ]
          },
          "start_date": {
            "type": "string"
          },
          "end_date": {
            "type": "string"
          },
          "event_id": {
            "type": "string"
          }
        }
      },
      "IntegrationEditableFields": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "description": "Integration name"
          },
          "description": {
            "type": "string",
            "maxLength": 1000,
            "description": "Optional description of the integration"
          },
          "access_token_ids": {
            "type": "array",
            "description": "List of access token IDs associated with this integration",
            "items": {
              "type": "string"
            }
          },
          "app_ids": {
            "type": "array",
            "description": "List of app IDs associated with this integration",
            "items": {
              "type": "string"
            }
          },
          "environment_config": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EnvironmentFieldConfig"
            },
            "description": "Configuration defining environment variables needed by this integration. Values are stored in the Environments API."
          },
          "settings": {
            "$ref": "#/components/schemas/IntegrationSettings"
          },
          "integration_type": {
            "type": "string",
            "enum": [
              "erp",
              "connector"
            ],
            "default": "erp",
            "description": "Type of integration. \"erp\" is the ERP integration with inbound/outbound use cases. \"connector\" is for complex proxy integrations with external APIs.\n"
          },
          "connector_config": {
            "$ref": "#/components/schemas/ConnectorConfig"
          },
          "protected": {
            "type": "boolean",
            "description": "If true, integration is displayed in read-only mode in the UI to discourage changes"
          },
          "_manifest": {
            "type": "array",
            "description": "The manifest IDs associated with this integration",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "ConnectorConfig": {
        "type": "object",
        "description": "Shared configuration for connector-type integrations",
        "properties": {
          "base_url": {
            "type": "string",
            "description": "Base URL for the partner API"
          },
          "auth": {
            "$ref": "#/components/schemas/ManagedCallAuth"
          },
          "types_versions": {
            "type": "array",
            "description": "History of generated type package versions",
            "items": {
              "type": "object",
              "required": [
                "version",
                "package_name",
                "generated_at",
                "generated_by",
                "status"
              ],
              "properties": {
                "version": {
                  "type": "string"
                },
                "package_name": {
                  "type": "string"
                },
                "generated_at": {
                  "type": "string",
                  "format": "date-time"
                },
                "generated_by": {
                  "type": "string"
                },
                "status": {
                  "type": "string",
                  "enum": [
                    "active",
                    "deprecated"
                  ]
                }
              }
            }
          },
          "latest_types_version": {
            "type": "string",
            "description": "Latest active types package version"
          },
          "latest_types_package_name": {
            "type": "string",
            "description": "Latest active types package name"
          }
        }
      },
      "ManagedCallAuth": {
        "type": "object",
        "description": "Authentication configuration for managed call requests",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "oauth2_client_credentials",
              "api_key",
              "bearer"
            ],
            "description": "Authentication type"
          },
          "token_url": {
            "type": "string",
            "description": "OAuth2 token URL. Can be plain text or {{env.key}} reference."
          },
          "client_id": {
            "type": "string",
            "description": "OAuth2 client ID. Can be plain text or {{env.key}} reference."
          },
          "client_secret": {
            "type": "string",
            "description": "OAuth2 client secret. Must be an {{env.key}} reference (secret)."
          },
          "scope": {
            "type": "string",
            "description": "OAuth2 scope"
          },
          "audience": {
            "type": "string",
            "description": "OAuth2 audience parameter (e.g. for Auth0, Azure AD). Can be plain text or {{env.key}} reference."
          },
          "resource": {
            "type": "string",
            "description": "OAuth2 resource parameter (e.g. for Azure AD). Can be plain text or {{env.key}} reference."
          },
          "body_params": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Additional key-value pairs for the OAuth2 token request body. Values can be {{env.key}} references."
          },
          "headers": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Additional headers for the OAuth2 token request. Values can be {{env.key}} references."
          },
          "query_params": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Additional query parameters for the OAuth2 token URL. Values can be {{env.key}} references."
          },
          "api_key_header": {
            "type": "string",
            "description": "Header name for API key auth (default X-API-Key)"
          },
          "api_key": {
            "type": "string",
            "description": "API key value. Must be an {{env.key}} reference (secret)."
          },
          "token": {
            "type": "string",
            "description": "Bearer token value. Must be an {{env.key}} reference (secret)."
          }
        }
      },
      "Integration": {
        "allOf": [
          {
            "type": "object",
            "required": [
              "id",
              "orgId",
              "name",
              "created_at",
              "updated_at"
            ],
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid",
                "readOnly": true,
                "description": "Unique identifier for the integration"
              },
              "orgId": {
                "type": "string",
                "readOnly": true,
                "description": "Organization ID"
              },
              "created_at": {
                "type": "string",
                "format": "date-time",
                "readOnly": true,
                "description": "ISO-8601 timestamp when the integration was created"
              },
              "updated_at": {
                "type": "string",
                "format": "date-time",
                "readOnly": true,
                "description": "ISO-8601 timestamp when the integration was last updated"
              }
            }
          },
          {
            "$ref": "#/components/schemas/IntegrationEditableFields"
          }
        ]
      },
      "CreateIntegrationRequest": {
        "allOf": [
          {
            "$ref": "#/components/schemas/IntegrationEditableFields"
          },
          {
            "type": "object",
            "required": [
              "name"
            ]
          }
        ]
      },
      "UpdateIntegrationRequest": {
        "$ref": "#/components/schemas/IntegrationEditableFields"
      },
      "EnvironmentFieldConfig": {
        "type": "object",
        "required": [
          "key",
          "label",
          "type"
        ],
        "properties": {
          "key": {
            "type": "string",
            "description": "Environment variable key, used to look up the value in the Environments API.",
            "pattern": "^[a-z0-9][a-z0-9_.\\-]{0,127}$"
          },
          "label": {
            "type": "string",
            "description": "Display label for the field in the UI",
            "minLength": 1,
            "maxLength": 255
          },
          "type": {
            "type": "string",
            "enum": [
              "String",
              "SecretString"
            ],
            "description": "Whether the value is a plain string or an encrypted secret"
          },
          "description": {
            "type": "string",
            "description": "Help text shown below the field",
            "maxLength": 1000
          },
          "required": {
            "type": "boolean",
            "default": false,
            "description": "Whether this field must be filled before the integration can be used"
          },
          "order": {
            "type": "integer",
            "minimum": 0,
            "description": "Sort order for display and drag-to-reorder"
          }
        }
      },
      "IntegrationSettings": {
        "type": "object",
        "description": "Settings for the integration",
        "properties": {
          "autoRefresh": {
            "$ref": "#/components/schemas/AutoRefreshSettings"
          },
          "notifications": {
            "$ref": "#/components/schemas/IntegrationNotificationConfig"
          }
        }
      },
      "AutoRefreshSettings": {
        "type": "object",
        "description": "Auto-refresh settings for keeping integration data fresh",
        "properties": {
          "enabled": {
            "type": "boolean",
            "default": false,
            "description": "Whether auto-refresh is enabled"
          },
          "freshnessThresholdMinutes": {
            "type": "integer",
            "minimum": 1,
            "description": "Maximum age (in minutes) of data before it is considered stale and eligible for refresh"
          }
        }
      },
      "IntegrationNotificationConfig": {
        "type": "object",
        "description": "Integration monitoring notification configuration. Rides Integration.settings.notifications (camelCase) and surfaces on both v1 and v2 GET/PUT. Unknown keys are stripped server-side to stay forward-compatible with deferred (V2) rule types.",
        "required": [
          "enabled",
          "recipients",
          "defaultChannels",
          "rules",
          "digest"
        ],
        "properties": {
          "enabled": {
            "type": "boolean",
            "description": "Master switch for this integration's notifications."
          },
          "recipients": {
            "type": "array",
            "description": "epilot user ids notified for this integration. Same-org membership and per-user notification preferences are enforced at send time (Phases 3–5), not at config-write time.",
            "items": {
              "$ref": "#/components/schemas/NotificationRecipient"
            }
          },
          "defaultChannels": {
            "$ref": "#/components/schemas/NotificationChannelSet"
          },
          "monitoredUseCases": {
            "type": "array",
            "description": "Integration-level use-case include-filter; absent/empty means all use cases.",
            "items": {
              "type": "string"
            }
          },
          "monitoredCodes": {
            "type": "array",
            "description": "Integration-level code scope; absent/empty resolves to ['_error_']. Accepts concrete monitoring error codes or group sentinels (_error_, _warning_, _success_, _info_, _any_, _parent_).",
            "items": {
              "type": "string"
            }
          },
          "rules": {
            "type": "array",
            "description": "Enabled triggers and their params. A type MAY repeat; capped at 20 rules (enforced at the write boundary).",
            "items": {
              "$ref": "#/components/schemas/NotificationRule"
            }
          },
          "digest": {
            "$ref": "#/components/schemas/NotificationDigestConfig"
          },
          "muteUntil": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "ISO instant; snooze all non-digest alerts until this time. `null` means not muted."
          }
        }
      },
      "NotificationRecipient": {
        "type": "object",
        "description": "A configured recipient. Only the epilot user_id is stored.",
        "required": [
          "user_id"
        ],
        "properties": {
          "user_id": {
            "type": "string",
            "description": "epilot user id. Same-org membership is enforced at send time (Phases 3–5), which re-validates each recipient against the integration's org before fanning out — it is not enforced at config-write time."
          }
        }
      },
      "NotificationChannelSet": {
        "type": "object",
        "description": "Delivery channel toggles. New channels added in svc-notification-api inherit here.",
        "required": [
          "email",
          "in_app"
        ],
        "properties": {
          "email": {
            "type": "boolean"
          },
          "in_app": {
            "type": "boolean"
          }
        }
      },
      "NotificationRule": {
        "type": "object",
        "description": "A single notification rule. Only the params relevant to a given type are set. The id is a server-minted ULID, preserved across edits.",
        "required": [
          "id",
          "type",
          "enabled"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Stable server-minted ULID. AlertState + baseline key."
          },
          "name": {
            "type": "string",
            "description": "Optional human label disambiguating two rules of the same type."
          },
          "type": {
            "type": "string",
            "description": "Rule trigger type. V1 produces the first six; the remaining values are deferred (V2) catalog types accepted by the data model but not produced by any V1 producer.",
            "enum": [
              "critical_error",
              "error_threshold",
              "warning_threshold",
              "success_rate_drop",
              "recovery",
              "silence",
              "consecutive_failures",
              "first_error",
              "new_error_code",
              "auth_expiry",
              "ack_timeout",
              "validation_surge"
            ]
          },
          "enabled": {
            "type": "boolean"
          },
          "channels": {
            "$ref": "#/components/schemas/NotificationChannelSet"
          },
          "codes": {
            "type": "array",
            "description": "Per-rule code scope. Event-matching rules default to ['_parent_']; silence defaults to ['_any_']. success_rate_drop and recovery take no codes.",
            "items": {
              "type": "string"
            }
          },
          "threshold": {
            "description": "Count or percentage; 'auto' selects anomaly-baseline mode.",
            "oneOf": [
              {
                "type": "number"
              },
              {
                "type": "string",
                "enum": [
                  "auto"
                ]
              }
            ]
          },
          "sensitivity": {
            "type": "string",
            "description": "Band width for 'auto' mode.",
            "enum": [
              "low",
              "medium",
              "high"
            ]
          },
          "fallbackThreshold": {
            "type": "number",
            "description": "Static value used while the 'auto' baseline is immature (cold start)."
          },
          "window": {
            "type": "string",
            "description": "Evaluation window, e.g. '15m', '1h', '24h'."
          },
          "minSampleSize": {
            "type": "integer",
            "description": "success_rate_drop minimum sample size guard."
          },
          "consecutive": {
            "type": "integer",
            "description": "consecutive_failures count."
          },
          "quietPeriod": {
            "type": "string",
            "description": "silence quiet period, e.g. '12h'."
          }
        }
      },
      "NotificationDigestConfig": {
        "type": "object",
        "description": "Digest schedule and content configuration.",
        "required": [
          "enabled",
          "frequency",
          "timeOfDay",
          "timezone",
          "channels",
          "includeHealthy",
          "skipIfEmpty"
        ],
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "frequency": {
            "type": "string",
            "enum": [
              "daily",
              "weekly"
            ]
          },
          "dayOfWeek": {
            "type": "integer",
            "description": "Weekly only. 0 = Sunday … 6 = Saturday.",
            "enum": [
              0,
              1,
              2,
              3,
              4,
              5,
              6
            ]
          },
          "timeOfDay": {
            "type": "string",
            "description": "HH:mm"
          },
          "timezone": {
            "type": "string",
            "description": "IANA timezone, e.g. 'Europe/Berlin'."
          },
          "channels": {
            "$ref": "#/components/schemas/NotificationChannelSet"
          },
          "includeHealthy": {
            "type": "boolean",
            "description": "List all integrations vs. only ones with issues."
          },
          "skipIfEmpty": {
            "type": "boolean",
            "description": "Suppress the digest when nothing happened."
          }
        }
      },
      "SetIntegrationAppMappingRequest": {
        "type": "object",
        "required": [
          "app_id",
          "component_id"
        ],
        "properties": {
          "app_id": {
            "type": "string",
            "format": "uuid",
            "description": "UUID of the integration app instance"
          },
          "component_id": {
            "type": "string",
            "format": "uuid",
            "description": "UUID of the integration app component instance"
          },
          "overwrite": {
            "type": "boolean",
            "default": false,
            "description": "If true, overwrites existing mapping. If false and mapping exists, returns 409 Conflict."
          }
        }
      },
      "DeleteIntegrationAppMappingRequest": {
        "type": "object",
        "required": [
          "app_id",
          "component_id"
        ],
        "properties": {
          "app_id": {
            "type": "string",
            "format": "uuid",
            "description": "UUID of the integration app instance"
          },
          "component_id": {
            "type": "string",
            "format": "uuid",
            "description": "UUID of the integration app component instance"
          }
        }
      },
      "IntegrationAppMapping": {
        "type": "object",
        "required": [
          "integration_id"
        ],
        "properties": {
          "integration_id": {
            "type": "string",
            "format": "uuid",
            "description": "The integration ID this app/component is mapped to"
          }
        }
      },
      "IntegrationWithUseCases": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Integration"
          },
          {
            "type": "object",
            "description": "Integration with embedded use cases for atomic CRUD operations",
            "required": [
              "use_cases"
            ],
            "properties": {
              "use_cases": {
                "type": "array",
                "description": "All use cases belonging to this integration",
                "items": {
                  "$ref": "#/components/schemas/UseCase"
                }
              }
            }
          }
        ]
      },
      "UpsertIntegrationWithUseCasesRequest": {
        "allOf": [
          {
            "$ref": "#/components/schemas/IntegrationEditableFields"
          },
          {
            "type": "object",
            "description": "Request to create or update an integration with embedded use cases (upsert).\nThis is a declarative operation - the request represents the desired state.\n",
            "required": [
              "name"
            ],
            "properties": {
              "use_cases": {
                "type": "array",
                "description": "Full list of use cases (declarative). This replaces ALL existing use cases.\n- Use cases with an `id` field matching an existing use case will be updated\n- Use cases without an `id` or with a non-matching `id` will be created\n- Existing use cases not in this list will be deleted\n",
                "items": {
                  "$ref": "#/components/schemas/EmbeddedUseCaseRequest"
                }
              }
            }
          }
        ]
      },
      "InboundIntegrationEventConfiguration": {
        "type": "object",
        "description": "Configuration for inbound use cases (ERP to epilot)",
        "properties": {
          "entities": {
            "type": "array",
            "description": "Array of entity configurations for this event",
            "items": {
              "$ref": "#/components/schemas/IntegrationEntity"
            }
          },
          "meter_readings": {
            "type": "array",
            "description": "Array of meter reading configurations for this event",
            "items": {
              "$ref": "#/components/schemas/IntegrationMeterReading"
            }
          }
        }
      },
      "OutboundIntegrationEventConfiguration": {
        "type": "object",
        "required": [
          "event_catalog_event",
          "mappings"
        ],
        "description": "Configuration for outbound use cases. Defines the event that triggers the flow and the webhook mappings.",
        "properties": {
          "event_catalog_event": {
            "type": "string",
            "description": "The Event Catalog event name that triggers this outbound flow",
            "example": "contract.created"
          },
          "mappings": {
            "type": "array",
            "minItems": 1,
            "items": {
              "$ref": "#/components/schemas/OutboundMapping"
            },
            "description": "List of mappings that transform and deliver the event"
          }
        }
      },
      "IntegrationEntity": {
        "type": "object",
        "required": [
          "entity_schema",
          "unique_ids",
          "fields"
        ],
        "properties": {
          "entity_schema": {
            "type": "string",
            "description": "Target entity schema (e.g., 'contact', 'contract')"
          },
          "unique_ids": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Array of attribute names that uniquely identify this entity.\nThe _type hint for repeatable fields (e.g., email, phone) should be specified\non the corresponding field definition in the fields array.\n"
          },
          "jsonataExpression": {
            "type": "string",
            "description": "Optional JSONata expression to pre-process the event data before field mapping"
          },
          "enabled": {
            "oneOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              }
            ],
            "description": "Controls whether this entity mapping should be processed. Can be a boolean or a JSONata expression (string) that evaluates to a boolean."
          },
          "mode": {
            "type": "string",
            "enum": [
              "upsert",
              "delete",
              "purge",
              "upsert-prune-scope-purge",
              "upsert-prune-scope-delete"
            ],
            "default": "upsert",
            "description": "Operation mode for entity mapping:\n- 'upsert': Create or update the entity (default)\n- 'delete': Soft delete the entity (marks as deleted)\n- 'purge': Hard delete the entity (permanent removal)\n- 'upsert-prune-scope-purge': Upsert entities from array, then purge entities in scope that weren't upserted\n- 'upsert-prune-scope-delete': Upsert entities from array, then soft delete entities in scope that weren't upserted\n"
          },
          "scope": {
            "$ref": "#/components/schemas/PruneScopeConfig"
          },
          "fields": {
            "type": "array",
            "description": "Field mapping definitions",
            "items": {
              "$ref": "#/components/schemas/IntegrationEntityField"
            }
          }
        }
      },
      "IntegrationMeterReading": {
        "type": "object",
        "required": [
          "meter",
          "fields"
        ],
        "properties": {
          "jsonataExpression": {
            "type": "string",
            "description": "Optional JSONata expression to extract meter reading items from the event data.\nIf not provided, the entire payload is used as the reading data.\nUseful when you need to extract an array of readings from a nested structure (e.g., \"$.readings\").\n"
          },
          "reading_matching": {
            "type": "string",
            "enum": [
              "external_id",
              "strict-date"
            ],
            "default": "external_id",
            "description": "Strategy for matching incoming readings against existing readings.\n- 'external_id': Match readings by external_id attribute (default behavior)\n- 'strict-date': Match by meter_id + counter_id + direction + date (German timezone).\n  Useful when readings originate from ECP and are echoed back by the ERP with truncated timestamps.\n"
          },
          "mode": {
            "type": "string",
            "enum": [
              "upsert",
              "delete",
              "upsert-prune-scope"
            ],
            "default": "upsert",
            "description": "Operation mode for meter reading mapping:\n- 'upsert': Create or update meter readings (default)\n- 'delete': Delete the meter reading\n- 'upsert-prune-scope': Upsert readings from array, then delete all other readings for the same meter+counter that weren't upserted\n"
          },
          "scope": {
            "$ref": "#/components/schemas/MeterReadingPruneScopeConfig"
          },
          "meter": {
            "$ref": "#/components/schemas/MeterUniqueIdsConfig"
          },
          "meter_counter": {
            "$ref": "#/components/schemas/MeterUniqueIdsConfig"
          },
          "fields": {
            "type": "array",
            "description": "Field mapping definitions for meter reading attributes",
            "items": {
              "$ref": "#/components/schemas/IntegrationEntityField"
            }
          }
        }
      },
      "PruneScopeConfig": {
        "type": "object",
        "description": "Scope configuration for upsert-prune-scope modes.\nDefines how to find entities that should be pruned if not in the upsert payload.\nThe scope is resolved against the original event payload (not individual array items).\n",
        "required": [
          "scope_mode"
        ],
        "properties": {
          "scope_mode": {
            "type": "string",
            "enum": [
              "relations",
              "query"
            ],
            "description": "Scope mode for finding entities to prune:\n- 'relations': Find scope by looking at all entities related to a specific entity (both direct and reverse relations)\n- 'query': Find scope entities directly via query parameters\n"
          },
          "schema": {
            "type": "string",
            "description": "For 'relations' mode: The schema of the entity to find (e.g., 'billing_account').\nNot used for 'query' mode.\n"
          },
          "unique_ids": {
            "type": "array",
            "description": "For 'relations' mode: How to identify the scope entity from the payload.\nNot used for 'query' mode.\n",
            "items": {
              "$ref": "#/components/schemas/RelationUniqueIdField"
            }
          },
          "query": {
            "type": "array",
            "description": "For 'query' mode: Direct query parameters to find scope entities.\nNot used for 'relations' or 'reverse-relations' modes.\n",
            "items": {
              "$ref": "#/components/schemas/RelationUniqueIdField"
            }
          }
        }
      },
      "MeterReadingPruneScopeConfig": {
        "type": "object",
        "description": "Scope configuration for meter reading upsert-prune-scope mode.\nThe scope is all readings for the same meter + counter.\n",
        "properties": {
          "source": {
            "type": "string",
            "description": "Optional source filter. When set, only readings with this source\nare eligible for pruning (e.g., 'ERP' to only prune ERP-synced readings).\n"
          }
        }
      },
      "MeterUniqueIdsConfig": {
        "type": "object",
        "required": [
          "unique_ids"
        ],
        "properties": {
          "unique_ids": {
            "type": "array",
            "minItems": 1,
            "description": "Array of unique identifier field mappings",
            "items": {
              "$ref": "#/components/schemas/RelationUniqueIdField"
            }
          }
        }
      },
      "IntegrationEntityField": {
        "type": "object",
        "required": [
          "attribute"
        ],
        "properties": {
          "attribute": {
            "type": "string",
            "description": "Target attribute name"
          },
          "field": {
            "type": "string",
            "description": "Source field name or JSONPath expression (if starts with $)"
          },
          "jsonataExpression": {
            "type": "string",
            "description": "JSONata expression for transformation"
          },
          "constant": {
            "description": "Constant value to assign (any type)"
          },
          "_type": {
            "$ref": "#/components/schemas/RepeatableFieldType"
          },
          "enabled": {
            "oneOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              }
            ],
            "description": "Controls whether this field mapping should be processed. Can be a boolean or a JSONata expression (string) that evaluates to a boolean. Defaults to true if omitted."
          },
          "relations": {
            "$ref": "#/components/schemas/RelationConfig"
          },
          "relation_refs": {
            "$ref": "#/components/schemas/RelationRefsConfig"
          },
          "file_proxy_url": {
            "$ref": "#/components/schemas/FileProxyUrlConfig"
          },
          "portal_ref": {
            "$ref": "#/components/schemas/PortalRefConfig"
          },
          "env_var_ref": {
            "$ref": "#/components/schemas/EnvVarRefConfig"
          }
        }
      },
      "FileProxyUrlParam": {
        "description": "Parameter for file proxy URL. Exactly one of field, constant, or jsonataExpression must be set.",
        "oneOf": [
          {
            "type": "object",
            "required": [
              "field"
            ],
            "properties": {
              "field": {
                "type": "string",
                "description": "Source field name or JSONPath expression (if starts with $)"
              }
            }
          },
          {
            "type": "object",
            "required": [
              "constant"
            ],
            "properties": {
              "constant": {
                "description": "Constant value (any type, stringified for URL)"
              }
            }
          },
          {
            "type": "object",
            "required": [
              "jsonataExpression"
            ],
            "properties": {
              "jsonataExpression": {
                "type": "string",
                "description": "JSONata expression for transformation"
              }
            }
          }
        ]
      },
      "FileProxyUrlParams": {
        "type": "object",
        "description": "Custom query parameters. Keys become URL param names, values resolved from payload.",
        "additionalProperties": {
          "$ref": "#/components/schemas/FileProxyUrlParam"
        }
      },
      "FileProxyUrlConfig": {
        "description": "Auto-constructs a file proxy download URL. orgId and integrationId are injected from context. Exactly one of use_case_id or use_case_slug must be provided. Using use_case_slug is recommended as it is portable across environments.\n",
        "oneOf": [
          {
            "type": "object",
            "required": [
              "use_case_slug"
            ],
            "properties": {
              "use_case_slug": {
                "type": "string",
                "pattern": "^[a-z0-9][a-z0-9_-]*$",
                "description": "Recommended. Slug of the file_proxy use case. Maps to useCaseSlug query parameter. Portable across environments.\n"
              },
              "params": {
                "$ref": "#/components/schemas/FileProxyUrlParams"
              }
            }
          },
          {
            "type": "object",
            "required": [
              "use_case_id"
            ],
            "properties": {
              "use_case_id": {
                "type": "string",
                "description": "Legacy. UUID of the file_proxy use case. Maps to useCaseId query parameter. Prefer use_case_slug for portable configuration.\n"
              },
              "params": {
                "$ref": "#/components/schemas/FileProxyUrlParams"
              }
            }
          }
        ]
      },
      "PortalOrigin": {
        "type": "string",
        "enum": [
          "END_CUSTOMER_PORTAL",
          "INSTALLER_PORTAL",
          "B2B_PORTAL",
          "ADDITIONAL_PORTAL"
        ],
        "description": "Origin/type of an epilot portal configuration."
      },
      "PortalRefFilter": {
        "type": "object",
        "description": "Filter applied to the org's portal configurations before selection. All filters default to \"match any\" except `enabled` (default `true`) and `is_dummy` (default `false`). Set `enabled` or `is_dummy` to `null` to opt out of the default.\n",
        "properties": {
          "origin": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/PortalOrigin"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/PortalOrigin"
                }
              }
            ],
            "description": "Single origin or array of origins (matches if origin is in the array)."
          },
          "enabled": {
            "type": "boolean",
            "nullable": true,
            "description": "Match portals with this `enabled` value. Default `true`. Set to `null` to ignore."
          },
          "is_dummy": {
            "type": "boolean",
            "nullable": true,
            "description": "Match portals with this `is_dummy` value. Default `false`. Set to `null` to ignore."
          },
          "is_epilot_domain": {
            "type": "boolean",
            "description": "Optional restriction on `is_epilot_domain`."
          },
          "name": {
            "type": "string",
            "description": "Exact match on the portal's `name`."
          },
          "domain": {
            "type": "string",
            "description": "Exact match on the portal's `domain`."
          }
        }
      },
      "PortalRefConfig": {
        "description": "Resolves to a property of one of the calling organization's epilot portal configurations at runtime, replacing hard-coded environment-specific portal UUIDs in inbound mappings. Matched portals are sorted ascending by `(_created_at, portal_id)`; portals without `_created_at` sort first (treated as oldest). When `select: \"single\"` matches more than one portal, the resolver still returns the oldest match and emits a `PORTAL_REF_AMBIGUOUS` warning.\n",
        "oneOf": [
          {
            "type": "object",
            "properties": {
              "filter": {
                "$ref": "#/components/schemas/PortalRefFilter"
              },
              "select": {
                "type": "string",
                "enum": [
                  "single",
                  "all"
                ],
                "default": "single",
                "description": "`single` returns one literal value (the oldest matching portal); `all` returns an array of literal values (0, 1, or many).\n"
              },
              "return": {
                "type": "string",
                "enum": [
                  "portal_id",
                  "origin",
                  "domain",
                  "name"
                ],
                "default": "portal_id",
                "description": "Which portal field to emit."
              }
            }
          },
          {
            "type": "object",
            "required": [
              "return",
              "jsonataExpression"
            ],
            "properties": {
              "filter": {
                "$ref": "#/components/schemas/PortalRefFilter"
              },
              "select": {
                "type": "string",
                "enum": [
                  "single",
                  "all"
                ],
                "default": "single"
              },
              "return": {
                "type": "string",
                "enum": [
                  "jsonata"
                ],
                "description": "Evaluate the sibling `jsonataExpression` against the matched portal(s). With `select: \"single\"` the input is the matched PortalConfig object; with `select: \"all\"` it is the full filtered+sorted array.\n"
              },
              "jsonataExpression": {
                "type": "string",
                "description": "JSONata expression evaluated against the matched portal(s)."
              }
            }
          }
        ]
      },
      "EnvVarRefConfig": {
        "description": "Resolves to an org-scoped environment variable from the epilot environments-api service at runtime, replacing hard-coded environment-specific values (URLs, prefixes, identifiers) in inbound mappings. Secrets (`SecretString` values) are never exposed; the runtime treats both \"missing key\" and \"secret-typed key\" as identical `undefined` outcomes (no info disclosure via error code). For secret-resolving contexts (e.g. authorization headers in managed-call or file-proxy step configurations), use the templated `{{ env.<key> }}` syntax instead — that mechanism does decrypt secrets.\n",
        "oneOf": [
          {
            "type": "object",
            "required": [
              "key"
            ],
            "properties": {
              "key": {
                "type": "string",
                "pattern": "^[a-z0-9][a-z0-9_.-]{0,127}$",
                "description": "Environment variable key. Must match the environments-api key contract (lowercase, digits, `_`, `.`, `-`; max 128 chars; starts with a lowercase letter or digit). Supports dot-namespaced keys like `erp_api.base_url`.\n"
              },
              "default": {
                "type": "string",
                "description": "Literal string returned when the key is missing (or is a secret). When provided, the `ENV_VAR_REF_NOT_FOUND` warning is suppressed because the author signalled the absence is expected.\n"
              },
              "return": {
                "type": "string",
                "enum": [
                  "value"
                ],
                "default": "value",
                "description": "`value` returns the resolved env-var string as-is.\n"
              }
            }
          },
          {
            "type": "object",
            "required": [
              "key",
              "return",
              "jsonataExpression"
            ],
            "properties": {
              "key": {
                "type": "string",
                "pattern": "^[a-z0-9][a-z0-9_.-]{0,127}$"
              },
              "default": {
                "type": "string"
              },
              "return": {
                "type": "string",
                "enum": [
                  "jsonata"
                ],
                "description": "Evaluate the sibling `jsonataExpression` against the resolved env-var value (the input `$` is the string value).\n"
              },
              "jsonataExpression": {
                "type": "string",
                "description": "JSONata expression evaluated against the resolved env-var value."
              }
            }
          }
        ]
      },
      "EmbeddedUseCaseRequest": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/EmbeddedInboundUseCaseRequest"
          },
          {
            "$ref": "#/components/schemas/EmbeddedOutboundUseCaseRequest"
          },
          {
            "$ref": "#/components/schemas/EmbeddedFileProxyUseCaseRequest"
          },
          {
            "$ref": "#/components/schemas/EmbeddedManagedCallUseCaseRequest"
          },
          {
            "$ref": "#/components/schemas/EmbeddedSecureProxyUseCaseRequest"
          }
        ],
        "discriminator": {
          "propertyName": "type",
          "mapping": {
            "inbound": "#/components/schemas/EmbeddedInboundUseCaseRequest",
            "outbound": "#/components/schemas/EmbeddedOutboundUseCaseRequest",
            "file_proxy": "#/components/schemas/EmbeddedFileProxyUseCaseRequest",
            "managed_call": "#/components/schemas/EmbeddedManagedCallUseCaseRequest",
            "secure_proxy": "#/components/schemas/EmbeddedSecureProxyUseCaseRequest"
          }
        }
      },
      "EmbeddedUseCaseRequestBase": {
        "type": "object",
        "required": [
          "name",
          "type",
          "enabled"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Optional use case ID for update matching.\n- If provided and matches an existing use case, that use case is updated\n- If provided but no match, a new use case with this ID is created\n- If omitted, a new use case with auto-generated ID is created\n"
          },
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "description": "Use case name"
          },
          "slug": {
            "type": "string",
            "pattern": "^[a-z0-9][a-z0-9_-]*$",
            "minLength": 1,
            "maxLength": 255,
            "description": "URL-safe identifier for the use case. Optional on this upsert/sync endpoint — when omitted, the server derives one from the name and ensures uniqueness within the integration. Immutable after creation.\n"
          },
          "enabled": {
            "type": "boolean",
            "description": "Whether the use case is enabled"
          },
          "change_description": {
            "type": "string",
            "maxLength": 2000,
            "description": "Optional description of this change (like a commit message)"
          }
        }
      },
      "EmbeddedInboundUseCaseRequest": {
        "allOf": [
          {
            "$ref": "#/components/schemas/EmbeddedUseCaseRequestBase"
          },
          {
            "type": "object",
            "required": [
              "type"
            ],
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "inbound"
                ],
                "description": "Use case type"
              },
              "configuration": {
                "$ref": "#/components/schemas/InboundIntegrationEventConfiguration"
              }
            }
          }
        ]
      },
      "EmbeddedOutboundUseCaseRequest": {
        "allOf": [
          {
            "$ref": "#/components/schemas/EmbeddedUseCaseRequestBase"
          },
          {
            "type": "object",
            "required": [
              "type"
            ],
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "outbound"
                ],
                "description": "Use case type"
              },
              "configuration": {
                "$ref": "#/components/schemas/OutboundIntegrationEventConfiguration"
              }
            }
          }
        ]
      },
      "EmbeddedFileProxyUseCaseRequest": {
        "allOf": [
          {
            "$ref": "#/components/schemas/EmbeddedUseCaseRequestBase"
          },
          {
            "type": "object",
            "required": [
              "type"
            ],
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "file_proxy"
                ],
                "description": "Use case type"
              },
              "configuration": {
                "$ref": "#/components/schemas/FileProxyUseCaseConfiguration"
              }
            }
          }
        ]
      },
      "EmbeddedManagedCallUseCaseRequest": {
        "allOf": [
          {
            "$ref": "#/components/schemas/EmbeddedUseCaseRequestBase"
          },
          {
            "type": "object",
            "required": [
              "type"
            ],
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "managed_call"
                ],
                "description": "Use case type for managed API calls"
              },
              "configuration": {
                "$ref": "#/components/schemas/ManagedCallOperationConfig"
              }
            }
          }
        ]
      },
      "EmbeddedSecureProxyUseCaseRequest": {
        "allOf": [
          {
            "$ref": "#/components/schemas/EmbeddedUseCaseRequestBase"
          },
          {
            "type": "object",
            "required": [
              "type"
            ],
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "secure_proxy"
                ],
                "description": "Use case type"
              },
              "configuration": {
                "$ref": "#/components/schemas/SecureProxyUseCaseConfiguration"
              }
            }
          }
        ]
      },
      "UseCaseBase": {
        "type": "object",
        "required": [
          "id",
          "integrationId",
          "name",
          "type",
          "enabled",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Unique identifier for the use case"
          },
          "integrationId": {
            "type": "string",
            "format": "uuid",
            "description": "Parent integration ID"
          },
          "name": {
            "type": "string",
            "description": "Use case name"
          },
          "slug": {
            "type": "string",
            "pattern": "^[a-z0-9][a-z0-9_-]*$",
            "minLength": 1,
            "maxLength": 255,
            "description": "URL-safe identifier for the use case. Recommended for portable cross-environment referencing. Unique per integration. Immutable after creation. Lowercase alphanumeric, hyphens, and underscores only.\n"
          },
          "type": {
            "type": "string",
            "enum": [
              "inbound",
              "outbound",
              "file_proxy",
              "managed_call",
              "secure_proxy"
            ],
            "description": "Use case type"
          },
          "enabled": {
            "type": "boolean"
          },
          "change_description": {
            "type": "string",
            "maxLength": 2000,
            "description": "Description of the last change made to this use case"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "ISO-8601 timestamp when the use case was created"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "description": "ISO-8601 timestamp when the use case was last updated"
          }
        }
      },
      "InboundUseCase": {
        "allOf": [
          {
            "$ref": "#/components/schemas/UseCaseBase"
          },
          {
            "type": "object",
            "required": [
              "type"
            ],
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "inbound"
                ],
                "description": "Use case type"
              },
              "configuration": {
                "$ref": "#/components/schemas/InboundIntegrationEventConfiguration"
              }
            }
          }
        ]
      },
      "OutboundUseCase": {
        "allOf": [
          {
            "$ref": "#/components/schemas/UseCaseBase"
          },
          {
            "type": "object",
            "required": [
              "type"
            ],
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "outbound"
                ],
                "description": "Use case type"
              },
              "configuration": {
                "$ref": "#/components/schemas/OutboundIntegrationEventConfiguration"
              }
            }
          }
        ]
      },
      "FileProxyUseCase": {
        "allOf": [
          {
            "$ref": "#/components/schemas/UseCaseBase"
          },
          {
            "type": "object",
            "required": [
              "type"
            ],
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "file_proxy"
                ],
                "description": "Use case type"
              },
              "configuration": {
                "$ref": "#/components/schemas/FileProxyUseCaseConfiguration"
              }
            }
          }
        ]
      },
      "ManagedCallUseCase": {
        "allOf": [
          {
            "$ref": "#/components/schemas/UseCaseBase"
          },
          {
            "type": "object",
            "required": [
              "type"
            ],
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "managed_call"
                ],
                "description": "Use case type for managed API calls"
              },
              "configuration": {
                "$ref": "#/components/schemas/ManagedCallOperationConfig"
              },
              "type_annotations": {
                "$ref": "#/components/schemas/TypeAnnotations"
              },
              "types_locked": {
                "type": "boolean",
                "description": "Whether types have been generated for this use case"
              }
            }
          }
        ]
      },
      "SecureProxyUseCase": {
        "allOf": [
          {
            "$ref": "#/components/schemas/UseCaseBase"
          },
          {
            "type": "object",
            "required": [
              "type"
            ],
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "secure_proxy"
                ],
                "description": "Use case type"
              },
              "configuration": {
                "$ref": "#/components/schemas/SecureProxyUseCaseConfiguration"
              }
            }
          }
        ]
      },
      "UseCase": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/InboundUseCase"
          },
          {
            "$ref": "#/components/schemas/OutboundUseCase"
          },
          {
            "$ref": "#/components/schemas/FileProxyUseCase"
          },
          {
            "$ref": "#/components/schemas/ManagedCallUseCase"
          },
          {
            "$ref": "#/components/schemas/SecureProxyUseCase"
          }
        ],
        "discriminator": {
          "propertyName": "type",
          "mapping": {
            "inbound": "#/components/schemas/InboundUseCase",
            "outbound": "#/components/schemas/OutboundUseCase",
            "file_proxy": "#/components/schemas/FileProxyUseCase",
            "managed_call": "#/components/schemas/ManagedCallUseCase",
            "secure_proxy": "#/components/schemas/SecureProxyUseCase"
          }
        }
      },
      "CreateUseCaseRequest": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/CreateInboundUseCaseRequest"
          },
          {
            "$ref": "#/components/schemas/CreateOutboundUseCaseRequest"
          },
          {
            "$ref": "#/components/schemas/CreateFileProxyUseCaseRequest"
          },
          {
            "$ref": "#/components/schemas/CreateManagedCallUseCaseRequest"
          },
          {
            "$ref": "#/components/schemas/CreateSecureProxyUseCaseRequest"
          }
        ],
        "discriminator": {
          "propertyName": "type",
          "mapping": {
            "inbound": "#/components/schemas/CreateInboundUseCaseRequest",
            "outbound": "#/components/schemas/CreateOutboundUseCaseRequest",
            "file_proxy": "#/components/schemas/CreateFileProxyUseCaseRequest",
            "managed_call": "#/components/schemas/CreateManagedCallUseCaseRequest",
            "secure_proxy": "#/components/schemas/CreateSecureProxyUseCaseRequest"
          }
        }
      },
      "CreateUseCaseRequestBase": {
        "type": "object",
        "required": [
          "name",
          "slug",
          "type",
          "enabled"
        ],
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "description": "Use case name"
          },
          "slug": {
            "type": "string",
            "pattern": "^[a-z0-9][a-z0-9_-]*$",
            "minLength": 1,
            "maxLength": 255,
            "description": "URL-safe identifier for the use case. Required for explicit creates so every use case has a portable cross-environment identifier. Must be unique per integration. Immutable after creation. Lowercase alphanumeric, hyphens, and underscores only.\n"
          },
          "enabled": {
            "type": "boolean",
            "description": "Whether the use case is enabled"
          }
        }
      },
      "CreateInboundUseCaseRequest": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CreateUseCaseRequestBase"
          },
          {
            "type": "object",
            "required": [
              "type"
            ],
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "inbound"
                ],
                "description": "Use case type"
              },
              "configuration": {
                "$ref": "#/components/schemas/InboundIntegrationEventConfiguration"
              }
            }
          }
        ]
      },
      "CreateOutboundUseCaseRequest": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CreateUseCaseRequestBase"
          },
          {
            "type": "object",
            "required": [
              "type"
            ],
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "outbound"
                ],
                "description": "Use case type"
              },
              "configuration": {
                "$ref": "#/components/schemas/OutboundIntegrationEventConfiguration"
              }
            }
          }
        ]
      },
      "CreateFileProxyUseCaseRequest": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CreateUseCaseRequestBase"
          },
          {
            "type": "object",
            "required": [
              "type"
            ],
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "file_proxy"
                ],
                "description": "Use case type"
              },
              "configuration": {
                "$ref": "#/components/schemas/FileProxyUseCaseConfiguration"
              }
            }
          }
        ]
      },
      "CreateManagedCallUseCaseRequest": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CreateUseCaseRequestBase"
          },
          {
            "type": "object",
            "required": [
              "type"
            ],
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "managed_call"
                ],
                "description": "Use case type for managed API calls"
              },
              "configuration": {
                "$ref": "#/components/schemas/ManagedCallOperationConfig"
              }
            }
          }
        ]
      },
      "CreateSecureProxyUseCaseRequest": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CreateUseCaseRequestBase"
          },
          {
            "type": "object",
            "required": [
              "type"
            ],
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "secure_proxy"
                ],
                "description": "Use case type"
              },
              "configuration": {
                "$ref": "#/components/schemas/SecureProxyUseCaseConfiguration"
              }
            }
          }
        ]
      },
      "UpdateUseCaseRequest": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/UpdateInboundUseCaseRequest"
          },
          {
            "$ref": "#/components/schemas/UpdateOutboundUseCaseRequest"
          },
          {
            "$ref": "#/components/schemas/UpdateFileProxyUseCaseRequest"
          },
          {
            "$ref": "#/components/schemas/UpdateManagedCallUseCaseRequest"
          },
          {
            "$ref": "#/components/schemas/UpdateSecureProxyUseCaseRequest"
          }
        ],
        "discriminator": {
          "propertyName": "type",
          "mapping": {
            "inbound": "#/components/schemas/UpdateInboundUseCaseRequest",
            "outbound": "#/components/schemas/UpdateOutboundUseCaseRequest",
            "file_proxy": "#/components/schemas/UpdateFileProxyUseCaseRequest",
            "managed_call": "#/components/schemas/UpdateManagedCallUseCaseRequest",
            "secure_proxy": "#/components/schemas/UpdateSecureProxyUseCaseRequest"
          }
        }
      },
      "UpdateUseCaseRequestBase": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "description": "Use case name"
          },
          "slug": {
            "type": "string",
            "pattern": "^[a-z0-9][a-z0-9_-]*$",
            "minLength": 1,
            "maxLength": 255,
            "description": "URL-safe identifier for the use case. Recommended for portable cross-environment referencing. Can only be set once on use cases that don't have a slug yet. Immutable after being set.\n"
          },
          "enabled": {
            "type": "boolean",
            "description": "Whether the use case is enabled"
          },
          "change_description": {
            "type": "string",
            "maxLength": 2000,
            "description": "Optional description of this change (like a commit message)"
          }
        }
      },
      "UpdateInboundUseCaseRequest": {
        "allOf": [
          {
            "$ref": "#/components/schemas/UpdateUseCaseRequestBase"
          },
          {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "inbound"
                ],
                "description": "Use case type"
              },
              "configuration": {
                "$ref": "#/components/schemas/InboundIntegrationEventConfiguration"
              }
            }
          }
        ]
      },
      "UpdateOutboundUseCaseRequest": {
        "allOf": [
          {
            "$ref": "#/components/schemas/UpdateUseCaseRequestBase"
          },
          {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "outbound"
                ],
                "description": "Use case type"
              },
              "configuration": {
                "$ref": "#/components/schemas/OutboundIntegrationEventConfiguration"
              }
            }
          }
        ]
      },
      "UpdateFileProxyUseCaseRequest": {
        "allOf": [
          {
            "$ref": "#/components/schemas/UpdateUseCaseRequestBase"
          },
          {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "file_proxy"
                ],
                "description": "Use case type"
              },
              "configuration": {
                "$ref": "#/components/schemas/FileProxyUseCaseConfiguration"
              }
            }
          }
        ]
      },
      "UpdateManagedCallUseCaseRequest": {
        "allOf": [
          {
            "$ref": "#/components/schemas/UpdateUseCaseRequestBase"
          },
          {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "managed_call"
                ],
                "description": "Use case type for managed API calls"
              },
              "configuration": {
                "$ref": "#/components/schemas/ManagedCallOperationConfig"
              },
              "type_annotations": {
                "$ref": "#/components/schemas/TypeAnnotations"
              }
            }
          }
        ]
      },
      "UpdateSecureProxyUseCaseRequest": {
        "allOf": [
          {
            "$ref": "#/components/schemas/UpdateUseCaseRequestBase"
          },
          {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "secure_proxy"
                ],
                "description": "Use case type"
              },
              "configuration": {
                "$ref": "#/components/schemas/SecureProxyUseCaseConfiguration"
              }
            }
          }
        ]
      },
      "UseCaseHistoryEntry": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/InboundUseCaseHistoryEntry"
          },
          {
            "$ref": "#/components/schemas/OutboundUseCaseHistoryEntry"
          },
          {
            "$ref": "#/components/schemas/FileProxyUseCaseHistoryEntry"
          },
          {
            "$ref": "#/components/schemas/ManagedCallUseCaseHistoryEntry"
          },
          {
            "$ref": "#/components/schemas/SecureProxyUseCaseHistoryEntry"
          }
        ],
        "discriminator": {
          "propertyName": "type",
          "mapping": {
            "inbound": "#/components/schemas/InboundUseCaseHistoryEntry",
            "outbound": "#/components/schemas/OutboundUseCaseHistoryEntry",
            "file_proxy": "#/components/schemas/FileProxyUseCaseHistoryEntry",
            "managed_call": "#/components/schemas/ManagedCallUseCaseHistoryEntry",
            "secure_proxy": "#/components/schemas/SecureProxyUseCaseHistoryEntry"
          }
        }
      },
      "UseCaseHistoryEntryBase": {
        "type": "object",
        "required": [
          "id",
          "useCaseId",
          "integrationId",
          "name",
          "type",
          "enabled",
          "created_at",
          "updated_at",
          "history_created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Unique identifier for this history entry"
          },
          "useCaseId": {
            "type": "string",
            "format": "uuid",
            "description": "Reference to the parent use case"
          },
          "integrationId": {
            "type": "string",
            "format": "uuid",
            "description": "Parent integration ID"
          },
          "name": {
            "type": "string",
            "description": "Use case name at this point in history"
          },
          "slug": {
            "type": "string",
            "description": "Use case slug at this point in history"
          },
          "enabled": {
            "type": "boolean",
            "description": "Whether the use case was enabled at this point in history"
          },
          "change_description": {
            "type": "string",
            "description": "Description of the change that was made at this point in history"
          },
          "changed_by": {
            "type": "string",
            "description": "User ID of the user who made the change that produced this history entry"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "ISO-8601 timestamp when the use case was originally created"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "description": "ISO-8601 timestamp of this historical snapshot (before the update)"
          },
          "history_created_at": {
            "type": "string",
            "format": "date-time",
            "description": "ISO-8601 timestamp when this history entry was created"
          }
        }
      },
      "InboundUseCaseHistoryEntry": {
        "allOf": [
          {
            "$ref": "#/components/schemas/UseCaseHistoryEntryBase"
          },
          {
            "type": "object",
            "required": [
              "type"
            ],
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "inbound"
                ],
                "description": "Use case type"
              },
              "configuration": {
                "$ref": "#/components/schemas/InboundIntegrationEventConfiguration"
              }
            }
          }
        ]
      },
      "OutboundUseCaseHistoryEntry": {
        "allOf": [
          {
            "$ref": "#/components/schemas/UseCaseHistoryEntryBase"
          },
          {
            "type": "object",
            "required": [
              "type"
            ],
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "outbound"
                ],
                "description": "Use case type"
              },
              "configuration": {
                "$ref": "#/components/schemas/OutboundIntegrationEventConfiguration"
              }
            }
          }
        ]
      },
      "FileProxyUseCaseHistoryEntry": {
        "allOf": [
          {
            "$ref": "#/components/schemas/UseCaseHistoryEntryBase"
          },
          {
            "type": "object",
            "required": [
              "type"
            ],
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "file_proxy"
                ],
                "description": "Use case type"
              },
              "configuration": {
                "$ref": "#/components/schemas/FileProxyUseCaseConfiguration"
              }
            }
          }
        ]
      },
      "ManagedCallUseCaseHistoryEntry": {
        "allOf": [
          {
            "$ref": "#/components/schemas/UseCaseHistoryEntryBase"
          },
          {
            "type": "object",
            "required": [
              "type"
            ],
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "managed_call"
                ],
                "description": "Use case type for managed API calls"
              },
              "configuration": {
                "$ref": "#/components/schemas/ManagedCallOperationConfig"
              },
              "type_annotations": {
                "$ref": "#/components/schemas/TypeAnnotations"
              },
              "types_locked": {
                "type": "boolean",
                "description": "Whether types have been generated for this use case"
              }
            }
          }
        ]
      },
      "SecureProxyUseCaseHistoryEntry": {
        "allOf": [
          {
            "$ref": "#/components/schemas/UseCaseHistoryEntryBase"
          },
          {
            "type": "object",
            "required": [
              "type"
            ],
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "secure_proxy"
                ],
                "description": "Use case type"
              },
              "configuration": {
                "$ref": "#/components/schemas/SecureProxyUseCaseConfiguration"
              }
            }
          }
        ]
      },
      "SecureProxyUseCaseConfiguration": {
        "type": "object",
        "required": [
          "vpc_mode"
        ],
        "description": "Configuration for secure_proxy use cases. Defines how to route requests through a secure VPC.\n",
        "properties": {
          "vpc_mode": {
            "type": "string",
            "enum": [
              "static_ip",
              "secure_link"
            ],
            "readOnly": true,
            "description": "VPC routing mode. Read-only after creation.\n- static_ip: Routes through a VPC with static outbound IP (NAT Gateway) for IP-allowlisted external APIs.\n- secure_link: Routes through a VPN VPC for accessing private customer networks.\n"
          },
          "allowed_domains": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "readOnly": true,
            "description": "Domain whitelist for secure_link mode. Admin-only — can only be modified directly in DynamoDB via admin script.\nSupports exact match (e.g., \"api.wemag.com\") and wildcard prefix (e.g., \"*.wemag.com\").\n"
          },
          "allowed_ips": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "readOnly": true,
            "description": "IP allowlist (CIDR notation) for secure_link mode. Admin-only — can only be modified directly in DynamoDB via admin script.\nRequired for secure_link mode. All DNS-resolved IPs must match at least one range.\nExample: [\"10.0.1.0/24\", \"192.168.1.0/24\"]\n"
          }
        }
      },
      "SecureProxyWhitelist": {
        "type": "object",
        "required": [
          "vpc_mode",
          "allowed_domains",
          "allowed_ips"
        ],
        "description": "Current whitelist state for a secure_proxy use case. vpc_mode is read-only\ncontext so the UI can show the user what mode the pool is in.\n",
        "properties": {
          "vpc_mode": {
            "type": "string",
            "nullable": true,
            "enum": [
              "static_ip",
              "secure_link"
            ],
            "description": "VPC routing mode (read-only). `null` if not yet set."
          },
          "allowed_domains": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Exact domain (\"api.example.com\") or wildcard prefix (\"*.example.com\").\nWildcards must have at least 2 labels in the suffix.\n"
          },
          "allowed_ips": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "CIDR-notation IP ranges, e.g. \"10.0.0.0/24\"."
          }
        }
      },
      "SecureProxyWhitelistUpdate": {
        "type": "object",
        "description": "Partial update for a secure_proxy whitelist. At least one of\n`allowed_domains` or `allowed_ips` must be provided.\n\nPer-field semantics:\n  - **omitted** — the field is not modified; the stored value is preserved.\n  - **non-empty array** — the stored value is replaced with the supplied list.\n  - **empty array (`[]`)** — the list is cleared (stored as `[]`). This is the\n    canonical way to remove all entries from a list. `null` is not accepted.\n",
        "minProperties": 1,
        "properties": {
          "allowed_domains": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Exact domain (\"api.example.com\") or wildcard prefix (\"*.example.com\").\nWildcards must have at least 2 labels in the suffix.\nPass `[]` to clear all allowed domains.\n"
          },
          "allowed_ips": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "CIDR-notation IP ranges, e.g. \"10.0.0.0/24\".\nPass `[]` to clear all allowed IPs.\n"
          }
        }
      },
      "SecureProxySummary": {
        "type": "object",
        "required": [
          "id",
          "name",
          "enabled",
          "vpc_mode",
          "integration_id",
          "integration_name"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "enabled": {
            "type": "boolean"
          },
          "vpc_mode": {
            "type": "string",
            "enum": [
              "static_ip",
              "secure_link"
            ]
          },
          "allowed_domains": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "allowed_ips": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "integration_id": {
            "type": "string",
            "format": "uuid"
          },
          "integration_name": {
            "type": "string"
          }
        }
      },
      "SecureProxyRequest": {
        "type": "object",
        "required": [
          "url",
          "method",
          "integration_id"
        ],
        "properties": {
          "integration_id": {
            "type": "string",
            "format": "uuid",
            "description": "Integration ID that owns the secure_proxy use case"
          },
          "use_case_id": {
            "type": "string",
            "format": "uuid",
            "description": "Use case ID (provide either use_case_id or use_case_slug)"
          },
          "use_case_slug": {
            "type": "string",
            "description": "Use case slug (provide either use_case_id or use_case_slug)"
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Target URL to proxy the request to"
          },
          "method": {
            "type": "string",
            "enum": [
              "GET",
              "POST",
              "PUT",
              "PATCH",
              "DELETE"
            ],
            "description": "HTTP method"
          },
          "headers": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Request headers to forward"
          },
          "body": {
            "description": "Request body (string or JSON)"
          },
          "response_type": {
            "type": "string",
            "enum": [
              "json",
              "binary"
            ],
            "default": "json",
            "description": "Expected response type"
          }
        }
      },
      "SecureProxyResponse": {
        "type": "object",
        "properties": {
          "status_code": {
            "type": "integer",
            "description": "HTTP status code from the upstream response"
          },
          "headers": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Response headers from upstream"
          },
          "body": {
            "description": "Response body from upstream. When `status_code` is 502 and the target never produced an HTTP response (TLS/connection/DNS failure or timeout), this is a `SecureProxyUpstreamError` describing the underlying cause."
          }
        }
      },
      "SecureProxyUpstreamError": {
        "type": "object",
        "description": "Error payload returned when epilot could not obtain an HTTP response from the proxied target. The failure is epilot-generated (HTTP 502) but the cause is usually remote-side; `code`/`reason` make that attributable.",
        "required": [
          "message"
        ],
        "properties": {
          "message": {
            "type": "string",
            "description": "Short error category.",
            "enum": [
              "Upstream network error",
              "Upstream error"
            ]
          },
          "code": {
            "type": "string",
            "description": "Underlying Node.js/axios error code when available (e.g. `UNABLE_TO_VERIFY_LEAF_SIGNATURE`, `ECONNREFUSED`, `ETIMEDOUT`, `ENOTFOUND`)."
          },
          "reason": {
            "type": "string",
            "description": "Human-readable explanation, present only for well-known codes (TLS/certificate, DNS and connection failures)."
          }
        }
      },
      "ManagedCallOperationConfig": {
        "type": "object",
        "required": [
          "operation"
        ],
        "description": "Configuration for managed_call use cases. Defines a single API operation with JSONata mapping.",
        "properties": {
          "operation": {
            "$ref": "#/components/schemas/ManagedCallOperation"
          },
          "request_mapping": {
            "type": "string",
            "description": "JSONata expression for outbound body transformation"
          },
          "response_mapping": {
            "type": "string",
            "description": "JSONata expression for inbound response transformation"
          },
          "inbound_use_case_slug": {
            "type": "string",
            "description": "Slug of the inbound use case to route responses to for async entity processing.\nWhen set, the managed call response is queued to the inbound pipeline and processed\nusing the referenced inbound use case's mapping configuration.\n"
          }
        }
      },
      "ManagedCallOperation": {
        "type": "object",
        "required": [
          "method",
          "path"
        ],
        "description": "HTTP operation configuration for managed calls",
        "properties": {
          "method": {
            "type": "string",
            "enum": [
              "GET",
              "POST",
              "PUT",
              "PATCH",
              "DELETE"
            ]
          },
          "path": {
            "type": "string",
            "description": "URL path template with {{variable}} interpolation"
          },
          "headers": {
            "type": "object",
            "description": "Custom HTTP headers for the request. Values support {{variable}} interpolation from the request payload and {{env.VAR}} references for environment variables.",
            "additionalProperties": {
              "type": "string"
            }
          },
          "query_params": {
            "type": "object",
            "description": "Query parameters for the request. Values support {{variable}} interpolation from the request payload.",
            "additionalProperties": {
              "type": "string"
            }
          }
        }
      },
      "ManagedCallExecuteRequest": {
        "type": "object",
        "required": [
          "integration_id"
        ],
        "properties": {
          "integration_id": {
            "type": "string",
            "format": "uuid",
            "description": "Integration ID"
          },
          "payload": {
            "type": "object",
            "additionalProperties": true,
            "description": "Request payload for the managed call operation"
          },
          "correlation_id": {
            "type": "string",
            "description": "Correlation ID for tracing related events (auto-generated if not provided)"
          }
        }
      },
      "ManagedCallExecuteResponse": {
        "description": "The response from a managed call execution.\nOn success, returns the JSONata-mapped response data directly (no wrapper).\nThe shape is entirely defined by your response_mapping JSONata expression.\nIf no response_mapping is configured, returns the raw external API response.\nCheck the X-Inbound-Event-Id header for inbound pipeline tracking when inbound routing is configured.\n",
        "additionalProperties": true
      },
      "ManagedCallErrorResponse": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "code",
              "message"
            ],
            "properties": {
              "code": {
                "type": "string",
                "description": "Error code (e.g., EXTERNAL_API_ERROR, SSRF_BLOCKED, MANAGED_CALL_EXECUTION_ERROR)"
              },
              "message": {
                "type": "string",
                "description": "Human-readable error message"
              },
              "details": {
                "type": "object",
                "additionalProperties": true,
                "description": "Additional error details (e.g., status code and body for external API errors)"
              }
            }
          }
        }
      },
      "TypeAnnotations": {
        "type": "object",
        "description": "Developer-provided type annotations for a use case's request and response fields",
        "properties": {
          "request": {
            "type": "object",
            "description": "Type annotations for request fields, keyed by dot-path (e.g., \"vendors[].id\" -> \"string\")",
            "additionalProperties": {
              "type": "string"
            }
          },
          "response": {
            "type": "object",
            "description": "Type annotations for response fields",
            "additionalProperties": {
              "type": "string"
            }
          }
        }
      },
      "TypeDescriptor": {
        "type": "object",
        "description": "Describes the inferred type shape of a JSONata expression",
        "required": [
          "kind"
        ],
        "properties": {
          "kind": {
            "type": "string",
            "enum": [
              "object",
              "array",
              "string",
              "number",
              "boolean",
              "null",
              "unknown",
              "union"
            ]
          },
          "properties": {
            "type": "object",
            "description": "For kind=object, the properties and their type descriptors",
            "additionalProperties": {
              "$ref": "#/components/schemas/TypeDescriptor"
            }
          },
          "items": {
            "description": "For kind=array, the type of array items",
            "allOf": [
              {
                "$ref": "#/components/schemas/TypeDescriptor"
              }
            ]
          },
          "source": {
            "type": "string",
            "description": "For kind=unknown, the JSONata path that produced this value"
          },
          "variants": {
            "type": "array",
            "description": "For kind=union, the variant types",
            "items": {
              "$ref": "#/components/schemas/TypeDescriptor"
            }
          }
        }
      },
      "UseCaseTypePreview": {
        "type": "object",
        "description": "Scaffolded type descriptors for a single use case",
        "required": [
          "slug",
          "request_shape",
          "response_shape"
        ],
        "properties": {
          "slug": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "request_shape": {
            "$ref": "#/components/schemas/TypeDescriptor"
          },
          "response_shape": {
            "$ref": "#/components/schemas/TypeDescriptor"
          },
          "existing_annotations": {
            "$ref": "#/components/schemas/TypeAnnotations"
          }
        }
      },
      "GenerateTypesPreviewResponse": {
        "type": "object",
        "required": [
          "use_cases"
        ],
        "properties": {
          "integration_name": {
            "type": "string"
          },
          "use_cases": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/UseCaseTypePreview"
            }
          },
          "previous_version": {
            "type": "string",
            "description": "Previously generated version, if any"
          },
          "suggested_version": {
            "type": "string",
            "description": "Suggested next version based on detected changes"
          },
          "suggested_bump": {
            "type": "string",
            "enum": [
              "major",
              "minor"
            ]
          },
          "detected_changes": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "slug",
                "field",
                "type",
                "description"
              ],
              "properties": {
                "slug": {
                  "type": "string"
                },
                "field": {
                  "type": "string"
                },
                "type": {
                  "type": "string",
                  "enum": [
                    "breaking",
                    "non-breaking"
                  ]
                },
                "description": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "GenerateTypesRequest": {
        "type": "object",
        "required": [
          "package_name",
          "version"
        ],
        "properties": {
          "package_name": {
            "type": "string",
            "description": "npm package name",
            "example": "@epilot/hems-cleverpv"
          },
          "version": {
            "type": "string",
            "description": "Package version",
            "example": "1.0.0"
          },
          "description": {
            "type": "string"
          },
          "domain_package": {
            "type": "string",
            "description": "Domain standard package to extend",
            "example": "@epilot/hems"
          },
          "domain_map_name": {
            "type": "string",
            "description": "Name of the domain UseCaseMap to extend",
            "example": "HemsUseCaseMap"
          },
          "annotations": {
            "type": "object",
            "description": "Type annotations per use case slug",
            "additionalProperties": {
              "$ref": "#/components/schemas/TypeAnnotations"
            }
          }
        }
      },
      "GenerateTypesResponse": {
        "type": "object",
        "required": [
          "package_name",
          "version",
          "files"
        ],
        "properties": {
          "package_name": {
            "type": "string"
          },
          "version": {
            "type": "string"
          },
          "files": {
            "type": "object",
            "description": "Generated file contents keyed by file path",
            "additionalProperties": {
              "type": "string"
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "CommitTypesRequest": {
        "type": "object",
        "required": [
          "package_name",
          "version"
        ],
        "properties": {
          "package_name": {
            "type": "string",
            "description": "npm package name",
            "example": "@epilot/hems-cleverpv"
          },
          "version": {
            "type": "string",
            "description": "Package version",
            "example": "1.0.0"
          },
          "annotations": {
            "type": "object",
            "description": "Type annotations per use case slug",
            "additionalProperties": {
              "$ref": "#/components/schemas/TypeAnnotations"
            }
          }
        }
      },
      "CommitTypesResponse": {
        "type": "object",
        "required": [
          "committed"
        ],
        "properties": {
          "committed": {
            "type": "boolean"
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "FileProxyUseCaseConfiguration": {
        "type": "object",
        "required": [
          "steps",
          "response"
        ],
        "description": "Configuration for file_proxy use cases. Defines how to authenticate and fetch files from external document systems.\n\nThe file proxy download URL always requires `orgId`, `integrationId`, and either `useCaseSlug` (recommended) or `useCaseId` (legacy UUID) as query parameters.\nThe `orgId` is included in the signed URL to establish organization context without requiring authentication.\nAdditional use-case-specific parameters are declared in the `params` array.\n",
        "properties": {
          "secure_proxy": {
            "description": "Optional secure proxy attachment for routing all outbound file proxy requests.\nOnly `use_case_slug` is supported and the referenced secure_proxy use case\nmust belong to the same integration.\n",
            "allOf": [
              {
                "$ref": "#/components/schemas/FileProxySecureProxyAttachment"
              }
            ]
          },
          "auth": {
            "$ref": "#/components/schemas/FileProxyAuth"
          },
          "params": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FileProxyParam"
            },
            "description": "Additional use-case-specific parameters expected in the download URL query string (beyond the required orgId, integrationId, and useCaseSlug or useCaseId)"
          },
          "allowed_origins": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uri",
              "pattern": "^https?://"
            },
            "description": "Additional origins permitted to call /download for this use case (CORS, exact match). Portal origins are always allowed."
          },
          "steps": {
            "type": "array",
            "minItems": 1,
            "items": {
              "$ref": "#/components/schemas/FileProxyStep"
            },
            "description": "Ordered list of HTTP steps to execute to retrieve the file"
          },
          "response": {
            "$ref": "#/components/schemas/FileProxyResponseConfig"
          }
        }
      },
      "FileProxySecureProxyAttachment": {
        "type": "object",
        "required": [
          "use_case_slug"
        ],
        "additionalProperties": false,
        "properties": {
          "use_case_slug": {
            "type": "string",
            "description": "Slug of the secure_proxy use case in the same integration."
          }
        }
      },
      "FileProxyAuth": {
        "type": "object",
        "required": [
          "type",
          "token_url",
          "client_id",
          "client_secret"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "oauth2_client_credentials",
              "oauth2_password"
            ],
            "description": "Authentication type"
          },
          "token_url": {
            "type": "string",
            "description": "Handlebars template for the OAuth2 token endpoint URL"
          },
          "client_id": {
            "type": "string",
            "description": "Handlebars template for the OAuth2 client ID"
          },
          "client_secret": {
            "type": "string",
            "description": "Handlebars template for the OAuth2 client secret"
          },
          "scope": {
            "type": "string",
            "description": "Optional OAuth2 scope"
          },
          "audience": {
            "type": "string",
            "description": "Handlebars template for the OAuth2 audience parameter"
          },
          "resource": {
            "type": "string",
            "description": "Handlebars template for the OAuth2 resource parameter"
          },
          "username": {
            "type": "string",
            "description": "Handlebars template for the OAuth2 resource owner username. Required when type is oauth2_password."
          },
          "password": {
            "type": "string",
            "description": "Handlebars template for the OAuth2 resource owner password. Required when type is oauth2_password."
          },
          "body_params": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Additional key-value pairs to include in the token request body. Values support Handlebars templates."
          },
          "headers": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Additional headers to include in the token request. Values support Handlebars templates."
          },
          "query_params": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Additional query parameters to append to the token URL. Values support Handlebars templates."
          }
        }
      },
      "FileProxyParam": {
        "type": "object",
        "required": [
          "name",
          "required"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "Parameter name as it appears in the query string"
          },
          "required": {
            "type": "boolean",
            "description": "Whether this parameter is required"
          },
          "description": {
            "type": "string",
            "description": "Human-readable description of the parameter"
          }
        }
      },
      "FileProxyStep": {
        "type": "object",
        "required": [
          "url",
          "method",
          "response_type"
        ],
        "properties": {
          "url": {
            "type": "string",
            "description": "Handlebars template for the request URL"
          },
          "method": {
            "type": "string",
            "enum": [
              "GET",
              "POST"
            ],
            "description": "HTTP method"
          },
          "headers": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Handlebars templates for request headers"
          },
          "body": {
            "type": "string",
            "description": "Handlebars template for the request body (POST only)"
          },
          "response_type": {
            "type": "string",
            "enum": [
              "json",
              "binary"
            ],
            "description": "Expected response type"
          }
        }
      },
      "FileProxyResponseConfig": {
        "type": "object",
        "required": [
          "body",
          "encoding"
        ],
        "properties": {
          "body": {
            "type": "string",
            "description": "JSONata expression to extract file content from step results"
          },
          "encoding": {
            "type": "string",
            "enum": [
              "base64",
              "binary"
            ],
            "description": "Encoding of the extracted body"
          },
          "filename": {
            "type": "string",
            "description": "JSONata expression to extract the filename"
          },
          "content_type": {
            "type": "string",
            "description": "JSONata expression to extract the content type"
          }
        }
      },
      "MappingSimulationRequest": {
        "type": "object",
        "required": [
          "mapping_configuration",
          "object_type",
          "format",
          "payload"
        ],
        "properties": {
          "mapping_configuration": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/IntegrationConfigurationV1"
              },
              {
                "$ref": "#/components/schemas/IntegrationConfigurationV2"
              }
            ]
          },
          "object_type": {
            "type": "string",
            "description": "Type of the object/event being mapped.\nFor v1.0: must match a key in mapping_configuration.mapping.objects\nFor v2.0: must match a key in mapping_configuration.mapping.events\n"
          },
          "format": {
            "type": "string",
            "enum": [
              "json",
              "xml"
            ],
            "default": "json",
            "description": "Format of the payload data"
          },
          "payload": {
            "oneOf": [
              {
                "type": "string",
                "description": "The serialized object data payload (JSON, XML, etc.) as a string"
              },
              {
                "type": "object",
                "description": "Direct JSON object (will be automatically serialized)",
                "additionalProperties": true
              }
            ],
            "description": "The object data payload - can be either a serialized string or a direct JSON object"
          }
        }
      },
      "MappingSimulationV2Request": {
        "type": "object",
        "description": "Request for v2 mapping simulation. Uses the same configuration format stored in integration use case resources,\nmaking it easier to test configurations before saving them.\n",
        "required": [
          "event_configuration",
          "format",
          "payload"
        ],
        "properties": {
          "event_configuration": {
            "$ref": "#/components/schemas/InboundIntegrationEventConfiguration"
          },
          "format": {
            "type": "string",
            "enum": [
              "json",
              "xml"
            ],
            "default": "json",
            "description": "Format of the payload data"
          },
          "payload": {
            "oneOf": [
              {
                "type": "string",
                "description": "The serialized event data payload (JSON, XML, etc.) as a string"
              },
              {
                "type": "object",
                "description": "Direct JSON object (will be automatically serialized)",
                "additionalProperties": true
              }
            ],
            "description": "The event data payload - can be either a serialized string or a direct JSON object"
          }
        }
      },
      "MappingSimulationResponse": {
        "type": "object",
        "required": [
          "entity_updates"
        ],
        "properties": {
          "entity_updates": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EntityUpdate"
            }
          },
          "meter_readings_updates": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MeterReadingUpdate"
            }
          },
          "warnings": {
            "type": "array",
            "description": "Validation warnings about the configuration (e.g., unique_ids referencing non-indexed fields)",
            "items": {
              "$ref": "#/components/schemas/MappingSimulationWarning"
            }
          }
        }
      },
      "MappingSimulationWarning": {
        "type": "object",
        "required": [
          "entity_schema",
          "field",
          "message"
        ],
        "properties": {
          "entity_schema": {
            "type": "string",
            "description": "The entity schema slug where the issue was found"
          },
          "field": {
            "type": "string",
            "description": "The field name that caused the warning"
          },
          "message": {
            "type": "string",
            "description": "Description of the validation issue"
          }
        }
      },
      "EntityUpdate": {
        "type": "object",
        "required": [
          "entity_slug",
          "unique_identifiers",
          "attributes"
        ],
        "properties": {
          "entity_slug": {
            "type": "string",
            "description": "The entity type slug"
          },
          "unique_identifiers": {
            "type": "object",
            "description": "Unique identifier mappings for this entity",
            "additionalProperties": true
          },
          "attributes": {
            "type": "object",
            "description": "Mapped attribute values",
            "additionalProperties": true
          }
        }
      },
      "MeterReadingUpdate": {
        "type": "object",
        "required": [
          "meter",
          "attributes"
        ],
        "properties": {
          "meter": {
            "type": "object",
            "required": [
              "$entity_unique_ids"
            ],
            "properties": {
              "$entity_unique_ids": {
                "type": "object",
                "additionalProperties": true,
                "description": "Unique identifiers for the meter"
              }
            }
          },
          "meter_counter": {
            "type": "object",
            "properties": {
              "$entity_unique_ids": {
                "type": "object",
                "additionalProperties": true,
                "description": "Unique identifiers for the meter counter"
              }
            }
          },
          "attributes": {
            "type": "object",
            "additionalProperties": true,
            "description": "Meter reading attributes. Required: external_id, timestamp, source, value. `timestamp` must be ISO 8601 — either `YYYY-MM-DD` or `YYYY-MM-DDTHH:mm:ss` (with optional fractional seconds and optional `Z` / `±HH:mm` timezone offset); non-ISO formats (e.g. `DD.MM.YYYY` or epoch numbers) are rejected and must be converted upstream via a `jsonataExpression` (e.g. `$fromMillis(...)`). Date-only values are normalized to midnight UTC and offset-less date-times are anchored to UTC before being forwarded to the metering API. `source` must be one of: ECP, ERP, 360, journey-submission. `reason` (optional) must be one of: regular, irregular, last, first, meter_change, contract_change, meter_adjustment (or empty/null)."
          }
        }
      },
      "IntegrationConfigurationV1": {
        "type": "object",
        "required": [
          "mapping"
        ],
        "properties": {
          "version": {
            "type": "string",
            "enum": [
              "1.0"
            ],
            "default": "1.0",
            "description": "Mapping specification version"
          },
          "mapping": {
            "type": "object",
            "required": [
              "objects"
            ],
            "properties": {
              "objects": {
                "type": "object",
                "description": "[v1.0] Object type mappings",
                "additionalProperties": {
                  "$ref": "#/components/schemas/IntegrationObjectV1"
                }
              }
            }
          }
        }
      },
      "IntegrationObjectV1": {
        "type": "object",
        "required": [
          "unique_ids",
          "fields"
        ],
        "properties": {
          "unique_ids": {
            "type": "object",
            "description": "Mapping of entity types to their unique identifier field mappings",
            "additionalProperties": {
              "oneOf": [
                {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "description": "List of local keys (must be present under the mapping \"fields\"!)"
                  }
                },
                {
                  "type": "object",
                  "description": "Map of remote keys to local entity keys",
                  "additionalProperties": {
                    "type": "string"
                  }
                }
              ]
            }
          },
          "fields": {
            "type": "array",
            "description": "Field mapping definitions",
            "items": {
              "$ref": "#/components/schemas/IntegrationFieldV1"
            }
          }
        }
      },
      "IntegrationFieldV1": {
        "type": "object",
        "required": [
          "entity",
          "attribute"
        ],
        "properties": {
          "entity": {
            "type": "string",
            "description": "Target entity slug"
          },
          "attribute": {
            "type": "string",
            "description": "Target attribute name"
          },
          "field": {
            "type": "string",
            "description": "Source field name (mutually exclusive with jsonataExpression)"
          },
          "jsonataExpression": {
            "type": "string",
            "description": "JSONata expression for transformation (mutually exclusive with field)"
          }
        }
      },
      "IntegrationConfigurationV2": {
        "type": "object",
        "required": [
          "version",
          "mapping"
        ],
        "properties": {
          "version": {
            "type": "string",
            "enum": [
              "2.0"
            ],
            "description": "Mapping specification version"
          },
          "mapping": {
            "type": "object",
            "required": [
              "events"
            ],
            "properties": {
              "events": {
                "type": "object",
                "description": "[v2.0] Event type mappings",
                "additionalProperties": {
                  "$ref": "#/components/schemas/InboundIntegrationEventConfiguration"
                }
              }
            }
          }
        }
      },
      "OutboundMapping": {
        "type": "object",
        "required": [
          "name",
          "enabled",
          "delivery"
        ],
        "description": "A mapping that delivers an event to an external system — either pushed to a webhook (with a JSONata payload transformation) or made available on the pull-based poll queue (raw event payload, no transformation)",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Unique identifier for this mapping"
          },
          "name": {
            "type": "string",
            "description": "Human-readable name for this mapping",
            "example": "ERP Contract Sync"
          },
          "jsonata_expression": {
            "type": "string",
            "description": "JSONata expression to transform the event payload. Required for webhook delivery; ignored for poll delivery.",
            "example": "{ \"id\": entity._id, \"customer\": entity.customer_name }"
          },
          "enabled": {
            "type": "boolean",
            "description": "Whether this mapping is active",
            "default": true
          },
          "delivery": {
            "$ref": "#/components/schemas/DeliveryConfig"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Timestamp when the mapping was created"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "description": "Timestamp when the mapping was last updated"
          }
        }
      },
      "DeliveryConfig": {
        "description": "Configuration for how the event should be delivered. webhook = push delivery via svc-webhooks (JSONata-transformed payload); poll = pull-based queue delivery where the consumer fetches items via the poll API (raw event payload)",
        "oneOf": [
          {
            "$ref": "#/components/schemas/WebhookDeliveryConfig"
          },
          {
            "$ref": "#/components/schemas/PollDeliveryConfig"
          }
        ],
        "discriminator": {
          "propertyName": "type",
          "mapping": {
            "webhook": "#/components/schemas/WebhookDeliveryConfig",
            "poll": "#/components/schemas/PollDeliveryConfig"
          }
        }
      },
      "WebhookDeliveryConfig": {
        "type": "object",
        "required": [
          "type",
          "webhook_id"
        ],
        "description": "Push delivery of the transformed event to a webhook via svc-webhooks",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "webhook"
            ],
            "description": "Delivery mechanism type"
          },
          "webhook_id": {
            "type": "string",
            "description": "Reference to the webhook configuration in svc-webhooks"
          },
          "webhook_name": {
            "type": "string",
            "description": "Cached webhook name for display purposes"
          },
          "webhook_url": {
            "type": "string",
            "description": "Cached webhook URL for display purposes"
          }
        }
      },
      "PollDeliveryConfig": {
        "type": "object",
        "required": [
          "type"
        ],
        "description": "Pull-based queue delivery. Items carry the raw standardized event-catalog payload; no JSONata mapping is applied in poll mode. Consumers fetch and acknowledge items via the poll API.",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "poll"
            ],
            "description": "Delivery mechanism type"
          },
          "retention_days": {
            "type": "integer",
            "minimum": 1,
            "maximum": 90,
            "default": 30,
            "description": "How long undelivered queue items are retained before expiry"
          },
          "poison_policy": {
            "type": "string",
            "enum": [
              "dead_letter",
              "block"
            ],
            "default": "dead_letter",
            "description": "What happens when an item exhausts max_delivery_attempts: dead_letter routes the exhausted item to the dead-letter queue and advances past it so the stream keeps flowing; block halts the queue at that item until operator/consumer action removes it."
          },
          "max_delivery_attempts": {
            "type": "integer",
            "minimum": 1,
            "maximum": 100,
            "default": 5,
            "description": "Maximum delivery attempts before the poison_policy is applied"
          }
        }
      },
      "OutboundStatusResponse": {
        "type": "object",
        "required": [
          "useCases"
        ],
        "properties": {
          "useCases": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OutboundUseCaseStatus"
            }
          }
        }
      },
      "OutboundUseCaseStatus": {
        "type": "object",
        "required": [
          "useCaseId",
          "name",
          "useCaseEnabled",
          "status"
        ],
        "properties": {
          "useCaseId": {
            "type": "string",
            "format": "uuid",
            "description": "Unique identifier for the use case"
          },
          "name": {
            "type": "string",
            "description": "Human-readable name of the use case"
          },
          "useCaseEnabled": {
            "type": "boolean",
            "description": "Whether the use case is enabled"
          },
          "eventCatalogEvent": {
            "type": "string",
            "description": "The Event Catalog event name that triggers this outbound flow",
            "example": "contract.created"
          },
          "eventEnabled": {
            "type": "boolean",
            "nullable": true,
            "description": "Whether the event is enabled in Event Catalog. Null if the API is unreachable."
          },
          "webhooks": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookStatus"
            }
          },
          "status": {
            "type": "string",
            "enum": [
              "ok",
              "conflict",
              "disabled"
            ],
            "description": "Overall status of the use case:\n- 'ok': Use case is enabled and all dependencies are properly configured\n- 'conflict': Use case has configuration issues (disabled events/webhooks while enabled)\n- 'disabled': Use case is disabled\n"
          },
          "conflicts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OutboundConflict"
            },
            "description": "List of detected conflicts, if any"
          },
          "poll": {
            "$ref": "#/components/schemas/OutboundPollStatus"
          }
        }
      },
      "OutboundPollStatus": {
        "type": "object",
        "description": "Queue/consumer health for a poll-mode use case. Present only on use\ncases with a poll delivery mapping — webhook-only use cases are\nunaffected. Depth/age/DLQ numbers are first-page approximations.\n",
        "required": [
          "queue_depth",
          "oldest_unconsumed_age_seconds",
          "last_poll_at",
          "last_ack_at",
          "blocked",
          "dlq_count"
        ],
        "properties": {
          "queue_depth": {
            "type": "integer",
            "description": "Unconsumed messages attributable to this use case (first-page approximation)"
          },
          "oldest_unconsumed_age_seconds": {
            "type": "integer",
            "nullable": true,
            "description": "Age of the oldest unconsumed message in seconds — null when the queue is empty"
          },
          "last_poll_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Timestamp of the last successful poll lease — null before the first poll"
          },
          "last_ack_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Timestamp of the last committed acknowledgment — null before the first ack"
          },
          "blocked": {
            "type": "boolean",
            "description": "Whether the integration's outbound stream is currently halted by a\nblocked head message (poison_policy 'block'). Stream-level flag —\nthe same value is reported on every poll use case of the\nintegration, because the stream spans them.\n"
          },
          "dlq_count": {
            "type": "integer",
            "description": "Dead-lettered messages of this use case awaiting redrive or expiry (first-page approximation)"
          }
        }
      },
      "WebhookStatus": {
        "type": "object",
        "required": [
          "webhookId"
        ],
        "properties": {
          "webhookId": {
            "type": "string",
            "description": "Unique identifier for the webhook"
          },
          "webhookName": {
            "type": "string",
            "description": "Human-readable name of the webhook"
          },
          "enabled": {
            "type": "boolean",
            "nullable": true,
            "description": "Whether the webhook is enabled. Null if the API is unreachable."
          }
        }
      },
      "OutboundConflict": {
        "type": "object",
        "required": [
          "type",
          "message"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "event_disabled",
              "all_webhooks_disabled",
              "event_enabled_while_disabled",
              "webhook_enabled_while_disabled",
              "stream_blocked",
              "dlq_items_present"
            ],
            "description": "Type of conflict:\n- 'event_disabled': Event catalog event is disabled while use case is enabled\n- 'all_webhooks_disabled': All webhooks are disabled while use case is enabled\n- 'event_enabled_while_disabled': Event is enabled while use case is disabled\n- 'webhook_enabled_while_disabled': A webhook is enabled while use case is disabled\n- 'stream_blocked': The outbound stream is halted by a poison message awaiting operator action or consumer ack (poll mode)\n- 'dlq_items_present': Dead-lettered messages await redrive or expiry (poll mode)\n"
          },
          "webhookId": {
            "type": "string",
            "description": "Webhook ID (only present for webhook_enabled_while_disabled conflicts)"
          },
          "message": {
            "type": "string",
            "description": "Human-readable description of the conflict"
          }
        }
      },
      "PollOutboundMessagesRequest": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "limit": {
            "type": "integer",
            "maximum": 100,
            "minimum": 1,
            "default": 10,
            "description": "Maximum number of messages to lease in this batch. The ~5.5 MB\nresponse cap may truncate the batch earlier when payloads are\nlarge — the leased run shrinks accordingly.\n"
          }
        }
      },
      "OutboundMessage": {
        "type": "object",
        "required": [
          "id",
          "lease_token",
          "use_case_id",
          "event_name",
          "event_id",
          "group",
          "payload",
          "enqueued_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Opaque message id (msg_…) — stable per message across leases"
          },
          "lease_token": {
            "type": "string",
            "description": "Opaque lease token (lt_…) — echo back on ack"
          },
          "use_case_id": {
            "type": "string",
            "description": "The poll-mode use case that produced this message"
          },
          "event_name": {
            "type": "string",
            "description": "Standardized event name (e.g. contract.updated)"
          },
          "event_id": {
            "type": "string",
            "description": "Unique id of the originating event"
          },
          "group": {
            "type": "string",
            "description": "Ordering group — messages sharing a group are strictly ordered,\ndistinct groups are independent. Constant \"0\" in v1.\n"
          },
          "payload": {
            "type": "object",
            "additionalProperties": true,
            "description": "The raw standardized event-catalog event, always inlined as-is"
          },
          "enqueued_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the message was enqueued"
          }
        }
      },
      "PollOutboundMessagesResponse": {
        "type": "object",
        "required": [
          "messages",
          "visibility_timeout_seconds",
          "has_more"
        ],
        "properties": {
          "messages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OutboundMessage"
            },
            "description": "The leased batch in strict stream order (empty when contended or drained)"
          },
          "visibility_timeout_seconds": {
            "type": "integer",
            "description": "Effective visibility timeout for this lease — a per-integration\nserver-side setting (default 300 seconds)\n"
          },
          "has_more": {
            "type": "boolean",
            "description": "Whether more messages are available beyond this batch"
          }
        }
      },
      "AckOutboundMessagesRequest": {
        "type": "object",
        "required": [
          "acks"
        ],
        "properties": {
          "acks": {
            "type": "array",
            "minItems": 1,
            "maxItems": 100,
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "id",
                "lease_token"
              ],
              "properties": {
                "id": {
                  "type": "string",
                  "description": "The message id (msg_…) to acknowledge"
                },
                "lease_token": {
                  "type": "string",
                  "description": "The lease token (lt_…) returned by the poll that leased this message"
                }
              }
            }
          }
        }
      },
      "AckResult": {
        "type": "object",
        "required": [
          "id",
          "status"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "The acknowledged message id"
          },
          "status": {
            "type": "string",
            "enum": [
              "accepted",
              "rejected"
            ]
          },
          "reason": {
            "type": "string",
            "enum": [
              "stale_lease",
              "out_of_order",
              "not_found"
            ],
            "description": "Rejection reason — present only when status is rejected"
          }
        }
      },
      "AckOutboundMessagesResponse": {
        "type": "object",
        "required": [
          "results"
        ],
        "properties": {
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AckResult"
            },
            "description": "Per-id acknowledgement outcome"
          }
        }
      },
      "OutboundDlqMessage": {
        "type": "object",
        "required": [
          "id",
          "use_case_id",
          "event_name",
          "event_id",
          "dead_lettered_at",
          "delivery_attempts"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Opaque message id (msg_…) of the dead-lettered message"
          },
          "use_case_id": {
            "type": "string",
            "description": "The poll-mode use case that produced this message"
          },
          "event_name": {
            "type": "string",
            "description": "Standardized event name (e.g. contract.updated)"
          },
          "event_id": {
            "type": "string",
            "description": "Unique id of the originating event"
          },
          "enqueued_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the message was originally enqueued"
          },
          "dead_lettered_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the message was dead-lettered"
          },
          "delivery_attempts": {
            "type": "integer",
            "description": "Delivery attempts at the moment the message was dead-lettered"
          },
          "reason": {
            "type": "string",
            "description": "Why the message was dead-lettered (policy or operator reason)"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the DLQ entry expires (retention window re-armed at dead-letter time)"
          }
        }
      },
      "OutboundDlqListResponse": {
        "type": "object",
        "required": [
          "items"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OutboundDlqMessage"
            },
            "description": "Dead-lettered messages, oldest first"
          },
          "next_token": {
            "type": "string",
            "description": "Opaque pagination token — present when more entries exist"
          }
        }
      },
      "RedriveOutboundDlqRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "ids"
        ],
        "properties": {
          "ids": {
            "type": "array",
            "minItems": 1,
            "maxItems": 100,
            "items": {
              "type": "string"
            },
            "description": "Message ids (msg_…) of the DLQ entries to redrive"
          }
        }
      },
      "RedriveOutboundDlqResult": {
        "type": "object",
        "required": [
          "id",
          "status"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "The requested message id"
          },
          "status": {
            "type": "string",
            "enum": [
              "redriven",
              "not_found"
            ],
            "description": "Outcome — `redriven` re-enqueued at the tail; `not_found` for\nunknown ids or entries concurrently redriven/expired\n"
          }
        }
      },
      "RedriveOutboundDlqResponse": {
        "type": "object",
        "required": [
          "results"
        ],
        "properties": {
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RedriveOutboundDlqResult"
            },
            "description": "Per-id redrive outcome, input order preserved"
          }
        }
      },
      "UnblockOutboundStreamRequest": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "reason": {
            "type": "string",
            "maxLength": 500,
            "description": "Operator reason recorded on the dead-lettered head"
          }
        }
      },
      "UnblockOutboundStreamResponse": {
        "type": "object",
        "required": [
          "unblocked"
        ],
        "properties": {
          "unblocked": {
            "type": "boolean",
            "description": "Whether a blocked head was skipped (false = no-op, stream was not blocked)"
          },
          "dead_lettered_id": {
            "type": "string",
            "description": "Message id of the skipped head — present only when unblocked is true"
          }
        }
      },
      "RelationConfig": {
        "type": "object",
        "required": [
          "operation"
        ],
        "properties": {
          "operation": {
            "type": "string",
            "enum": [
              "_set",
              "_append",
              "_append_all"
            ],
            "description": "Relation operation:\n- '_set': Replace all existing relations with the specified items\n- '_append': Add new unique items to existing relations (deduplicates by entity_id)\n- '_append_all': Add all items to existing relations (no deduplication, allows duplicates)\n"
          },
          "items": {
            "type": "array",
            "description": "Array of relation item configurations",
            "items": {
              "$ref": "#/components/schemas/RelationItemConfig"
            }
          },
          "jsonataExpression": {
            "type": "string",
            "description": "JSONata expression that returns relation items array (alternative to 'items')"
          }
        }
      },
      "RelationItemConfig": {
        "type": "object",
        "required": [
          "entity_schema",
          "unique_ids"
        ],
        "properties": {
          "entity_schema": {
            "type": "string",
            "description": "Related entity schema"
          },
          "_tags": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Optional tags for this relation"
          },
          "unique_ids": {
            "type": "array",
            "description": "Unique identifier mappings for the related entity",
            "items": {
              "$ref": "#/components/schemas/RelationUniqueIdField"
            }
          }
        }
      },
      "RelationUniqueIdField": {
        "type": "object",
        "required": [
          "attribute"
        ],
        "properties": {
          "attribute": {
            "type": "string",
            "description": "Target attribute name in the related entity"
          },
          "_type": {
            "$ref": "#/components/schemas/RepeatableFieldType"
          },
          "field": {
            "type": "string",
            "description": "Source field name from the event data"
          },
          "jsonataExpression": {
            "type": "string",
            "description": "JSONata expression to compute the value"
          },
          "constant": {
            "description": "Constant value (any type)"
          }
        }
      },
      "RelationRefsConfig": {
        "type": "object",
        "description": "Configuration for relation references ($relation_ref).\nRelation references link to a specific item within a repeatable attribute on a related entity.\nCommon use case: referencing a specific address within a contact's address list.\n",
        "required": [
          "operation"
        ],
        "properties": {
          "operation": {
            "type": "string",
            "enum": [
              "_set",
              "_append",
              "_append_all"
            ],
            "description": "Relation reference operation:\n- '_set': Replace all existing relation_refs with the specified items\n- '_append': Add new unique items to existing relation_refs (deduplicates by entity_id + _id)\n- '_append_all': Add all items to existing relation_refs (no deduplication, allows duplicates)\n"
          },
          "items": {
            "type": "array",
            "description": "Array of relation reference item configurations",
            "items": {
              "$ref": "#/components/schemas/RelationRefItemConfig"
            }
          },
          "jsonataExpression": {
            "type": "string",
            "description": "JSONata expression that returns relation_ref items array (alternative to 'items')"
          }
        }
      },
      "RelationRefItemConfig": {
        "type": "object",
        "description": "Configuration for a single relation reference item",
        "required": [
          "entity_schema",
          "unique_ids",
          "path",
          "value"
        ],
        "properties": {
          "entity_schema": {
            "type": "string",
            "description": "Schema of the related entity (e.g., \"contact\")"
          },
          "unique_ids": {
            "type": "array",
            "description": "Unique identifier mappings for the related entity",
            "items": {
              "$ref": "#/components/schemas/RelationUniqueIdField"
            }
          },
          "path": {
            "type": "string",
            "description": "Attribute path on the related entity (e.g., \"address\")"
          },
          "value": {
            "$ref": "#/components/schemas/RelationRefValueConfig"
          }
        }
      },
      "RelationRefValueConfig": {
        "type": "object",
        "description": "Configuration for the value to set on the related entity's attribute",
        "required": [
          "attribute"
        ],
        "properties": {
          "attribute": {
            "type": "string",
            "description": "Target attribute name on the related entity"
          },
          "operation": {
            "type": "string",
            "enum": [
              "_set",
              "_append",
              "_append_all"
            ],
            "description": "Operation for the attribute value:\n- '_set': Replace the attribute value\n- '_append': Add new unique items (deduplicates)\n- '_append_all': Add all items (no deduplication)\n"
          },
          "field": {
            "type": "string",
            "description": "Source field name from the event data"
          },
          "jsonataExpression": {
            "type": "string",
            "description": "JSONata expression to compute the value"
          },
          "constant": {
            "description": "Constant value (any type)"
          }
        }
      },
      "RepeatableFieldType": {
        "type": "string",
        "enum": [
          "email",
          "phone"
        ],
        "description": "Type hint for repeatable fields that require special search handling.\nThese fields are stored as arrays of objects (e.g., email: [{ email: \"value\" }]).\n"
      },
      "ReplayEventsRequest": {
        "type": "object",
        "required": [
          "event_ids"
        ],
        "properties": {
          "event_ids": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "minItems": 1,
            "maxItems": 100,
            "description": "List of event IDs to replay. Maximum 100 events per request."
          }
        }
      },
      "QueryEventsRequest": {
        "type": "object",
        "properties": {
          "event_id": {
            "type": "string",
            "description": "Filter by event ID"
          },
          "event_type": {
            "type": "string",
            "enum": [
              "CREATE",
              "UPDATE",
              "DELETE"
            ],
            "description": "Filter by event type"
          },
          "correlation_id": {
            "type": "string",
            "description": "Filter by correlation ID"
          },
          "object_type": {
            "type": "string",
            "description": "Filter by object type"
          },
          "event_name": {
            "type": "string",
            "description": "Filter by event name (alias for object_type)"
          },
          "use_case_id": {
            "type": "string",
            "minLength": 1,
            "description": "Filter by use case ID"
          },
          "limit": {
            "type": "integer",
            "description": "Maximum number of results to return",
            "example": 25,
            "default": 25,
            "minimum": 1,
            "maximum": 25
          },
          "cursor": {
            "type": "object",
            "description": "Cursor for pagination. Use the next_cursor from the previous response to get the next page.",
            "properties": {
              "event_time": {
                "type": "string",
                "format": "date-time",
                "description": "Timestamp from the last event in the previous page",
                "example": "2025-10-31T12:34:56Z"
              },
              "event_id": {
                "type": "string",
                "description": "Event ID from the last event in the previous page",
                "example": "evt_1234567890abcdef"
              }
            }
          }
        }
      },
      "QueryInboundMonitoringEventsRequest": {
        "type": "object",
        "properties": {
          "use_case_id": {
            "type": "string",
            "format": "uuid",
            "description": "Filter by use case ID"
          },
          "event_type": {
            "type": "string",
            "enum": [
              "CREATE",
              "UPDATE",
              "DELETE",
              "TRIGGER"
            ],
            "description": "Filter by event type"
          },
          "sync_type": {
            "type": "string",
            "enum": [
              "entity",
              "meter_reading",
              "webhook",
              "api_deprecation"
            ],
            "description": "Filter by sync type"
          },
          "status": {
            "type": "string",
            "enum": [
              "success",
              "error",
              "skipped",
              "warning"
            ],
            "description": "Filter by processing status"
          },
          "error_category": {
            "type": "string",
            "enum": [
              "validation",
              "configuration",
              "downstream_api",
              "timeout",
              "system"
            ],
            "description": "Filter by error category (only applicable when status=error)"
          },
          "correlation_id": {
            "type": "string",
            "description": "Filter by correlation ID"
          },
          "object_type": {
            "type": "string",
            "description": "Filter by object type (e.g., 'contract', 'meter')"
          },
          "event_name": {
            "type": "string",
            "description": "Filter by event name (alias for object_type)"
          },
          "event_id": {
            "type": "string",
            "description": "Filter by event ID to find a specific event"
          },
          "from_date": {
            "type": "string",
            "format": "date-time",
            "description": "Filter events from this date (inclusive)",
            "example": "2025-01-01T00:00:00Z"
          },
          "to_date": {
            "type": "string",
            "format": "date-time",
            "description": "Filter events until this date (inclusive)",
            "example": "2025-01-31T23:59:59Z"
          },
          "limit": {
            "type": "integer",
            "description": "Maximum number of results to return",
            "example": 50,
            "default": 50,
            "minimum": 1,
            "maximum": 100
          },
          "cursor": {
            "type": "object",
            "description": "Cursor for pagination",
            "properties": {
              "completed_at": {
                "type": "string",
                "format": "date-time",
                "description": "Timestamp from the last event in the previous page"
              },
              "event_id": {
                "type": "string",
                "description": "Event ID from the last event in the previous page"
              }
            }
          }
        }
      },
      "QueryAccessLogsRequest": {
        "type": "object",
        "properties": {
          "token_id": {
            "type": "string",
            "description": "Filter by a specific access token ID (e.g., 'api_5ZugdRXasLfWBypHi93Fk').\nMust be one of the access_token_ids linked to the integration.\nIf omitted, returns logs for all access tokens linked to the integration.\n",
            "example": "api_5ZugdRXasLfWBypHi93Fk"
          },
          "service": {
            "type": "string",
            "description": "Filter by service name (e.g., 'entity', 'metering', 'submission-api')",
            "example": "entity"
          },
          "method": {
            "type": "string",
            "enum": [
              "GET",
              "POST",
              "PUT",
              "PATCH",
              "DELETE",
              "OPTIONS",
              "HEAD"
            ],
            "description": "Filter by HTTP method"
          },
          "path": {
            "type": "string",
            "description": "Filter by request path (partial match)",
            "example": "/v1/entity"
          },
          "status": {
            "type": "integer",
            "description": "Filter by HTTP status code",
            "example": 200
          },
          "from_date": {
            "type": "string",
            "format": "date-time",
            "description": "Filter logs from this date (inclusive)",
            "example": "2025-01-01T00:00:00Z"
          },
          "to_date": {
            "type": "string",
            "format": "date-time",
            "description": "Filter logs until this date (inclusive)",
            "example": "2025-01-31T23:59:59Z"
          },
          "limit": {
            "type": "integer",
            "description": "Maximum number of results to return",
            "example": 50,
            "default": 50,
            "minimum": 1,
            "maximum": 100
          },
          "cursor": {
            "type": "object",
            "description": "Cursor for pagination (infinite scroll)",
            "properties": {
              "timestamp": {
                "type": "string",
                "format": "date-time",
                "description": "Timestamp from the last log entry in the previous page"
              },
              "request_id": {
                "type": "string",
                "description": "Request ID from the last log entry in the previous page"
              }
            }
          }
        }
      },
      "AccessLogEntry": {
        "type": "object",
        "properties": {
          "timestamp": {
            "type": "string",
            "format": "date-time",
            "description": "When the request was made"
          },
          "environment": {
            "type": "string",
            "description": "Environment (e.g., 'dev', 'prod')"
          },
          "service": {
            "type": "string",
            "description": "Service name (e.g., 'entity', 'metering')"
          },
          "request_id": {
            "type": "string",
            "description": "Unique request identifier"
          },
          "method": {
            "type": "string",
            "description": "HTTP method"
          },
          "path": {
            "type": "string",
            "description": "Request path"
          },
          "status": {
            "type": "integer",
            "description": "HTTP status code"
          },
          "response_latency_ms": {
            "type": "integer",
            "description": "Response latency in milliseconds"
          },
          "response_length": {
            "type": "integer",
            "description": "Response body length in bytes"
          },
          "token_id": {
            "type": "string",
            "description": "Access token identifier"
          },
          "org_id": {
            "type": "string",
            "description": "Organization ID"
          },
          "origin": {
            "type": "string",
            "description": "Request origin header"
          },
          "source_ip": {
            "type": "string",
            "description": "Client IP address"
          }
        }
      },
      "GetMonitoringStatsRequest": {
        "type": "object",
        "properties": {
          "from_date": {
            "type": "string",
            "format": "date-time",
            "description": "Start date for statistics period (inclusive)",
            "example": "2025-01-01T00:00:00Z"
          },
          "to_date": {
            "type": "string",
            "format": "date-time",
            "description": "End date for statistics period (inclusive)",
            "example": "2025-01-31T23:59:59Z"
          },
          "inbound_group_by": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "use_case_id",
                "sync_type",
                "status",
                "error_category",
                "object_type",
                "event_name",
                "date"
              ]
            },
            "description": "Fields to group inbound statistics by",
            "example": [
              "use_case_id",
              "status"
            ]
          },
          "outbound_group_by": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "event_name",
                "status",
                "webhook_config_id",
                "date"
              ]
            },
            "description": "Fields to group outbound statistics by",
            "example": [
              "event_name",
              "status"
            ]
          }
        }
      },
      "GetMonitoringTimeSeriesRequest": {
        "type": "object",
        "required": [
          "from_date",
          "interval"
        ],
        "properties": {
          "from_date": {
            "type": "string",
            "format": "date-time",
            "description": "Start date for the time series (inclusive)",
            "example": "2025-01-01T00:00:00Z"
          },
          "to_date": {
            "type": "string",
            "format": "date-time",
            "description": "End date for the time series (inclusive). Defaults to current time if not specified.",
            "example": "2025-01-31T23:59:59Z"
          },
          "interval": {
            "type": "string",
            "enum": [
              "5m",
              "10m",
              "30m",
              "1h",
              "3h",
              "1d"
            ],
            "description": "The time bucket interval for aggregation",
            "example": "1h"
          },
          "direction": {
            "type": "string",
            "enum": [
              "inbound",
              "outbound",
              "both"
            ],
            "default": "both",
            "description": "Filter by event direction. Defaults to both.",
            "example": "both"
          }
        }
      },
      "TimeSeriesBucket": {
        "type": "object",
        "required": [
          "timestamp"
        ],
        "properties": {
          "timestamp": {
            "type": "string",
            "format": "date-time",
            "description": "The start timestamp of the bucket"
          },
          "inbound": {
            "type": "object",
            "nullable": true,
            "description": "Inbound event counts for this bucket. Null when direction is outbound.",
            "properties": {
              "success_count": {
                "type": "integer"
              },
              "error_count": {
                "type": "integer"
              },
              "warning_count": {
                "type": "integer"
              },
              "skipped_count": {
                "type": "integer"
              },
              "total_count": {
                "type": "integer"
              }
            }
          },
          "outbound": {
            "type": "object",
            "nullable": true,
            "description": "Outbound event counts for this bucket. Null when direction is inbound.",
            "properties": {
              "success_count": {
                "type": "integer"
              },
              "error_count": {
                "type": "integer"
              },
              "pending_count": {
                "type": "integer"
              },
              "total_count": {
                "type": "integer"
              }
            }
          }
        }
      },
      "QueryOutboundMonitoringEventsRequest": {
        "type": "object",
        "properties": {
          "event_name": {
            "type": "string",
            "description": "Filter by event name (event_catalog_event). If not specified, returns events for all linked event names in the integration's outbound use cases.",
            "example": "automation_flow_target"
          },
          "status": {
            "type": "string",
            "enum": [
              "succeeded",
              "failed",
              "pending"
            ],
            "description": "Filter by delivery status"
          },
          "webhook_config_id": {
            "type": "string",
            "description": "Filter by webhook configuration ID"
          },
          "from_date": {
            "type": "string",
            "format": "date-time",
            "description": "Filter events from this date (inclusive)",
            "example": "2025-01-01T00:00:00Z"
          },
          "to_date": {
            "type": "string",
            "format": "date-time",
            "description": "Filter events until this date (inclusive)",
            "example": "2025-01-31T23:59:59Z"
          },
          "limit": {
            "type": "integer",
            "description": "Maximum number of results to return",
            "example": 50,
            "default": 50,
            "minimum": 1,
            "maximum": 100
          },
          "cursor": {
            "type": "object",
            "description": "Cursor for pagination",
            "properties": {
              "created_at": {
                "type": "string",
                "format": "date-time",
                "description": "Timestamp from the last event in the previous page"
              },
              "event_id": {
                "type": "string",
                "description": "Event ID from the last event in the previous page"
              }
            }
          }
        }
      },
      "OutboundMonitoringEvent": {
        "type": "object",
        "required": [
          "org_id",
          "event_id",
          "event_name",
          "status",
          "created_at"
        ],
        "properties": {
          "org_id": {
            "type": "string",
            "description": "Organization ID"
          },
          "event_id": {
            "type": "string",
            "description": "Unique event identifier"
          },
          "event_name": {
            "type": "string",
            "description": "Event name (event_catalog_event)"
          },
          "status": {
            "type": "string",
            "enum": [
              "succeeded",
              "failed",
              "pending"
            ],
            "description": "Delivery status"
          },
          "url": {
            "type": "string",
            "description": "Target URL"
          },
          "http_method": {
            "type": "string",
            "description": "HTTP method used (e.g., POST)"
          },
          "http_response": {
            "type": "object",
            "description": "HTTP response details (status_code, message, headers)",
            "additionalProperties": true
          },
          "webhook_config_id": {
            "type": "string",
            "description": "Webhook configuration ID"
          },
          "metadata": {
            "type": "object",
            "description": "Additional metadata (webhook_id, organization details, correlation_id, etc.)",
            "additionalProperties": true
          },
          "execution_context": {
            "type": "object",
            "description": "Execution context (execution_arn, state_machine_arn, etc.)",
            "additionalProperties": true
          },
          "payload": {
            "type": "object",
            "description": "Payload that was sent",
            "additionalProperties": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the event was created"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the event was last updated"
          }
        }
      },
      "MonitoringStats": {
        "type": "object",
        "required": [
          "inbound",
          "outbound"
        ],
        "properties": {
          "inbound": {
            "type": "object",
            "description": "Statistics for inbound (ERP sync) events",
            "required": [
              "total_events",
              "success_count",
              "error_count",
              "skipped_count"
            ],
            "properties": {
              "total_events": {
                "type": "integer",
                "description": "Total number of inbound events in the period"
              },
              "total_correlations": {
                "type": "integer",
                "description": "Total number of unique correlation IDs"
              },
              "success_count": {
                "type": "integer",
                "description": "Number of successful events"
              },
              "error_count": {
                "type": "integer",
                "description": "Number of failed events"
              },
              "skipped_count": {
                "type": "integer",
                "description": "Number of skipped events"
              },
              "warning_count": {
                "type": "integer",
                "description": "Number of warning events"
              },
              "success_rate": {
                "type": "number",
                "format": "float",
                "description": "Success rate as percentage (0-100)"
              },
              "last_error_at": {
                "type": "string",
                "format": "date-time",
                "nullable": true,
                "description": "Timestamp of the most recent error"
              },
              "breakdown": {
                "type": "array",
                "description": "Statistics breakdown by requested inbound_group_by fields",
                "items": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "outbound": {
            "type": "object",
            "description": "Statistics for outbound (webhook delivery) events",
            "required": [
              "total_events",
              "success_count",
              "error_count"
            ],
            "properties": {
              "total_events": {
                "type": "integer",
                "description": "Total number of outbound events in the period"
              },
              "success_count": {
                "type": "integer",
                "description": "Number of successful deliveries"
              },
              "error_count": {
                "type": "integer",
                "description": "Number of failed deliveries"
              },
              "pending_count": {
                "type": "integer",
                "description": "Number of pending deliveries"
              },
              "success_rate": {
                "type": "number",
                "format": "float",
                "description": "Success rate as percentage (0-100)"
              },
              "last_error_at": {
                "type": "string",
                "format": "date-time",
                "nullable": true,
                "description": "Timestamp of the most recent error"
              },
              "breakdown": {
                "type": "array",
                "description": "Statistics breakdown by requested outbound_group_by fields",
                "items": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          }
        }
      },
      "InboundMonitoringEvent": {
        "type": "object",
        "required": [
          "org_id",
          "event_id",
          "object_type",
          "sync_type",
          "status",
          "received_at",
          "completed_at"
        ],
        "properties": {
          "org_id": {
            "type": "string",
            "description": "Organization ID"
          },
          "event_id": {
            "type": "string",
            "description": "Unique event identifier"
          },
          "correlation_id": {
            "type": "string",
            "nullable": true,
            "description": "Correlation ID for tracing related events"
          },
          "integration_id": {
            "type": "string",
            "nullable": true,
            "description": "Integration ID"
          },
          "use_case_id": {
            "type": "string",
            "nullable": true,
            "description": "Use case ID"
          },
          "event_type": {
            "type": "string",
            "enum": [
              "CREATE",
              "UPDATE",
              "DELETE",
              "TRIGGER"
            ],
            "description": "Type of event (optional for V3 events)"
          },
          "object_type": {
            "type": "string",
            "description": "Type of object being synced (e.g., 'contract', 'meter')"
          },
          "sync_type": {
            "type": "string",
            "enum": [
              "entity",
              "meter_reading",
              "webhook",
              "api_deprecation"
            ],
            "description": "Type of sync operation"
          },
          "status": {
            "type": "string",
            "enum": [
              "success",
              "error",
              "skipped",
              "warning"
            ],
            "description": "Processing status"
          },
          "error_code": {
            "type": "string",
            "nullable": true,
            "description": "Error code (when status=error)"
          },
          "error_message": {
            "type": "string",
            "nullable": true,
            "description": "Error message (when status=error)"
          },
          "error_category": {
            "type": "string",
            "nullable": true,
            "enum": [
              "validation",
              "configuration",
              "downstream_api",
              "timeout",
              "system"
            ],
            "description": "Error category (when status=error)"
          },
          "processing_duration_ms": {
            "type": "integer",
            "nullable": true,
            "description": "Processing duration in milliseconds"
          },
          "received_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the event was received"
          },
          "completed_at": {
            "type": "string",
            "format": "date-time",
            "description": "When processing completed"
          }
        }
      },
      "QueryMonitoringEventsV2Request": {
        "type": "object",
        "properties": {
          "use_case_id": {
            "type": "string",
            "description": "Filter by use case ID (UUID). Empty string matches \"General\" events. Special value \"__unknown__\" matches events whose use_case_id does not belong to any currently configured use case for this integration (excludes \"General\" events).\n"
          },
          "use_case_type": {
            "type": "string",
            "enum": [
              "inbound",
              "outbound",
              "file_proxy",
              "managed_call",
              "secure_proxy"
            ],
            "description": "Filter by use case type (replaces direction)"
          },
          "level": {
            "type": "string",
            "enum": [
              "success",
              "error",
              "skipped",
              "warning"
            ],
            "description": "Filter by event level"
          },
          "code": {
            "type": "string",
            "description": "Filter by taxonomy code (e.g. OAUTH2_TOKEN_FAILURE, HTTP_502)"
          },
          "event_id": {
            "type": "string",
            "description": "Filter by trigger/inbound event ID"
          },
          "correlation_id": {
            "type": "string",
            "description": "Filter by correlation ID for tracing"
          },
          "from_date": {
            "type": "string",
            "format": "date-time",
            "description": "Filter events from this date (inclusive)",
            "example": "2025-01-01T00:00:00Z"
          },
          "to_date": {
            "type": "string",
            "format": "date-time",
            "description": "Filter events until this date (inclusive)",
            "example": "2025-01-31T23:59:59Z"
          },
          "limit": {
            "type": "integer",
            "description": "Maximum number of results to return",
            "example": 50,
            "default": 50,
            "minimum": 1,
            "maximum": 100
          },
          "cursor": {
            "type": "object",
            "description": "Cursor for pagination (from previous response's next_cursor)",
            "properties": {
              "created_at": {
                "type": "string",
                "format": "date-time"
              },
              "id": {
                "type": "string",
                "format": "uuid"
              }
            }
          }
        }
      },
      "MonitoringEventV2": {
        "type": "object",
        "required": [
          "id",
          "org_id",
          "integration_id",
          "event_id",
          "use_case_type",
          "level",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Unique monitoring event ID"
          },
          "org_id": {
            "type": "string",
            "description": "Organization ID"
          },
          "integration_id": {
            "type": "string",
            "description": "Integration ID"
          },
          "event_id": {
            "type": "string",
            "description": "Trigger/inbound event ID (groups related monitoring events)"
          },
          "correlation_id": {
            "type": "string",
            "description": "Correlation ID for tracing. Empty when unavailable."
          },
          "use_case_id": {
            "type": "string",
            "description": "Use case ID. Empty for system-level events (\"General\")."
          },
          "use_case_type": {
            "type": "string",
            "enum": [
              "inbound",
              "outbound",
              "file_proxy",
              "managed_call",
              "secure_proxy",
              ""
            ],
            "description": "Use case type. Empty for system-level events."
          },
          "level": {
            "type": "string",
            "enum": [
              "success",
              "error",
              "skipped",
              "warning"
            ],
            "description": "Event outcome level"
          },
          "code": {
            "type": "string",
            "description": "Taxonomy code (e.g. OAUTH2_TOKEN_FAILURE, HTTP_502). Empty for success."
          },
          "message": {
            "type": "string",
            "description": "Human-readable message. Empty when not applicable."
          },
          "detail": {
            "type": "object",
            "nullable": true,
            "additionalProperties": true,
            "description": "Event-specific JSON data. Structure determined by `code`."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the monitoring event was created"
          }
        }
      },
      "GetMonitoringStatsV2Request": {
        "type": "object",
        "properties": {
          "from_date": {
            "type": "string",
            "format": "date-time",
            "description": "Start of the time range",
            "example": "2025-01-01T00:00:00Z"
          },
          "to_date": {
            "type": "string",
            "format": "date-time",
            "description": "End of the time range",
            "example": "2025-01-31T23:59:59Z"
          },
          "use_case_type": {
            "type": "string",
            "enum": [
              "inbound",
              "outbound",
              "file_proxy",
              "managed_call",
              "secure_proxy"
            ],
            "description": "Filter stats by use case type"
          },
          "group_by": {
            "type": "string",
            "enum": [
              "use_case_id",
              "use_case_type",
              "level",
              "code",
              "date"
            ],
            "description": "Field to group the breakdown by"
          },
          "source": {
            "type": "string",
            "enum": [
              "monitoring",
              "incoming"
            ],
            "default": "monitoring",
            "description": "Data source for the stats. \"monitoring\" (default) aggregates processed events from erp_monitoring_v2 — this counts every event produced throughout the processing tree (fan-out children, post-actions, relation resolutions, etc.). \"incoming\" counts only the initial inbound events actually received (distinct event_id from erp_incoming_events); only group_by=use_case_id is supported and status/level breakdown is not available for this source (success/error/warning/skipped counts are returned as 0).\n"
          }
        }
      },
      "MonitoringStatsV2": {
        "type": "object",
        "required": [
          "total_events",
          "success_count",
          "error_count",
          "warning_count",
          "skipped_count"
        ],
        "properties": {
          "total_events": {
            "type": "integer",
            "description": "Total number of events in the period"
          },
          "success_count": {
            "type": "integer",
            "description": "Number of successful events"
          },
          "error_count": {
            "type": "integer",
            "description": "Number of error events"
          },
          "warning_count": {
            "type": "integer",
            "description": "Number of warning events"
          },
          "skipped_count": {
            "type": "integer",
            "description": "Number of skipped events"
          },
          "ack_timeout_count": {
            "type": "integer",
            "description": "Number of ACK_TIMEOUT events (acknowledgement timed out)"
          },
          "success_rate": {
            "type": "number",
            "format": "float",
            "description": "Success rate as percentage (0-100)"
          },
          "last_error_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Timestamp of the most recent error"
          },
          "breakdown": {
            "type": "array",
            "description": "Statistics breakdown by requested group_by field",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          }
        }
      },
      "GetMonitoringTimeSeriesV2Request": {
        "type": "object",
        "required": [
          "from_date",
          "interval"
        ],
        "properties": {
          "from_date": {
            "type": "string",
            "format": "date-time",
            "description": "Start of the time range (required)",
            "example": "2025-01-01T00:00:00Z"
          },
          "to_date": {
            "type": "string",
            "format": "date-time",
            "description": "End of the time range (defaults to now)",
            "example": "2025-01-31T23:59:59Z"
          },
          "interval": {
            "type": "string",
            "enum": [
              "5m",
              "10m",
              "30m",
              "1h",
              "3h",
              "1d"
            ],
            "description": "Time bucket interval"
          },
          "use_case_type": {
            "type": "string",
            "enum": [
              "inbound",
              "outbound",
              "file_proxy",
              "managed_call",
              "secure_proxy"
            ],
            "description": "Filter by use case type"
          },
          "group_by": {
            "type": "string",
            "enum": [
              "use_case_type",
              "use_case"
            ],
            "description": "Field to group the bucket breakdown by"
          }
        }
      },
      "TimeSeriesBreakdownItemV2": {
        "type": "object",
        "required": [
          "success_count",
          "error_count",
          "warning_count",
          "skipped_count",
          "total_count"
        ],
        "properties": {
          "use_case_type": {
            "type": "string",
            "enum": [
              "inbound",
              "outbound",
              "file_proxy",
              "managed_call",
              "secure_proxy"
            ],
            "description": "Present when grouping by use_case_type"
          },
          "use_case_id": {
            "type": "string",
            "description": "Present when grouping by use_case. Unknown historical IDs are collapsed into \"__unknown__\""
          },
          "success_count": {
            "type": "integer",
            "description": "Number of successful events in the breakdown item"
          },
          "error_count": {
            "type": "integer",
            "description": "Number of error events in the breakdown item"
          },
          "warning_count": {
            "type": "integer",
            "description": "Number of warning events in the breakdown item"
          },
          "skipped_count": {
            "type": "integer",
            "description": "Number of skipped events in the breakdown item"
          },
          "total_count": {
            "type": "integer",
            "description": "Total events in the breakdown item"
          }
        }
      },
      "TimeSeriesBucketV2": {
        "type": "object",
        "required": [
          "timestamp",
          "total_count"
        ],
        "properties": {
          "timestamp": {
            "type": "string",
            "format": "date-time",
            "description": "Bucket start timestamp"
          },
          "success_count": {
            "type": "integer",
            "description": "Number of successful events in the bucket"
          },
          "error_count": {
            "type": "integer",
            "description": "Number of error events in the bucket"
          },
          "warning_count": {
            "type": "integer",
            "description": "Number of warning events in the bucket"
          },
          "skipped_count": {
            "type": "integer",
            "description": "Number of skipped events in the bucket"
          },
          "total_count": {
            "type": "integer",
            "description": "Total events in the bucket"
          },
          "breakdown": {
            "type": "array",
            "description": "Statistics breakdown by the requested group_by field for this bucket",
            "items": {
              "$ref": "#/components/schemas/TimeSeriesBreakdownItemV2"
            }
          }
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Bad request",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponseBase"
            }
          }
        }
      },
      "NotFound": {
        "description": "Resource not found",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponseBase"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Unauthorized request",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponseBase"
            }
          }
        }
      },
      "Forbidden": {
        "description": "Forbidden - insufficient permissions",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponseBase"
            }
          }
        }
      },
      "InternalServerError": {
        "description": "Internal Server Error",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponseBase"
            }
          }
        }
      },
      "QueryInboundMonitoringEventsResponse": {
        "description": "Inbound monitoring events queried successfully",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "data": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/InboundMonitoringEvent"
                  },
                  "description": "List of inbound monitoring events"
                },
                "next_cursor": {
                  "type": "object",
                  "nullable": true,
                  "description": "Cursor to fetch the next page. Null if no more results.",
                  "properties": {
                    "completed_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "event_id": {
                      "type": "string"
                    }
                  }
                },
                "has_more": {
                  "type": "boolean",
                  "description": "Indicates if more results are available"
                }
              }
            }
          }
        }
      },
      "GetMonitoringStatsResponse": {
        "description": "Monitoring statistics retrieved successfully",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/MonitoringStats"
            }
          }
        }
      },
      "GetMonitoringTimeSeriesResponse": {
        "description": "Time-series aggregated event counts retrieved successfully",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "interval",
                "from_date",
                "to_date",
                "buckets"
              ],
              "properties": {
                "interval": {
                  "type": "string",
                  "enum": [
                    "5m",
                    "10m",
                    "30m",
                    "1h",
                    "3h",
                    "1d"
                  ],
                  "description": "The time bucket interval used for aggregation"
                },
                "from_date": {
                  "type": "string",
                  "format": "date-time",
                  "description": "Start date of the time series"
                },
                "to_date": {
                  "type": "string",
                  "format": "date-time",
                  "description": "End date of the time series"
                },
                "buckets": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/TimeSeriesBucket"
                  },
                  "description": "List of time-series buckets with event counts"
                }
              }
            }
          }
        }
      },
      "QueryAccessLogsResponse": {
        "description": "Access logs queried successfully",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "data": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/AccessLogEntry"
                  },
                  "description": "List of access log entries"
                },
                "next_cursor": {
                  "type": "object",
                  "nullable": true,
                  "description": "Cursor to fetch the next page. Null if no more results.",
                  "properties": {
                    "timestamp": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "request_id": {
                      "type": "string"
                    }
                  }
                },
                "has_more": {
                  "type": "boolean",
                  "description": "Indicates if more results are available"
                }
              }
            }
          }
        }
      },
      "QueryOutboundMonitoringEventsResponse": {
        "description": "Outbound monitoring events queried successfully",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "data": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/OutboundMonitoringEvent"
                  },
                  "description": "List of outbound monitoring events"
                },
                "next_cursor": {
                  "type": "object",
                  "nullable": true,
                  "description": "Cursor to fetch the next page. Null if no more results.",
                  "properties": {
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "event_id": {
                      "type": "string"
                    }
                  }
                },
                "has_more": {
                  "type": "boolean",
                  "description": "Indicates if more results are available"
                }
              }
            }
          }
        }
      },
      "ReplayEventsResponse": {
        "description": "Events replay initiated",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "replayed",
                "results"
              ],
              "properties": {
                "event_ids": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  },
                  "description": "List of event IDs for which replay was requested"
                }
              }
            }
          }
        }
      },
      "ERPUpdatesResponse": {
        "description": "Some events failed to process",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "results": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "required": [
                      "event_id",
                      "status"
                    ],
                    "properties": {
                      "event_id": {
                        "type": "string",
                        "description": "ID of the processed event"
                      },
                      "status": {
                        "type": "string",
                        "enum": [
                          "success",
                          "error",
                          "skipped",
                          "ignored"
                        ],
                        "description": "Processing status for the event (skipped indicates duplicate deduplication_id, ignored indicates unconfigured event)"
                      },
                      "message": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "TriggerWebhookResponse": {
        "description": "Result of triggering an ERP synchronization event",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/TriggerWebhookResp"
            }
          }
        }
      },
      "QueryEventsResponse": {
        "description": "Events queried successfully",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "data": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ErpEvent"
                  },
                  "description": "List of erp events"
                },
                "next_cursor": {
                  "type": "object",
                  "nullable": true,
                  "description": "Cursor to fetch the next page. Null if no more results.",
                  "properties": {
                    "event_time": {
                      "type": "string",
                      "format": "date-time",
                      "example": "2025-10-31T12:34:56Z"
                    },
                    "event_id": {
                      "type": "string",
                      "example": "evt_1234567890abcdef"
                    }
                  }
                },
                "has_more": {
                  "type": "boolean",
                  "description": "Indicates if more results are available",
                  "example": true
                }
              }
            }
          }
        }
      },
      "QueryMonitoringEventsV2Response": {
        "description": "Monitoring events queried successfully",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "data": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/MonitoringEventV2"
                  },
                  "description": "List of monitoring events"
                },
                "next_cursor": {
                  "type": "object",
                  "nullable": true,
                  "description": "Cursor to fetch the next page. Null if no more results.",
                  "properties": {
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "id": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                },
                "has_more": {
                  "type": "boolean",
                  "description": "Indicates if more results are available"
                }
              }
            }
          }
        }
      },
      "GetMonitoringStatsV2Response": {
        "description": "Monitoring statistics retrieved successfully",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/MonitoringStatsV2"
            }
          }
        }
      },
      "GetMonitoringTimeSeriesV2Response": {
        "description": "Time-series data retrieved successfully",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "interval": {
                  "type": "string",
                  "enum": [
                    "5m",
                    "10m",
                    "30m",
                    "1h",
                    "3h",
                    "1d"
                  ],
                  "description": "The bucket interval"
                },
                "from_date": {
                  "type": "string",
                  "format": "date-time"
                },
                "to_date": {
                  "type": "string",
                  "format": "date-time"
                },
                "buckets": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/TimeSeriesBucketV2"
                  }
                }
              }
            }
          }
        }
      },
      "GetAssociatedMonitoringEventsResponse": {
        "description": "Associated monitoring events for the given event_id",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "monitoring_events": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/MonitoringEventV2"
                  },
                  "description": "All monitoring events sharing this event_id, ordered by created_at ASC"
                },
                "inbound_event": {
                  "type": "object",
                  "nullable": true,
                  "additionalProperties": true,
                  "description": "The original inbound event payload from erp_incoming_events, if available"
                }
              }
            }
          }
        }
      }
    }
  }
}
