{
  "openapi": "3.0.3",
  "info": {
    "title": "Northwind CRM API",
    "version": "1.0.0",
    "description": "Northwind CRM (Salesforce-shaped). Vocabulary: Contacts · Accounts · Opportunities · Cases. Records are Contacts, identified by ContactId (e.g. 003Ax000001aBcD). Identifiers this system emits: ContactId, Email. No authentication."
  },
  "servers": [
    {
      "url": "https://necogoode-systems.azurewebsites.net"
    }
  ],
  "tags": [
    {
      "name": "Contacts"
    },
    {
      "name": "Operations"
    }
  ],
  "paths": {
    "/api/crm/records": {
      "get": {
        "operationId": "listCrmRecords",
        "tags": [
          "Contacts"
        ],
        "summary": "List Contacts (newest first)",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "count": {
                      "type": "integer"
                    },
                    "records": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Record"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createCrmRecord",
        "tags": [
          "Contacts"
        ],
        "summary": "Create a Contact (emits northwind.contact.created)",
        "description": "Creates a Contact in Northwind CRM and emits the northwind.contact.created webhook to SoloLift.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "record": {
                      "$ref": "#/components/schemas/Record"
                    },
                    "event": {
                      "$ref": "#/components/schemas/Event"
                    },
                    "droppedFields": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "identifiers belonging to another system, dropped before the record was written"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "A required field was missing",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/crm/records/{id}": {
      "get": {
        "operationId": "getCrmRecord",
        "tags": [
          "Contacts"
        ],
        "summary": "Read one Contact",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "ContactId, e.g. 003Ax000001aBcD",
            "example": "003Ax000001aBcD"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "record": {
                      "$ref": "#/components/schemas/Record"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found"
          }
        }
      },
      "patch": {
        "operationId": "updateCrmRecord",
        "tags": [
          "Contacts"
        ],
        "summary": "Update a Contact (emits northwind.contact.updated)",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "ContactId, e.g. 003Ax000001aBcD",
            "example": "003Ax000001aBcD"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "record": {
                      "$ref": "#/components/schemas/Record"
                    },
                    "event": {
                      "$ref": "#/components/schemas/Event"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found"
          }
        }
      }
    },
    "/api/crm/records/{id}/convert": {
      "post": {
        "operationId": "crmConvert",
        "tags": [
          "Operations"
        ],
        "summary": "Convert to Employee (emits northwind.contact.converted)",
        "description": "Convert the Contact record to an Employee record on its Account.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "ContactId, e.g. 003Ax000001aBcD",
            "example": "003Ax000001aBcD"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ActionRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "record": {
                      "$ref": "#/components/schemas/Record"
                    },
                    "event": {
                      "$ref": "#/components/schemas/Event"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found"
          }
        }
      }
    },
    "/api/crm/records/{id}/events": {
      "get": {
        "operationId": "listCrmRecordEvents",
        "tags": [
          "Operations"
        ],
        "summary": "Every event this system has emitted for the record",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "ContactId, e.g. 003Ax000001aBcD",
            "example": "003Ax000001aBcD"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "events": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Event"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/crm/events": {
      "get": {
        "operationId": "listCrmEvents",
        "tags": [
          "Operations"
        ],
        "summary": "Every event this system has emitted (newest first)",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 200
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "events": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Event"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/crm/chaos": {
      "post": {
        "operationId": "crmChaos",
        "tags": [
          "Operations"
        ],
        "summary": "Emit a deliberately awkward event for anomaly testing",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ChaosRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "event": {
                      "$ref": "#/components/schemas/Event"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/crm/seed": {
      "post": {
        "operationId": "crmSeedHistory",
        "tags": [
          "Operations"
        ],
        "summary": "Generate N backdated Contacts with events across a date window",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SeedRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/api/_health": {
      "get": {
        "operationId": "health",
        "tags": [
          "Operations"
        ],
        "summary": "Liveness and build stamp",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "build": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Record": {
        "type": "object",
        "properties": {
          "ContactId": {
            "type": "string",
            "description": "Contact identifier issued by Northwind CRM",
            "example": "003Ax000001aBcD"
          },
          "FirstName": {
            "type": "string",
            "description": "First name (required on create)"
          },
          "LastName": {
            "type": "string",
            "description": "Last name (required on create)"
          },
          "Email": {
            "type": "string",
            "format": "email",
            "description": "Email (required on create)"
          },
          "AccountName": {
            "type": "string",
            "description": "Account",
            "default": "Northwind Traders"
          },
          "Department": {
            "type": "string",
            "enum": [
              "Finance",
              "Operations",
              "Sales",
              "Information Technology",
              "Human Resources",
              "Logistics"
            ],
            "description": "Department",
            "default": "Operations"
          },
          "JobTitle": {
            "type": "string",
            "description": "Job title"
          },
          "LineManager": {
            "type": "string",
            "enum": [
              "A. Whitfield",
              "R. Okonkwo",
              "S. Delacroix",
              "M. Bergstrom",
              "P. Ramachandran",
              "J. Halvorsen",
              "T. Nakamura",
              "C. Mbeki",
              "L. Fontaine"
            ],
            "description": "Line manager",
            "default": "A. Whitfield"
          },
          "StartDate": {
            "type": "string",
            "format": "date",
            "description": "Start date"
          },
          "EquipmentPackage": {
            "type": "string",
            "enum": [
              "standard",
              "specialist"
            ],
            "description": "Equipment package",
            "default": "standard"
          },
          "CostCentre": {
            "type": "string",
            "description": "Cost centre (optional)"
          },
          "Stage": {
            "type": "string",
            "enum": [
              "Contact",
              "Employee"
            ],
            "description": "Stage",
            "default": "Contact"
          },
          "CaseNotes": {
            "type": "string",
            "description": "Case notes"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "eventCount": {
            "type": "integer",
            "description": "number of events this system has emitted for the record"
          },
          "lastDelivery": {
            "$ref": "#/components/schemas/Delivery"
          }
        }
      },
      "CreateRequest": {
        "type": "object",
        "required": [
          "FirstName",
          "LastName",
          "Email"
        ],
        "properties": {
          "FirstName": {
            "type": "string",
            "description": "First name (required on create)"
          },
          "LastName": {
            "type": "string",
            "description": "Last name (required on create)"
          },
          "Email": {
            "type": "string",
            "format": "email",
            "description": "Email (required on create)"
          },
          "AccountName": {
            "type": "string",
            "description": "Account",
            "default": "Northwind Traders"
          },
          "Department": {
            "type": "string",
            "enum": [
              "Finance",
              "Operations",
              "Sales",
              "Information Technology",
              "Human Resources",
              "Logistics"
            ],
            "description": "Department",
            "default": "Operations"
          },
          "JobTitle": {
            "type": "string",
            "description": "Job title"
          },
          "LineManager": {
            "type": "string",
            "enum": [
              "A. Whitfield",
              "R. Okonkwo",
              "S. Delacroix",
              "M. Bergstrom",
              "P. Ramachandran",
              "J. Halvorsen",
              "T. Nakamura",
              "C. Mbeki",
              "L. Fontaine"
            ],
            "description": "Line manager",
            "default": "A. Whitfield"
          },
          "StartDate": {
            "type": "string",
            "format": "date",
            "description": "Start date"
          },
          "EquipmentPackage": {
            "type": "string",
            "enum": [
              "standard",
              "specialist"
            ],
            "description": "Equipment package",
            "default": "standard"
          },
          "CostCentre": {
            "type": "string",
            "description": "Cost centre (optional)"
          },
          "Stage": {
            "type": "string",
            "enum": [
              "Contact",
              "Employee"
            ],
            "description": "Stage",
            "default": "Contact"
          },
          "CaseNotes": {
            "type": "string",
            "description": "Case notes"
          },
          "occurredAt": {
            "type": "string",
            "format": "date-time",
            "description": "Optional. Backdates the record and the emitted event (used for seeding history)."
          },
          "emit": {
            "type": "boolean",
            "default": true,
            "description": "Optional. false suppresses the webhook to SoloLift."
          }
        }
      },
      "UpdateRequest": {
        "type": "object",
        "properties": {
          "FirstName": {
            "type": "string",
            "description": "First name (required on create)"
          },
          "LastName": {
            "type": "string",
            "description": "Last name (required on create)"
          },
          "Email": {
            "type": "string",
            "format": "email",
            "description": "Email (required on create)"
          },
          "AccountName": {
            "type": "string",
            "description": "Account",
            "default": "Northwind Traders"
          },
          "Department": {
            "type": "string",
            "enum": [
              "Finance",
              "Operations",
              "Sales",
              "Information Technology",
              "Human Resources",
              "Logistics"
            ],
            "description": "Department",
            "default": "Operations"
          },
          "JobTitle": {
            "type": "string",
            "description": "Job title"
          },
          "LineManager": {
            "type": "string",
            "enum": [
              "A. Whitfield",
              "R. Okonkwo",
              "S. Delacroix",
              "M. Bergstrom",
              "P. Ramachandran",
              "J. Halvorsen",
              "T. Nakamura",
              "C. Mbeki",
              "L. Fontaine"
            ],
            "description": "Line manager",
            "default": "A. Whitfield"
          },
          "StartDate": {
            "type": "string",
            "format": "date",
            "description": "Start date"
          },
          "EquipmentPackage": {
            "type": "string",
            "enum": [
              "standard",
              "specialist"
            ],
            "description": "Equipment package",
            "default": "standard"
          },
          "CostCentre": {
            "type": "string",
            "description": "Cost centre (optional)"
          },
          "Stage": {
            "type": "string",
            "enum": [
              "Contact",
              "Employee"
            ],
            "description": "Stage",
            "default": "Contact"
          },
          "CaseNotes": {
            "type": "string",
            "description": "Case notes"
          },
          "occurredAt": {
            "type": "string",
            "format": "date-time",
            "description": "Optional. Backdates the record and the emitted event (used for seeding history)."
          },
          "emit": {
            "type": "boolean",
            "default": true,
            "description": "Optional. false suppresses the webhook to SoloLift."
          }
        }
      },
      "ActionRequest": {
        "type": "object",
        "required": [],
        "properties": {
          "employeeType": {
            "type": "string",
            "enum": [
              "Permanent",
              "Contract",
              "Intern"
            ],
            "default": "Permanent"
          },
          "occurredAt": {
            "type": "string",
            "format": "date-time",
            "description": "Optional. Backdates the emitted event."
          }
        }
      },
      "ChaosRequest": {
        "type": "object",
        "required": [
          "mode"
        ],
        "properties": {
          "mode": {
            "type": "string",
            "enum": [
              "out_of_order",
              "duplicate",
              "omit_field",
              "unknown_type"
            ]
          },
          "recordId": {
            "type": "string",
            "description": "defaults to the most recent record"
          }
        }
      },
      "SeedRequest": {
        "type": "object",
        "properties": {
          "count": {
            "type": "integer",
            "default": 5,
            "maximum": 200
          },
          "from": {
            "type": "string",
            "format": "date-time",
            "description": "start of the backdating window"
          },
          "to": {
            "type": "string",
            "format": "date-time",
            "description": "end of the backdating window"
          },
          "includeAction": {
            "type": "boolean",
            "default": true,
            "description": "also emit northwind.contact.converted per record"
          },
          "specialistRatio": {
            "type": "number",
            "default": 0.15
          },
          "fieldRatios": {
            "type": "object",
            "additionalProperties": {
              "type": "number"
            },
            "description": "probability a normally-optional field is populated, e.g. {\"CostCentre\":0.35}"
          },
          "template": {
            "type": "object",
            "description": "field values forced on every seeded record"
          },
          "emit": {
            "type": "boolean",
            "default": true
          }
        }
      },
      "Delivery": {
        "type": "object",
        "description": "the outcome of the SoloLift webhook for the latest event",
        "properties": {
          "httpStatus": {
            "type": "integer"
          },
          "receiptStatus": {
            "type": "string"
          },
          "receiptReason": {
            "type": "string"
          },
          "externalEventId": {
            "type": "string"
          },
          "transportError": {
            "type": "string",
            "nullable": true
          },
          "at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Event": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "system": {
            "type": "string",
            "enum": [
              "crm"
            ]
          },
          "recordId": {
            "type": "string"
          },
          "eventType": {
            "type": "string",
            "enum": [
              "northwind.contact.created",
              "northwind.contact.updated",
              "northwind.contact.converted",
              "northwind.contact.teleported"
            ]
          },
          "externalEventId": {
            "type": "string"
          },
          "eventSourceId": {
            "type": "string"
          },
          "subject": {
            "type": "string"
          },
          "occurredAt": {
            "type": "string",
            "format": "date-time"
          },
          "emittedAt": {
            "type": "string",
            "format": "date-time"
          },
          "chaos": {
            "type": "string",
            "nullable": true,
            "enum": [
              "out_of_order",
              "duplicate",
              "omit_field",
              "unknown_type",
              null
            ]
          },
          "payload": {
            "type": "object",
            "additionalProperties": true
          },
          "delivery": {
            "$ref": "#/components/schemas/Delivery"
          }
        }
      }
    }
  }
}