{
  "openapi": "3.1.0",
  "info": {
    "title": "Samloryx OS API",
    "version": "v1",
    "description": "The read-only API a Samloryx OS company can open to its own integrations with an API key. Every response is limited to the company the key belongs to."
  },
  "servers": [
    {
      "url": "https://api.samloryx.co.za"
    }
  ],
  "security": [
    {
      "ApiKey": []
    },
    {
      "Bearer": []
    }
  ],
  "x-groups": [
    {
      "key": "identity",
      "title": "Identity",
      "blurb": "Check the key and see which products the company runs."
    },
    {
      "key": "graph",
      "title": "Business Graph",
      "blurb": "The company's shared record: who it deals with, where it works, what it holds and what it owes."
    },
    {
      "key": "tenders",
      "title": "Tenders",
      "blurb": "Public tenders matched to the company's profile."
    },
    {
      "key": "agents",
      "title": "Agents",
      "blurb": "The catalogue of governed agents and what each is permitted to do."
    }
  ],
  "paths": {
    "/api/v1/agents": {
      "get": {
        "operationId": "getAgents",
        "summary": "List agents",
        "description": "Every agent in the catalogue with its authority level, the tools it may use and the restricted actions it may attempt. Listing only: agents cannot be invoked with an API key in v1. This endpoint is covered by the tenders.read scope.",
        "x-group": "agents",
        "x-required-scope": "tenders.read",
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/AgentSummary"
                  }
                },
                "example": [
                  {
                    "name": "document-intelligence",
                    "description": "Reads a business document and extracts obligations, deadlines, amounts and compliance requirements. Every finding carries a verbatim citation from the document; uncited findings are flagged unverified and are never applied.",
                    "authority": "RECOMMEND",
                    "tools": [
                      "document.read"
                    ],
                    "outputType": "document.findings.v1",
                    "restrictedActions": []
                  }
                ]
              }
            }
          },
          "401": {
            "description": "The key is missing, unknown or revoked.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "The key is valid but lacks the scope for this endpoint.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many failed authentication attempts from this address. Wait for Retry-After seconds.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/graph/companies": {
      "get": {
        "operationId": "getGraphCompanies",
        "summary": "List companies",
        "description": "The organisations this company deals with: clients, public buyers, suppliers and subcontractors.",
        "x-group": "graph",
        "x-required-scope": "graph.read",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 100
            },
            "description": "How many rows to return, newest first. 1 to 200; values outside that range are clamped, not rejected. Default 100."
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/CompanyResponse"
                  }
                },
                "example": [
                  {
                    "id": "c0a80000-0000-4000-8000-000000000031",
                    "name": "Kopano Developments",
                    "registrationNumber": "2014/123456/07",
                    "kind": "CLIENT",
                    "notes": "Fictional property developer client (synthetic demo data).",
                    "createdAt": "2026-08-16T13:17:15.889594Z"
                  }
                ]
              }
            }
          },
          "400": {
            "description": "A parameter has a value that is not allowed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "The key is missing, unknown or revoked.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "The key is valid but lacks the scope for this endpoint.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many failed authentication attempts from this address. Wait for Retry-After seconds.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/graph/documents": {
      "get": {
        "operationId": "getGraphDocuments",
        "summary": "List documents",
        "description": "Document records: title, kind, expiry and provenance. This returns the record, not the file; file contents are not available to API keys in v1.",
        "x-group": "graph",
        "x-required-scope": "graph.read",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 100
            },
            "description": "How many rows to return, newest first. 1 to 200; values outside that range are clamped, not rejected. Default 100."
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/DocumentResponse"
                  }
                },
                "example": [
                  {
                    "id": "c0a80000-0000-4000-8000-000000000036",
                    "title": "Tender pack CB 112/2026",
                    "kind": "TENDER_PACK",
                    "sourceUri": null,
                    "sha256": null,
                    "expiresOn": null,
                    "companyId": "c0a80000-0000-4000-8000-000000000032",
                    "siteId": null,
                    "createdAt": "2026-08-16T13:17:15.889594Z"
                  }
                ]
              }
            }
          },
          "400": {
            "description": "A parameter has a value that is not allowed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "The key is missing, unknown or revoked.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "The key is valid but lacks the scope for this endpoint.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many failed authentication attempts from this address. Wait for Retry-After seconds.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/graph/obligations": {
      "get": {
        "operationId": "getGraphObligations",
        "summary": "List obligations",
        "description": "Things the company must do or is owed: compliance duties, contractual deadlines, payments.",
        "x-group": "graph",
        "x-required-scope": "graph.read",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 100
            },
            "description": "How many rows to return, newest first. 1 to 200; values outside that range are clamped, not rejected. Default 100."
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ObligationResponse"
                  }
                },
                "example": [
                  {
                    "id": "c0a80000-0000-4000-8000-000000000038",
                    "title": "Retention payment, Ward 4 road",
                    "kind": "PAYMENT",
                    "dueOn": "2026-10-15",
                    "status": "OPEN",
                    "amount": 240000,
                    "currency": "ZAR",
                    "companyId": "c0a80000-0000-4000-8000-000000000031",
                    "documentId": null,
                    "notes": null,
                    "createdAt": "2026-08-16T13:17:15.889594Z"
                  }
                ]
              }
            }
          },
          "400": {
            "description": "A parameter has a value that is not allowed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "The key is missing, unknown or revoked.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "The key is valid but lacks the scope for this endpoint.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many failed authentication attempts from this address. Wait for Retry-After seconds.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/graph/persons": {
      "get": {
        "operationId": "getGraphPersons",
        "summary": "List people",
        "description": "Contacts, each optionally attached to a company. This is personal information: store and use it only for the purpose the company authorised.",
        "x-group": "graph",
        "x-required-scope": "graph.read",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 100
            },
            "description": "How many rows to return, newest first. 1 to 200; values outside that range are clamped, not rejected. Default 100."
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/PersonResponse"
                  }
                },
                "example": [
                  {
                    "id": "c0a80000-0000-4000-8000-000000000033",
                    "companyId": "c0a80000-0000-4000-8000-000000000031",
                    "fullName": "Naledi Khumalo",
                    "roleTitle": "Client contact",
                    "email": "naledi@kopano-developments.example",
                    "phone": "+27 82 555 0101",
                    "notes": null,
                    "createdAt": "2026-08-16T13:17:15.889594Z"
                  }
                ]
              }
            }
          },
          "400": {
            "description": "A parameter has a value that is not allowed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "The key is missing, unknown or revoked.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "The key is valid but lacks the scope for this endpoint.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many failed authentication attempts from this address. Wait for Retry-After seconds.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/graph/sites": {
      "get": {
        "operationId": "getGraphSites",
        "summary": "List sites",
        "description": "Places where work happens: construction sites, properties, offices.",
        "x-group": "graph",
        "x-required-scope": "graph.read",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 100
            },
            "description": "How many rows to return, newest first. 1 to 200; values outside that range are clamped, not rejected. Default 100."
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/SiteResponse"
                  }
                },
                "example": [
                  {
                    "id": "c0a80000-0000-4000-8000-000000000034",
                    "companyId": "c0a80000-0000-4000-8000-000000000031",
                    "name": "Ward 4 access road, Tshwane",
                    "province": "Gauteng",
                    "address": null,
                    "status": "ACTIVE",
                    "createdAt": "2026-08-16T13:17:15.889594Z"
                  }
                ]
              }
            }
          },
          "400": {
            "description": "A parameter has a value that is not allowed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "The key is missing, unknown or revoked.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "The key is valid but lacks the scope for this endpoint.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many failed authentication attempts from this address. Wait for Retry-After seconds.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/me": {
      "get": {
        "operationId": "getMe",
        "summary": "Who this key is",
        "description": "Returns the key's name, the company it belongs to and the scopes it was granted. Call it first: a 200 here means the key is valid and tells you what it can reach.",
        "x-group": "identity",
        "x-required-scope": "workspaces.read",
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MeResponse"
                },
                "example": {
                  "displayName": "Accounting sync",
                  "tenant": "Thabeng Civils",
                  "roles": [
                    "API"
                  ],
                  "scopes": [
                    "graph.read",
                    "workspaces.read"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "The key is missing, unknown or revoked.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "The key is valid but lacks the scope for this endpoint.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many failed authentication attempts from this address. Wait for Retry-After seconds.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-example-illustrative": true
      }
    },
    "/api/v1/tenders": {
      "get": {
        "operationId": "getTenders",
        "summary": "List matched tenders",
        "description": "Public tenders scored against the company's profile, best tier first. An empty array means nothing has been matched yet, not an error.",
        "x-group": "tenders",
        "x-required-scope": "tenders.read",
        "parameters": [
          {
            "name": "tier",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "RECOMMENDED",
                "WORTH_A_LOOK",
                "STRETCH"
              ]
            },
            "description": "Only matches in this tier."
          },
          {
            "name": "decided",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean"
            },
            "description": "true returns only tenders a person has decided on; false only those still undecided. Omit for both."
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 50
            },
            "description": "How many rows to return, newest first. 1 to 200; values outside that range are clamped, not rejected. Default 100."
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/TenderItemResponse"
                  }
                },
                "example": [
                  {
                    "ocid": "ocds-9t57fa-112-2026",
                    "title": "CB 112/2026 Rehabilitation of internal roads, Ward 4",
                    "buyer": "Mmakau Local Municipality",
                    "province": "North West",
                    "closesOn": "2026-11-06",
                    "runwayDays": 27,
                    "score": 82,
                    "tier": "RECOMMENDED",
                    "reasons": [
                      "CIDB grade 6CE held; tender requires 5CE",
                      "Province matches operating area"
                    ],
                    "briefingNote": "Compulsory briefing 21 Oct, 10:00, municipal offices",
                    "decision": null,
                    "analysisRunId": null,
                    "docCount": 4
                  }
                ]
              }
            }
          },
          "400": {
            "description": "A parameter has a value that is not allowed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "The key is missing, unknown or revoked.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "The key is valid but lacks the scope for this endpoint.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many failed authentication attempts from this address. Wait for Retry-After seconds.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-example-illustrative": true
      }
    },
    "/api/v1/workspaces": {
      "get": {
        "operationId": "getWorkspaces",
        "summary": "List workspaces",
        "description": "One workspace per product the company has. Use it to find out which industry products are present before reading their data.",
        "x-group": "identity",
        "x-required-scope": "workspaces.read",
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/WorkspaceResponse"
                  }
                },
                "example": [
                  {
                    "id": "c0a80000-0000-4000-8000-000000000011",
                    "productKey": "CONSTRUCT",
                    "name": "Construct AI"
                  },
                  {
                    "id": "c0a80000-0000-4000-8000-000000000015",
                    "productKey": "GROWTH",
                    "name": "Growth AI"
                  }
                ]
              }
            }
          },
          "401": {
            "description": "The key is missing, unknown or revoked.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "The key is valid but lacks the scope for this endpoint.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many failed authentication attempts from this address. Wait for Retry-After seconds.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key"
      },
      "Bearer": {
        "type": "http",
        "scheme": "bearer",
        "description": "The same key, as Authorization: Bearer slx_…"
      }
    },
    "schemas": {
      "AgentSummary": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Agent identifier."
          },
          "description": {
            "type": "string",
            "description": "What the agent does and what it will not do."
          },
          "authority": {
            "type": "string",
            "enum": [
              "OBSERVE",
              "RESEARCH",
              "RECOMMEND",
              "PREPARE",
              "DRAFT",
              "EXECUTE_WITH_APPROVAL",
              "AUTONOMOUS"
            ],
            "description": "The highest rung of the authority ladder the agent may act at."
          },
          "tools": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The tools the agent may call."
          },
          "outputType": {
            "type": "string",
            "description": "The schema of what the agent produces."
          },
          "restrictedActions": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Restricted actions the agent may prepare. These are never executed without a person's approval."
          }
        }
      },
      "CompanyResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Company id."
          },
          "name": {
            "type": "string",
            "description": "Trading or registered name."
          },
          "registrationNumber": {
            "type": "string",
            "description": "Company registration number, when recorded."
          },
          "kind": {
            "type": "string",
            "enum": [
              "CLIENT",
              "BUYER",
              "SUPPLIER",
              "SUBCONTRACTOR",
              "OTHER"
            ],
            "description": "The relationship to the account holder."
          },
          "notes": {
            "type": "string",
            "description": "Free text."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the record was created (UTC)."
          }
        }
      },
      "DocumentResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Document id."
          },
          "title": {
            "type": "string",
            "description": "Document title."
          },
          "kind": {
            "type": "string",
            "enum": [
              "CONTRACT",
              "TENDER_PACK",
              "CERTIFICATE",
              "INVOICE",
              "OTHER"
            ],
            "description": "What sort of document it is."
          },
          "sourceUri": {
            "type": "string",
            "description": "Where the document came from, when recorded."
          },
          "sha256": {
            "type": "string",
            "description": "SHA-256 of the stored file, when a file is attached. Use it to confirm a copy is the same file."
          },
          "expiresOn": {
            "type": "string",
            "format": "date",
            "description": "Expiry date, for documents that lapse (certificates, for example)."
          },
          "companyId": {
            "type": "string",
            "format": "uuid",
            "description": "Related company, when linked."
          },
          "siteId": {
            "type": "string",
            "format": "uuid",
            "description": "Related site, when linked."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the record was created (UTC)."
          }
        }
      },
      "MeResponse": {
        "type": "object",
        "properties": {
          "email": {
            "type": "string",
            "description": "Present only when a person is signed in. Never present for an API key."
          },
          "displayName": {
            "type": "string",
            "description": "The key's name, as given when it was created."
          },
          "tenant": {
            "type": "string",
            "description": "The company the key belongs to. Every response is limited to this company's data."
          },
          "roles": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Always [\"API\"] for a key."
          },
          "scopes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The scopes granted to the key."
          }
        }
      },
      "ObligationResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Obligation id."
          },
          "title": {
            "type": "string",
            "description": "What must be done."
          },
          "kind": {
            "type": "string",
            "enum": [
              "COMPLIANCE",
              "CONTRACTUAL",
              "PAYMENT",
              "OTHER"
            ],
            "description": "The nature of the duty."
          },
          "dueOn": {
            "type": "string",
            "format": "date",
            "description": "Due date, when there is one."
          },
          "status": {
            "type": "string",
            "enum": [
              "OPEN",
              "DONE"
            ],
            "description": "OPEN until it is completed."
          },
          "amount": {
            "type": "number",
            "description": "Money involved, when there is any. A decimal number, not cents."
          },
          "currency": {
            "type": "string",
            "description": "ISO 4217 code for amount. ZAR unless stated."
          },
          "companyId": {
            "type": "string",
            "format": "uuid",
            "description": "The counterparty, when linked."
          },
          "documentId": {
            "type": "string",
            "format": "uuid",
            "description": "The document the obligation comes from, when linked."
          },
          "notes": {
            "type": "string",
            "description": "Free text."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the record was created (UTC)."
          }
        }
      },
      "PersonResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Person id."
          },
          "companyId": {
            "type": "string",
            "format": "uuid",
            "description": "The company this person belongs to, when linked."
          },
          "fullName": {
            "type": "string",
            "description": "Full name."
          },
          "roleTitle": {
            "type": "string",
            "description": "Job title or role."
          },
          "email": {
            "type": "string",
            "description": "Email address, when recorded."
          },
          "phone": {
            "type": "string",
            "description": "Phone number, when recorded."
          },
          "notes": {
            "type": "string",
            "description": "Free text."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the record was created (UTC)."
          }
        }
      },
      "Problem": {
        "type": "object",
        "description": "Every error has this shape (application/problem+json).",
        "properties": {
          "type": {
            "type": "string",
            "description": "Always about:blank."
          },
          "title": {
            "type": "string",
            "description": "The HTTP reason phrase."
          },
          "status": {
            "type": "integer",
            "description": "The HTTP status code."
          },
          "detail": {
            "type": "string",
            "description": "What went wrong, in words."
          },
          "correlationId": {
            "type": "string",
            "description": "Quote this when asking for help; it finds the request in our logs."
          },
          "timestamp": {
            "type": "string",
            "format": "date-time",
            "description": "When the error happened (UTC)."
          }
        }
      },
      "SiteResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Site id."
          },
          "companyId": {
            "type": "string",
            "format": "uuid",
            "description": "The company the site is for, when linked."
          },
          "name": {
            "type": "string",
            "description": "Site name."
          },
          "province": {
            "type": "string",
            "description": "Province, when recorded."
          },
          "address": {
            "type": "string",
            "description": "Street address, when recorded."
          },
          "status": {
            "type": "string",
            "enum": [
              "ACTIVE",
              "PLANNED",
              "CLOSED"
            ],
            "description": "Whether work there is planned, under way or finished."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the record was created (UTC)."
          }
        }
      },
      "TenderItemResponse": {
        "type": "object",
        "properties": {
          "ocid": {
            "type": "string",
            "description": "Open Contracting ID of the tender. Stable; use it as your key."
          },
          "title": {
            "type": "string",
            "description": "Tender title as published."
          },
          "buyer": {
            "type": "string",
            "description": "The procuring entity."
          },
          "province": {
            "type": "string",
            "description": "Province, when the notice states one."
          },
          "closesOn": {
            "type": "string",
            "format": "date",
            "description": "Closing date (UTC), when published."
          },
          "runwayDays": {
            "type": "integer",
            "format": "int32",
            "description": "Days from today to the closing date. Negative once closed; null when no closing date was published."
          },
          "score": {
            "type": "integer",
            "format": "int32",
            "description": "Match score. Higher is a closer fit to the company's profile."
          },
          "tier": {
            "type": "string",
            "enum": [
              "RECOMMENDED",
              "WORTH_A_LOOK",
              "STRETCH"
            ],
            "description": "RECOMMENDED, WORTH_A_LOOK, or STRETCH (the required CIDB grade is one above a grade the company holds)."
          },
          "reasons": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Plain-language reasons for the score."
          },
          "briefingNote": {
            "type": "string",
            "description": "Briefing session details, when the notice has any."
          },
          "decision": {
            "type": "string",
            "enum": [
              "BID",
              "NO_BID",
              "CLARIFY_FIRST"
            ],
            "description": "The decision a person recorded, or null if nobody has decided."
          },
          "analysisRunId": {
            "type": "string",
            "format": "uuid",
            "description": "The agent run that analysed the tender documents, when one has run."
          },
          "docCount": {
            "type": "integer",
            "format": "int32",
            "description": "How many documents the notice lists."
          }
        }
      },
      "WorkspaceResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Workspace id."
          },
          "productKey": {
            "type": "string",
            "enum": [
              "CONSTRUCT",
              "PROPERTY",
              "PROFESSIONAL",
              "FINANCIAL_SERVICES",
              "GROWTH"
            ],
            "description": "Which product this workspace is for."
          },
          "name": {
            "type": "string",
            "description": "Display name."
          }
        }
      }
    }
  }
}
