{
  "openapi": "3.1.0",
  "info": {
    "title": "Indraft API",
    "version": "1",
    "description": "A canonical CRM designed to be read and written by AI agents. Every error carries a stable code and a recovery hint written for an agent rather than for a human reading a log.\n\nHOW FAR THIS DOCUMENT IS GUARANTEED. Every path, parameter and request body here is generated from the same Zod schema the API validates against, so a request this document accepts is a request the API accepts. Response schemas are DECLARED rather than inferred, because a handler's return type does not exist at runtime; each one is driven against the running code and parsed with the schema it publishes, so a declared response that drifted would fail our build. Every operation carries one.\n\nVERSIONING. The `/v1` prefix is a namespace, not a stability promise, and until general availability this API may change in ways that break a caller. What is already frozen and will not change silently: the error codes, the identifier prefixes, the canonical object types, and the webhook event names, each of which is published as an enum here. When a deprecation policy exists it will appear in this description; there is none today, and saying so is more use than implying one."
  },
  "servers": [
    {
      "url": "https://api.indraft.io"
    }
  ],
  "components": {
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "code",
          "message",
          "recoveryHint",
          "requestId"
        ],
        "properties": {
          "code": {
            "type": "string",
            "enum": [
              "unauthorized",
              "forbidden_scope",
              "standing_override_refused",
              "workspace_not_found",
              "validation_error",
              "record_not_found",
              "ambiguous_identity",
              "duplicate_identity",
              "stale_version",
              "invalid_stage_transition",
              "idempotency_conflict",
              "not_reversible",
              "merge_conflict",
              "rate_limited",
              "quota_exceeded",
              "payload_too_large",
              "workspace_capacity",
              "payment_required",
              "billing_state_stale",
              "operation_in_flight",
              "internal_error"
            ]
          },
          "message": {
            "type": "string"
          },
          "recoveryHint": {
            "type": "string"
          },
          "requestId": {
            "type": "string"
          },
          "detail": {
            "$ref": "#/components/schemas/ErrorDetail"
          }
        }
      },
      "ErrorDetail": {
        "type": "object",
        "additionalProperties": true,
        "description": "The structured payload a recovery needs. Its shape differs per code; the keys below are the ones that recur, and anything else a code carries is present alongside them.",
        "properties": {
          "fieldErrors": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "One message per field the caller sent, keyed by that field. The key `(body)` is the request body itself, which is what an unrecognised key reports under."
          },
          "reason": {
            "type": "string",
            "description": "One sentence, where the refusal is about the request rather than a field. A refusal that names alternatives puts them here."
          },
          "available": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "What could have been asked for instead. Present on a filter, sort or group-by the API does not serve, so a correction is one edit rather than a round trip to read the schema."
          },
          "options": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The values an enum accepts, on a value it does not."
          },
          "currentVersion": {
            "type": "integer",
            "description": "What the record's version actually is, on `stale_version`. With the value you sent it is everything needed to decide whether to re-read and retry or to stop."
          },
          "expectedVersion": {
            "type": "integer",
            "description": "The version you sent, echoed back on `stale_version`."
          },
          "requiredScope": {
            "type": "string",
            "description": "The capability the credential lacks. Empty nowhere: a route no credential can reach is human-only and says so in its scopes instead."
          }
        }
      },
      "UpsertCandidate": {
        "type": "object",
        "required": [
          "id",
          "label",
          "matchedOn"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "The record this could have meant."
          },
          "label": {
            "type": "string",
            "description": "How it reads to a person, for a disambiguation prompt."
          },
          "matchedOn": {
            "type": "string",
            "description": "Why it was a possibility, and why that was not enough to decide. An exact name with no domain is the weakest evidence there is: two businesses share a name far more often than they share a domain."
          }
        }
      }
    },
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "An Indraft API token, or a WorkOS-issued session or MCP access token."
      }
    }
  },
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "paths": {
    "/v1/schema": {
      "get": {
        "summary": "Describe the CRM model, pipelines, custom fields, limits, and starter models",
        "description": "Describe the CRM: object types and whether they can be extended, pipelines and stages, custom fields, tags, your own capabilities, the workspace timezone and default currency, ID prefixes, every stated limit, every error code, and the derived values the database computes on read and nothing can write. Call this first; it removes the need to probe.",
        "tags": [
          "schema"
        ],
        "operationId": "get_v1_schema",
        "x-indraft-capability": "crm:read",
        "x-indraft-scopes": [
          "crm:read",
          "crm:write",
          "crm:configure",
          "crm:admin",
          "crm:revert",
          "data:export"
        ],
        "parameters": [
          {
            "name": "starterModel",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64,
              "description": "The key of one starter model to return in full. Absent returns only the summaries, which is enough to choose or to decide none of them fits. A key nobody defined is not an error."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "schema": {
                      "type": "object",
                      "properties": {
                        "objects": {
                          "type": "object",
                          "properties": {
                            "types": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              }
                            },
                            "canonical": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              }
                            },
                            "custom": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "key": {
                                    "type": "string"
                                  },
                                  "displayName": {
                                    "type": "string"
                                  },
                                  "displayNamePlural": {
                                    "type": "string"
                                  },
                                  "idPrefix": {
                                    "type": "string"
                                  },
                                  "fields": {
                                    "type": "array",
                                    "items": {
                                      "type": "object",
                                      "additionalProperties": {}
                                    }
                                  },
                                  "relationships": {
                                    "type": "array",
                                    "items": {
                                      "type": "object",
                                      "additionalProperties": {}
                                    }
                                  }
                                },
                                "required": [
                                  "key",
                                  "displayName",
                                  "displayNamePlural",
                                  "idPrefix",
                                  "fields",
                                  "relationships"
                                ],
                                "additionalProperties": true
                              }
                            },
                            "extensible": {
                              "type": "boolean"
                            },
                            "note": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "types",
                            "canonical",
                            "custom",
                            "extensible",
                            "note"
                          ],
                          "additionalProperties": true
                        },
                        "queries": {
                          "type": "object",
                          "properties": {
                            "operators": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              }
                            },
                            "maxPredicates": {
                              "type": "integer"
                            },
                            "filterExpression": {
                              "type": "string"
                            },
                            "sortExpression": {
                              "type": "string"
                            },
                            "defaultSort": {
                              "type": "string"
                            },
                            "filterable": {
                              "type": "object",
                              "additionalProperties": {
                                "type": "array",
                                "items": {
                                  "type": "string"
                                }
                              }
                            },
                            "note": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "operators",
                            "maxPredicates",
                            "filterExpression",
                            "sortExpression",
                            "defaultSort",
                            "filterable",
                            "note"
                          ],
                          "additionalProperties": true
                        },
                        "aggregates": {
                          "type": "object",
                          "properties": {
                            "functions": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              }
                            },
                            "dateBuckets": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              }
                            },
                            "maxGroups": {
                              "type": "integer"
                            },
                            "maxDimensions": {
                              "type": "integer"
                            },
                            "groupable": {
                              "type": "object",
                              "additionalProperties": {
                                "type": "array",
                                "items": {
                                  "type": "string"
                                }
                              }
                            },
                            "reducible": {
                              "type": "object",
                              "additionalProperties": {
                                "type": "array",
                                "items": {
                                  "type": "string"
                                }
                              }
                            },
                            "joins": {
                              "type": "object",
                              "additionalProperties": {
                                "type": "array",
                                "items": {
                                  "type": "object",
                                  "additionalProperties": {}
                                }
                              }
                            },
                            "calendar": {
                              "type": "object",
                              "properties": {
                                "fiscalYearStartMonth": {
                                  "type": "integer",
                                  "minimum": 1,
                                  "maximum": 12
                                },
                                "isCalendarYear": {
                                  "type": "boolean"
                                },
                                "note": {
                                  "type": "string"
                                }
                              },
                              "required": [
                                "fiscalYearStartMonth",
                                "isCalendarYear",
                                "note"
                              ],
                              "additionalProperties": true
                            },
                            "conversion": {
                              "type": "object",
                              "properties": {
                                "note": {
                                  "type": "string"
                                },
                                "rates": {
                                  "type": "array",
                                  "items": {
                                    "type": "object",
                                    "properties": {
                                      "id": {
                                        "type": "string"
                                      },
                                      "from": {
                                        "type": "string"
                                      },
                                      "to": {
                                        "type": "string"
                                      },
                                      "ratePpm": {
                                        "type": "integer"
                                      },
                                      "effectiveFrom": {
                                        "type": "string"
                                      },
                                      "sourceLabel": {
                                        "type": "string"
                                      },
                                      "assertedByActorId": {
                                        "type": "string"
                                      },
                                      "assertionKind": {
                                        "type": "string"
                                      }
                                    },
                                    "required": [
                                      "id",
                                      "from",
                                      "to",
                                      "ratePpm",
                                      "effectiveFrom",
                                      "sourceLabel",
                                      "assertedByActorId",
                                      "assertionKind"
                                    ],
                                    "additionalProperties": true
                                  }
                                }
                              },
                              "required": [
                                "note",
                                "rates"
                              ],
                              "additionalProperties": true
                            },
                            "note": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "functions",
                            "dateBuckets",
                            "maxGroups",
                            "maxDimensions",
                            "groupable",
                            "reducible",
                            "joins",
                            "calendar",
                            "conversion",
                            "note"
                          ],
                          "additionalProperties": true
                        },
                        "derived": {
                          "type": "object",
                          "properties": {
                            "values": {
                              "type": "object",
                              "additionalProperties": {
                                "type": "array",
                                "items": {
                                  "type": "object",
                                  "additionalProperties": {}
                                }
                              }
                            },
                            "computable": {
                              "type": "object",
                              "additionalProperties": {
                                "type": "object",
                                "properties": {
                                  "inputs": {
                                    "type": "array",
                                    "items": {
                                      "type": "string"
                                    }
                                  },
                                  "rollups": {
                                    "type": "array",
                                    "items": {
                                      "type": "string"
                                    }
                                  }
                                },
                                "required": [
                                  "inputs",
                                  "rollups"
                                ],
                                "additionalProperties": true
                              }
                            },
                            "note": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "values",
                            "computable",
                            "note"
                          ],
                          "additionalProperties": true
                        },
                        "pipelines": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string"
                              },
                              "name": {
                                "type": "string"
                              },
                              "isDefault": {
                                "type": "boolean"
                              },
                              "stages": {
                                "type": "array",
                                "items": {
                                  "type": "object",
                                  "properties": {
                                    "id": {
                                      "type": "string"
                                    },
                                    "pipelineId": {
                                      "type": "string"
                                    },
                                    "name": {
                                      "type": "string"
                                    },
                                    "position": {
                                      "type": "integer"
                                    },
                                    "stageKind": {
                                      "type": "string",
                                      "enum": [
                                        "open",
                                        "won",
                                        "lost"
                                      ]
                                    },
                                    "defaultProbabilityBps": {
                                      "type": "integer"
                                    }
                                  },
                                  "required": [
                                    "id",
                                    "pipelineId",
                                    "name",
                                    "position",
                                    "stageKind",
                                    "defaultProbabilityBps"
                                  ],
                                  "additionalProperties": true
                                }
                              }
                            },
                            "required": [
                              "id",
                              "name",
                              "isDefault",
                              "stages"
                            ],
                            "additionalProperties": true
                          }
                        },
                        "customFields": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string"
                              },
                              "key": {
                                "type": "string"
                              },
                              "label": {
                                "type": "string"
                              },
                              "target": {
                                "type": "string",
                                "enum": [
                                  "company",
                                  "contact",
                                  "opportunity",
                                  "interaction",
                                  "task"
                                ]
                              },
                              "valueType": {
                                "type": "string",
                                "enum": [
                                  "text",
                                  "number",
                                  "boolean",
                                  "timestamp",
                                  "enum",
                                  "json"
                                ]
                              },
                              "required": {
                                "type": "boolean"
                              },
                              "searchable": {
                                "type": "boolean"
                              },
                              "enumOptions": {
                                "type": "array",
                                "items": {
                                  "type": "string"
                                }
                              },
                              "computed": {
                                "type": "object",
                                "additionalProperties": {}
                              },
                              "archivedAt": {
                                "type": "string"
                              },
                              "createdAt": {
                                "type": "string"
                              },
                              "updatedAt": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "id",
                              "key",
                              "label",
                              "target",
                              "valueType",
                              "required",
                              "searchable",
                              "enumOptions",
                              "computed",
                              "archivedAt",
                              "createdAt",
                              "updatedAt"
                            ],
                            "additionalProperties": true
                          }
                        },
                        "tags": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string"
                              },
                              "name": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "id",
                              "name"
                            ],
                            "additionalProperties": true
                          }
                        },
                        "workspace": {
                          "type": "object",
                          "properties": {
                            "name": {
                              "type": "string"
                            },
                            "displayTimezone": {
                              "type": "string"
                            },
                            "defaultCurrency": {
                              "type": "string"
                            },
                            "fiscalYearStartMonth": {
                              "type": "integer"
                            }
                          },
                          "required": [
                            "name",
                            "displayTimezone",
                            "defaultCurrency",
                            "fiscalYearStartMonth"
                          ],
                          "additionalProperties": true
                        },
                        "caller": {
                          "type": "object",
                          "properties": {
                            "capabilities": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              }
                            },
                            "role": {
                              "type": "string"
                            },
                            "actorId": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "capabilities",
                            "role",
                            "actorId"
                          ],
                          "additionalProperties": true
                        },
                        "idPrefixes": {
                          "type": "object",
                          "additionalProperties": {
                            "type": "string"
                          }
                        },
                        "limits": {
                          "type": "object",
                          "additionalProperties": {
                            "anyOf": [
                              {
                                "type": "integer"
                              },
                              {
                                "type": "string"
                              }
                            ]
                          }
                        },
                        "configurable": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "notConfigurable": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "errors": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "code": {
                                "type": "string",
                                "enum": [
                                  "unauthorized",
                                  "forbidden_scope",
                                  "standing_override_refused",
                                  "workspace_not_found",
                                  "validation_error",
                                  "record_not_found",
                                  "ambiguous_identity",
                                  "duplicate_identity",
                                  "stale_version",
                                  "invalid_stage_transition",
                                  "idempotency_conflict",
                                  "not_reversible",
                                  "merge_conflict",
                                  "rate_limited",
                                  "quota_exceeded",
                                  "payload_too_large",
                                  "workspace_capacity",
                                  "payment_required",
                                  "billing_state_stale",
                                  "operation_in_flight",
                                  "internal_error"
                                ]
                              },
                              "meaning": {
                                "type": "string"
                              },
                              "recoveryHint": {
                                "type": "string"
                              },
                              "retryable": {
                                "type": "boolean"
                              }
                            },
                            "required": [
                              "code",
                              "meaning",
                              "recoveryHint",
                              "retryable"
                            ],
                            "additionalProperties": true
                          }
                        },
                        "starterModels": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "key": {
                                "type": "string"
                              },
                              "title": {
                                "type": "string"
                              },
                              "summary": {
                                "type": "string"
                              },
                              "bestFor": {
                                "type": "string"
                              },
                              "theDecision": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "key",
                              "title",
                              "summary",
                              "bestFor",
                              "theDecision"
                            ],
                            "additionalProperties": true
                          }
                        },
                        "starterModel": {
                          "type": "object",
                          "properties": {
                            "key": {
                              "type": "string"
                            },
                            "title": {
                              "type": "string"
                            },
                            "summary": {
                              "type": "string"
                            },
                            "bestFor": {
                              "type": "string"
                            },
                            "theDecision": {
                              "type": "string"
                            },
                            "objectTypes": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "key": {
                                    "type": "string",
                                    "pattern": "^[a-z][a-z0-9_]{0,47}$"
                                  },
                                  "displayName": {
                                    "type": "string",
                                    "minLength": 1,
                                    "maxLength": 200,
                                    "description": "What one record of this type is called, singular. A person reads this."
                                  },
                                  "displayNamePlural": {
                                    "type": "string",
                                    "minLength": 1,
                                    "maxLength": 200,
                                    "description": "The plural, for lists. Left out, a reasonable one is derived."
                                  },
                                  "idPrefix": {
                                    "type": "string",
                                    "pattern": "^[a-z][a-z0-9]{1,7}$"
                                  },
                                  "fields": {
                                    "type": "array",
                                    "items": {
                                      "type": "object",
                                      "properties": {
                                        "key": {
                                          "type": "string",
                                          "pattern": "^[a-z][a-z0-9_]{0,47}$",
                                          "description": "The name this field is addressed by, in every later read and write. Lower-case, starting with a letter. It is permanent: renaming a field is not offered, because every value already written is addressed by it."
                                        },
                                        "label": {
                                          "type": "string",
                                          "minLength": 1,
                                          "maxLength": 200,
                                          "description": "What a person sees. Change this freely; it names nothing."
                                        },
                                        "valueType": {
                                          "type": "string",
                                          "enum": [
                                            "text",
                                            "number",
                                            "boolean",
                                            "timestamp",
                                            "enum",
                                            "json"
                                          ],
                                          "description": "What kind of value this holds. Permanent, and chosen for what the field IS rather than for what is convenient to send: a date stored as text cannot be sorted, filtered by range, or counted by month, and converting it later is not offered."
                                        },
                                        "required": {
                                          "type": "boolean",
                                          "description": "Whether a record without this value can exist. Applies to records written from now on; records already stored are not made invalid by it."
                                        },
                                        "indexed": {
                                          "type": "boolean",
                                          "description": "Set this on a field you will filter or sort by. Without it those still work and get slower as the type fills up. There is a published cap on how many fields one type may index, so spend it on the ones a person actually searches."
                                        },
                                        "enumOptions": {
                                          "type": "array",
                                          "items": {
                                            "type": "string",
                                            "minLength": 1,
                                            "maxLength": 200
                                          },
                                          "maxItems": 100,
                                          "description": "The allowed values, required when valueType is enum and refused otherwise. A value outside this list is rejected rather than stored, so state every option you expect."
                                        }
                                      },
                                      "required": [
                                        "key",
                                        "label",
                                        "valueType"
                                      ],
                                      "additionalProperties": false
                                    },
                                    "minItems": 1,
                                    "maxItems": 100
                                  },
                                  "relationships": {
                                    "type": "array",
                                    "items": {
                                      "type": "object",
                                      "properties": {
                                        "name": {
                                          "type": "string",
                                          "pattern": "^[a-z][a-z0-9_]{0,47}$",
                                          "description": "How this link is addressed when writing a record. Permanent, like a field key."
                                        },
                                        "label": {
                                          "type": "string",
                                          "minLength": 1,
                                          "maxLength": 200,
                                          "description": "What a person sees for this link."
                                        },
                                        "target": {
                                          "type": "string",
                                          "pattern": "^[a-z][a-z0-9_]{0,47}$",
                                          "description": "What it points at: a canonical type (company, contact, opportunity, task) or the key of another type this workspace defined. The target must already exist."
                                        },
                                        "cardinality": {
                                          "type": "string",
                                          "enum": [
                                            "one",
                                            "many"
                                          ],
                                          "description": "Whether one record may point at one of the target or at many. Pick from the record's side: an Application belongs to one Candidate and a Candidate has many Applications, so on Application this is one."
                                        }
                                      },
                                      "required": [
                                        "name",
                                        "label",
                                        "target",
                                        "cardinality"
                                      ],
                                      "additionalProperties": false
                                    },
                                    "maxItems": 25
                                  },
                                  "identity": {
                                    "type": "object",
                                    "properties": {
                                      "field": {
                                        "type": "string",
                                        "pattern": "^[a-z][a-z0-9_]{0,47}$",
                                        "description": "The declared field whose value says two records are the same record. It must be a field of this type. Declare one only where the value really is unique per record: an upsert then matches on it instead of creating a second copy."
                                      },
                                      "normalize": {
                                        "type": "string",
                                        "enum": [
                                          "exact",
                                          "trimmed_casefold",
                                          "email",
                                          "domain",
                                          "phone"
                                        ],
                                        "description": "How the value is compared. `exact` compares as stored; `trimmed_casefold` ignores surrounding space and letter case; `email`, `domain` and `phone` apply the same rules the canonical types use, so a Candidate keyed on email and a contact keyed on email agree about what one address is."
                                      }
                                    },
                                    "required": [
                                      "field",
                                      "normalize"
                                    ],
                                    "additionalProperties": false
                                  }
                                },
                                "required": [
                                  "key",
                                  "displayName",
                                  "idPrefix",
                                  "fields"
                                ],
                                "additionalProperties": false
                              }
                            },
                            "pipelines": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "objectType": {
                                    "type": "string"
                                  },
                                  "name": {
                                    "type": "string"
                                  },
                                  "stages": {
                                    "type": "array",
                                    "items": {
                                      "type": "object",
                                      "properties": {
                                        "name": {
                                          "type": "string"
                                        },
                                        "stageKind": {
                                          "type": "string",
                                          "enum": [
                                            "open",
                                            "won",
                                            "lost"
                                          ]
                                        }
                                      },
                                      "required": [
                                        "name",
                                        "stageKind"
                                      ],
                                      "additionalProperties": true
                                    }
                                  }
                                },
                                "required": [
                                  "objectType",
                                  "name",
                                  "stages"
                                ],
                                "additionalProperties": true
                              }
                            }
                          },
                          "required": [
                            "key",
                            "title",
                            "summary",
                            "bestFor",
                            "theDecision",
                            "objectTypes",
                            "pipelines"
                          ],
                          "additionalProperties": true
                        }
                      },
                      "required": [
                        "objects",
                        "queries",
                        "aggregates",
                        "derived",
                        "pipelines",
                        "customFields",
                        "tags",
                        "workspace",
                        "caller",
                        "idPrefixes",
                        "limits",
                        "configurable",
                        "notConfigurable",
                        "errors",
                        "starterModels"
                      ],
                      "additionalProperties": true
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "schema",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/companies": {
      "get": {
        "summary": "List companies",
        "description": "List companies, newest first, with a cursor for the next page. Use this to walk the customer base; search_crm answers a keyword question and cannot enumerate. Narrow with filter, for example filter: ['owner_actor_id:eq:act_...', 'expected_close_date:isNotNull'] and sort: '-expected_close_date'; get_crm_schema lists the fields each type accepts.",
        "tags": [
          "companies"
        ],
        "operationId": "get_v1_companies",
        "x-indraft-capability": "crm:read",
        "x-indraft-scopes": [
          "crm:read",
          "crm:write",
          "crm:configure",
          "crm:admin",
          "crm:revert",
          "data:export"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "description": "How many to return. The page bound is published in the schema call, and asking for more is refused rather than quietly truncated."
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "The opaque marker from the previous page. Store it and hand it back; do not parse it. A cursor is only ever emitted when another row really exists, so a page you were given is never empty."
            }
          },
          {
            "name": "updatedSince",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 40,
              "description": "Only rows changed after this instant. The incremental read: without it a service syncing a large workspace has to walk all of it every time."
            }
          },
          {
            "name": "lastInteractionBefore",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 40,
              "description": "Only records whose most recent interaction is older than this, including those with none at all."
            }
          },
          {
            "name": "includeArchived",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "Include archived rows. Off by default, because a list is what you are working on and history is somewhere you go deliberately."
            }
          },
          {
            "name": "filter",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 560
                },
                {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 560
                  },
                  "maxItems": 8
                }
              ],
              "description": "Predicates, all of which must hold, written field:op:value. Only fields an index serves are accepted, and asking for one that is not names the ones that are."
            }
          },
          {
            "name": "or",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 560
                },
                {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 560
                  },
                  "maxItems": 4
                }
              ],
              "description": "Alternatives, ORed with each other and ANDed with filter. One level and never a tree: owned by me or owned by nobody is the question people ask, and anything deeper has a cost the caller cannot read off it."
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 65,
              "description": "A field to order by, with a leading minus for descending. Indexed fields only, for the same reason as filter."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "domain": {
                            "type": "string"
                          },
                          "domainNormalized": {
                            "type": "string"
                          },
                          "website": {
                            "type": "string"
                          },
                          "industry": {
                            "type": "string"
                          },
                          "lifecycle": {
                            "type": "object",
                            "properties": {
                              "category": {
                                "type": "string"
                              },
                              "label": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "category"
                            ],
                            "additionalProperties": true
                          },
                          "ownerActorId": {
                            "type": "string"
                          },
                          "externalProvider": {
                            "type": "string"
                          },
                          "externalId": {
                            "type": "string"
                          },
                          "version": {
                            "type": "integer"
                          },
                          "createdAt": {
                            "type": "string"
                          },
                          "updatedAt": {
                            "type": "string"
                          },
                          "archivedAt": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "name",
                          "domain",
                          "domainNormalized",
                          "website",
                          "industry",
                          "lifecycle",
                          "ownerActorId",
                          "externalProvider",
                          "externalId",
                          "version",
                          "createdAt",
                          "updatedAt",
                          "archivedAt"
                        ],
                        "additionalProperties": true
                      },
                      "description": "This page of results, in the order you asked for."
                    },
                    "nextCursor": {
                      "type": "string",
                      "description": "Hand this back to get the next page, or null when there is no next page. Null is the end of the list and an empty `items` is not: a cursor is only emitted when another row really exists."
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "items",
                    "nextCursor",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/companies:upsert": {
      "post": {
        "summary": "Create or safely match a company",
        "description": "Create a company, or match and update an existing one. Matching uses the normalized domain, never name similarity. If the identity is ambiguous the call returns candidates and writes NOTHING; choose one and pass its id, or set createDistinct to create a separate record.",
        "tags": [
          "companies"
        ],
        "operationId": "post_v1_companies_upsert",
        "x-indraft-capability": "crm:write",
        "x-indraft-scopes": [
          "crm:write",
          "crm:admin"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "idempotencyKey": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 200,
                    "description": "Your own name for this write, so retrying it cannot do it twice. Send the same key again and you get the SAME result back rather than a second record, which is what makes a re-run safe after a timeout you never saw the answer to. Derive it from what the write is about, not from the clock: `nightly-sync-halden` retries correctly and a timestamp does not."
                  },
                  "expectedVersion": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "The version you read before deciding to write. If the record has moved since, the write is refused instead of overwriting whatever changed. Send it whenever you read, reasoned, and then wrote: without it the last writer wins and neither of you finds out."
                  },
                  "sourceId": {
                    "type": "string",
                    "description": "The recorded source this claim came from, if one exists. It attaches evidence to the write, so a person reading the field later can see where it came from rather than only who sent it."
                  },
                  "assertionKind": {
                    "type": "string",
                    "enum": [
                      "observed",
                      "inferred",
                      "imported",
                      "user_supplied"
                    ],
                    "description": "HOW YOU KNOW. This is the field the product is built around, so say what is true rather than what is strongest: `observed` you saw it stated directly, `imported` it came from a file or another system, `inferred` you worked it out, `user_supplied` a person told you in so many words. They rank, weakest first: inferred < imported < observed < user_supplied < confirmed. A weaker claim does not overwrite a stronger one; it is reported in `held[]` and the stored value stands, so an unattended re-run converges instead of eroding what somebody checked. `confirmed` is not accepted here: it means a person checked the value, and only a signed-in person can set it."
                  },
                  "attributionLabel": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120,
                    "description": "A short name for the work this write belongs to, shown beside the actor so one credential can distinguish separate jobs. It is recorded as CALLER-SUPPLIED and grants nothing: it changes no permission, no idempotency scope and no quota."
                  },
                  "dryRun": {
                    "type": "boolean",
                    "description": "Report what this write WOULD do and commit nothing. The response carries the same change list, held fields and refusals as the real call, so it is the way to check a risky write, or a whole import, before it lands. Nothing is metered."
                  },
                  "overrideStanding": {
                    "type": "boolean",
                    "description": "Apply this write even when the value standing in the record was asserted more strongly than this one. Absent means no, which is the safe answer for a re-run. WITHOUT IT, a write can be accepted and change nothing: precedence is confirmed > user_supplied > observed > imported > inferred, and a weaker claim leaves the standing value in place and reports the field in `held[]` rather than failing. That is the whole of why a write can return 200 and not take. WITH it, this write wins regardless of what it is overruling, INCLUDING a value a person confirmed, so an agent that sets it by default has switched the provenance mechanism off. Set it per write, when the caller knows its claim supersedes what is there."
                  },
                  "id": {
                    "type": "string",
                    "description": "Update this exact company. Without it the call matches on identity evidence, in order: an external identity, then the normalised domain. Send the id when you already know which record you mean, which is the only way to be certain."
                  },
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 300,
                    "description": "The company's name. It is NOT identity: two companies may share a name, so a name alone never matches an existing record and creates a second one."
                  },
                  "domain": {
                    "type": "string",
                    "maxLength": 200,
                    "description": "The company's own domain, which IS identity: it is normalised and matched on, so sending it is what stops a nightly sync creating the same company twice. Send the domain, not a URL."
                  },
                  "website": {
                    "type": "string",
                    "maxLength": 500,
                    "description": "The full URL a person would open. Not matched on; `domain` is."
                  },
                  "industry": {
                    "type": "string",
                    "maxLength": 200,
                    "description": "What the company does, in words."
                  },
                  "lifecycle": {
                    "type": "object",
                    "properties": {
                      "category": {
                        "type": "string",
                        "enum": [
                          "lead",
                          "prospect",
                          "customer",
                          "former_customer",
                          "partner",
                          "other"
                        ],
                        "description": "Where this stands with you, from a fixed list so it can be counted and filtered across the workspace."
                      },
                      "label": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 200,
                        "description": "Your own word for it, shown to people. The category is what the product reasons with; this is what your team calls it."
                      }
                    },
                    "required": [
                      "category"
                    ],
                    "additionalProperties": false,
                    "description": "Where this company stands with you: the stage, and your own label for it."
                  },
                  "ownerActorId": {
                    "type": "string",
                    "minLength": 1,
                    "description": "Who owns this record: a member, or an agent. Null unassigns. Ownership is filterable, so it is how a person finds their own accounts."
                  },
                  "customFields": {
                    "type": "object",
                    "additionalProperties": {
                      "anyOf": [
                        {
                          "type": "string",
                          "maxLength": 2000
                        },
                        {
                          "type": "integer"
                        },
                        {
                          "type": "boolean"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "description": "Values for fields this workspace defined, keyed by the field's key. Read the schema first: a key that is not declared is REFUSED, with the available keys in the error, rather than stored where nobody will find it. Send null to clear one."
                  },
                  "tags": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 60
                    },
                    "maxItems": 50,
                    "description": "Labels, with no hierarchy and no meaning beyond membership. This REPLACES the tags on the record rather than adding to them, so send the full set you want."
                  },
                  "externalProvider": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120,
                    "description": "Which system issued `externalId`, for example `salesforce` or `stripe`. Required with it: two systems each numbering their records from one is the normal case, so an id without its issuer is not an identity and is refused."
                  },
                  "externalId": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200,
                    "description": "This record's id in that other system. Matched on BEFORE domain or email, so an integration can sync without remembering our ids."
                  },
                  "createDistinct": {
                    "type": "boolean",
                    "description": "Create a new record even though the evidence matches an existing one. For the case where you know two look alike and really are different. Absent means match, which is the safe answer for a re-run."
                  }
                },
                "required": [
                  "name"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": [
                        "created",
                        "matched",
                        "ambiguous"
                      ],
                      "description": "Whether this created a record, matched an existing one on real identity evidence, or found several and committed nothing. `ambiguous` is not an error: it means the evidence you sent fits more than one record, and `candidates` lists them so a caller can choose rather than have one picked for it."
                    },
                    "record": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "name": {
                          "type": "string"
                        },
                        "domain": {
                          "type": "string"
                        },
                        "domainNormalized": {
                          "type": "string"
                        },
                        "website": {
                          "type": "string"
                        },
                        "industry": {
                          "type": "string"
                        },
                        "lifecycle": {
                          "type": "object",
                          "properties": {
                            "category": {
                              "type": "string"
                            },
                            "label": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "category"
                          ],
                          "additionalProperties": true
                        },
                        "ownerActorId": {
                          "type": "string"
                        },
                        "externalProvider": {
                          "type": "string"
                        },
                        "externalId": {
                          "type": "string"
                        },
                        "version": {
                          "type": "integer"
                        },
                        "createdAt": {
                          "type": "string"
                        },
                        "updatedAt": {
                          "type": "string"
                        },
                        "archivedAt": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id",
                        "name",
                        "domain",
                        "domainNormalized",
                        "website",
                        "industry",
                        "lifecycle",
                        "ownerActorId",
                        "externalProvider",
                        "externalId",
                        "version",
                        "createdAt",
                        "updatedAt",
                        "archivedAt"
                      ],
                      "additionalProperties": true,
                      "description": "The record as it stands. Absent on an ambiguous upsert and on a dry run."
                    },
                    "mutation": {
                      "type": "object",
                      "properties": {
                        "mutationId": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "created",
                            "updated",
                            "matched",
                            "archived",
                            "merged",
                            "reverted",
                            "noop"
                          ],
                          "description": "What the write did. `noop` means it was accepted and changed nothing, because every value it carried already matched what was stored. IT IS NOT METERED: a noop does not count against your monthly change allowance, so a nightly sync that finds nothing new costs nothing. Neither does a write that only REDUCES what a workspace holds. `matched` means an upsert found an existing record on real identity evidence rather than creating a second one; `reverted` and `merged` are the undo and duplicate paths, and both are ordinary writes that count."
                        },
                        "targetId": {
                          "type": "string"
                        },
                        "record": {},
                        "changes": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "before": {},
                              "after": {}
                            },
                            "required": [
                              "field"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "held": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "kept": {},
                              "proposed": {},
                              "standing": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "incoming": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "actorId": {
                                "type": "string",
                                "minLength": 1
                              },
                              "assertedAt": {
                                "type": "string",
                                "minLength": 1
                              }
                            },
                            "required": [
                              "field",
                              "standing",
                              "incoming",
                              "actorId",
                              "assertedAt"
                            ],
                            "additionalProperties": false
                          },
                          "description": "Fields this write asked to change and did not, because the value standing in the record was asserted more strongly. THIS IS WHY A WRITE CAN RETURN 200 AND CHANGE NOTHING, and a caller that ignores it will believe it wrote something it did not. Precedence is confirmed > user_supplied > observed > imported > inferred, and a write carrying no `assertionKind` is weakest of all. Each entry reports the field, what the record still says, what you proposed, which claim won, and who made it. Send `overrideStanding` to write anyway, per write, when your claim really does supersede theirs."
                        },
                        "matchedBy": {
                          "type": "string",
                          "enum": [
                            "email",
                            "domain",
                            "external_id",
                            "idempotency_key",
                            "explicit_id"
                          ]
                        },
                        "reversible": {
                          "type": "boolean"
                        },
                        "replayed": {
                          "type": "boolean"
                        },
                        "dryRun": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "mutationId",
                        "status",
                        "reversible"
                      ],
                      "additionalProperties": false,
                      "description": "What the write did. Absent when nothing was written, which is the ambiguous case."
                    },
                    "candidates": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "minLength": 1
                          },
                          "label": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 300
                          },
                          "matchedOn": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 200
                          }
                        },
                        "required": [
                          "id",
                          "label",
                          "matchedOn"
                        ],
                        "additionalProperties": false
                      },
                      "description": "The records the evidence fits, when it fits more than one. Send the upsert again naming the `id` you mean."
                    },
                    "matchReason": {
                      "type": "string",
                      "description": "Why this matched the record it matched, in words, when it matched one."
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "status",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "A product quota is spent, or the subscription is not active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A conflict the caller can resolve: a stale expectedVersion, an idempotency key reused for different input, an ambiguous or duplicate identity, or a merge that no longer applies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The body, or a single record inside it, exceeds its bound.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "507": {
            "description": "The workspace is at its storage ceiling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/companies/{id}": {
      "get": {
        "summary": "Read one company",
        "description": "One company by its id, with its current field values. Provenance is not included here: ask for the company's context when you need to know who asserted a value and how they came by it.",
        "tags": [
          "companies"
        ],
        "operationId": "get_v1_companies__id_",
        "x-indraft-capability": "crm:read",
        "x-indraft-scopes": [
          "crm:read",
          "crm:write",
          "crm:configure",
          "crm:admin",
          "crm:revert",
          "data:export"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The company id, as returned by the call that created or matched it.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "company": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "name": {
                          "type": "string"
                        },
                        "domain": {
                          "type": "string"
                        },
                        "domainNormalized": {
                          "type": "string"
                        },
                        "website": {
                          "type": "string"
                        },
                        "industry": {
                          "type": "string"
                        },
                        "lifecycle": {
                          "type": "object",
                          "properties": {
                            "category": {
                              "type": "string"
                            },
                            "label": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "category"
                          ],
                          "additionalProperties": true
                        },
                        "ownerActorId": {
                          "type": "string"
                        },
                        "externalProvider": {
                          "type": "string"
                        },
                        "externalId": {
                          "type": "string"
                        },
                        "version": {
                          "type": "integer"
                        },
                        "createdAt": {
                          "type": "string"
                        },
                        "updatedAt": {
                          "type": "string"
                        },
                        "archivedAt": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id",
                        "name",
                        "domain",
                        "domainNormalized",
                        "website",
                        "industry",
                        "lifecycle",
                        "ownerActorId",
                        "externalProvider",
                        "externalId",
                        "version",
                        "createdAt",
                        "updatedAt",
                        "archivedAt"
                      ],
                      "additionalProperties": true
                    },
                    "customFields": {
                      "type": "object",
                      "additionalProperties": {}
                    },
                    "tags": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "derived": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string"
                          },
                          "value": {
                            "type": "integer"
                          },
                          "unit": {
                            "type": "string",
                            "enum": [
                              "minor_units",
                              "days"
                            ]
                          },
                          "currency": {
                            "type": "string"
                          },
                          "inputs": {
                            "type": "object",
                            "additionalProperties": {
                              "anyOf": [
                                {
                                  "type": "integer"
                                },
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            }
                          }
                        },
                        "required": [
                          "name",
                          "value",
                          "unit",
                          "currency",
                          "inputs"
                        ],
                        "additionalProperties": true
                      }
                    },
                    "standing": {
                      "type": "object",
                      "additionalProperties": {
                        "type": "object",
                        "properties": {
                          "assertionKind": {
                            "type": "string",
                            "enum": [
                              "observed",
                              "inferred",
                              "imported",
                              "user_supplied",
                              "confirmed"
                            ]
                          },
                          "actorId": {
                            "type": "string"
                          },
                          "assertedAt": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "assertionKind",
                          "actorId",
                          "assertedAt"
                        ],
                        "additionalProperties": true
                      },
                      "description": "Per field: which kind of claim is standing on it, who asserted it, and when. This is the provenance the product is sold on, keyed by column name so it lines up with `changes`, `held[]` and the unconfirmed queue. `confirmed` means a person checked it and outranks everything an agent can assert; `inferred` is the weakest and is what an agent's own conclusion should carry. A write whose claim ranks below what is here is held rather than applied."
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "company",
                    "customFields",
                    "tags",
                    "derived",
                    "standing",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such record, or it belongs to another workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/companies/{id}/context": {
      "get": {
        "summary": "Bounded company context for an agent",
        "description": "One bounded view of a company: the record, its contacts, open opportunities, open tasks, and recent interactions. Each collection is capped and the response says whether the cap was reached.",
        "tags": [
          "companies"
        ],
        "operationId": "get_v1_companies__id__context",
        "x-indraft-capability": "crm:read",
        "x-indraft-scopes": [
          "crm:read",
          "crm:write",
          "crm:configure",
          "crm:admin",
          "crm:revert",
          "data:export"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The company id, as returned by the call that created or matched it.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "interactions",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "description": "How many recent interactions to include in the brief. Bounded, and the answer says when the bound bit rather than implying it returned everything."
            }
          },
          {
            "name": "openTasks",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "description": "How many open tasks to include in the brief, bounded the same way."
            }
          },
          {
            "name": "openOpportunities",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "description": "How many open deals to include in the brief, bounded the same way."
            }
          },
          {
            "name": "relatedContacts",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "description": "How many of the account's contacts to include in the brief, bounded the same way."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "company": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "name": {
                          "type": "string"
                        },
                        "domain": {
                          "type": "string"
                        },
                        "domainNormalized": {
                          "type": "string"
                        },
                        "website": {
                          "type": "string"
                        },
                        "industry": {
                          "type": "string"
                        },
                        "lifecycle": {
                          "type": "object",
                          "properties": {
                            "category": {
                              "type": "string"
                            },
                            "label": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "category"
                          ],
                          "additionalProperties": true
                        },
                        "ownerActorId": {
                          "type": "string"
                        },
                        "externalProvider": {
                          "type": "string"
                        },
                        "externalId": {
                          "type": "string"
                        },
                        "version": {
                          "type": "integer"
                        },
                        "createdAt": {
                          "type": "string"
                        },
                        "updatedAt": {
                          "type": "string"
                        },
                        "archivedAt": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id",
                        "name",
                        "domain",
                        "domainNormalized",
                        "website",
                        "industry",
                        "lifecycle",
                        "ownerActorId",
                        "externalProvider",
                        "externalId",
                        "version",
                        "createdAt",
                        "updatedAt",
                        "archivedAt"
                      ],
                      "additionalProperties": true,
                      "description": "The company record itself, with its custom values and tags."
                    },
                    "contacts": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "displayName": {
                            "type": "string"
                          },
                          "primaryEmail": {
                            "type": "string"
                          },
                          "emailNormalized": {
                            "type": "string"
                          },
                          "phone": {
                            "type": "string"
                          },
                          "phoneNormalized": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "companyName": {
                            "type": "string"
                          },
                          "lifecycle": {
                            "type": "object",
                            "properties": {
                              "category": {
                                "type": "string"
                              },
                              "label": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "category"
                            ],
                            "additionalProperties": true
                          },
                          "ownerActorId": {
                            "type": "string"
                          },
                          "externalProvider": {
                            "type": "string"
                          },
                          "externalId": {
                            "type": "string"
                          },
                          "version": {
                            "type": "integer"
                          },
                          "createdAt": {
                            "type": "string"
                          },
                          "updatedAt": {
                            "type": "string"
                          },
                          "archivedAt": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "displayName",
                          "primaryEmail",
                          "emailNormalized",
                          "phone",
                          "phoneNormalized",
                          "title",
                          "lifecycle",
                          "ownerActorId",
                          "externalProvider",
                          "externalId",
                          "version",
                          "createdAt",
                          "updatedAt",
                          "archivedAt"
                        ],
                        "additionalProperties": true
                      },
                      "description": "People attached to this company, capped. Check `truncated.contacts`."
                    },
                    "openOpportunities": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "pipelineId": {
                            "type": "string"
                          },
                          "stageId": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "open",
                              "won",
                              "lost"
                            ]
                          },
                          "amountMinor": {
                            "type": "integer"
                          },
                          "currency": {
                            "type": "string"
                          },
                          "probabilityBps": {
                            "type": "integer"
                          },
                          "expectedCloseDate": {
                            "type": "string"
                          },
                          "companyName": {
                            "type": "string"
                          },
                          "lastActor": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string"
                              },
                              "kind": {
                                "type": "string",
                                "enum": [
                                  "human",
                                  "agent",
                                  "api_token",
                                  "system"
                                ]
                              },
                              "label": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "id",
                              "kind",
                              "label"
                            ],
                            "additionalProperties": true
                          },
                          "ownerActorId": {
                            "type": "string"
                          },
                          "externalProvider": {
                            "type": "string"
                          },
                          "externalId": {
                            "type": "string"
                          },
                          "version": {
                            "type": "integer"
                          },
                          "createdAt": {
                            "type": "string"
                          },
                          "updatedAt": {
                            "type": "string"
                          },
                          "archivedAt": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "name",
                          "pipelineId",
                          "stageId",
                          "status",
                          "amountMinor",
                          "currency",
                          "probabilityBps",
                          "expectedCloseDate",
                          "ownerActorId",
                          "externalProvider",
                          "externalId",
                          "version",
                          "createdAt",
                          "updatedAt",
                          "archivedAt"
                        ],
                        "additionalProperties": true
                      },
                      "description": "Deals still open on this company, capped. Closed ones are not here."
                    },
                    "openTasks": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "open",
                              "done",
                              "cancelled"
                            ]
                          },
                          "assigneeActorId": {
                            "type": "string"
                          },
                          "assignee": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string"
                              },
                              "kind": {
                                "type": "string",
                                "enum": [
                                  "human",
                                  "agent",
                                  "api_token",
                                  "system"
                                ]
                              },
                              "label": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "id",
                              "kind",
                              "label"
                            ],
                            "additionalProperties": true
                          },
                          "dueAt": {
                            "type": "string"
                          },
                          "priority": {
                            "type": "string",
                            "enum": [
                              "low",
                              "normal",
                              "high"
                            ]
                          },
                          "completedAt": {
                            "type": "string"
                          },
                          "ownerActorId": {
                            "type": "string"
                          },
                          "version": {
                            "type": "integer"
                          },
                          "links": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "objectType": {
                                  "type": "string",
                                  "enum": [
                                    "company",
                                    "contact",
                                    "opportunity"
                                  ]
                                },
                                "objectId": {
                                  "type": "string"
                                }
                              },
                              "required": [
                                "objectType",
                                "objectId"
                              ],
                              "additionalProperties": true
                            }
                          },
                          "createdAt": {
                            "type": "string"
                          },
                          "updatedAt": {
                            "type": "string"
                          },
                          "archivedAt": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "title",
                          "status",
                          "assigneeActorId",
                          "dueAt",
                          "priority",
                          "completedAt",
                          "ownerActorId",
                          "version",
                          "links",
                          "createdAt",
                          "updatedAt",
                          "archivedAt"
                        ],
                        "additionalProperties": true
                      },
                      "description": "Work still outstanding on this company, capped. Done and cancelled are not here."
                    },
                    "recentInteractions": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "interactionType": {
                            "type": "string",
                            "enum": [
                              "email",
                              "call",
                              "meeting",
                              "message",
                              "note"
                            ]
                          },
                          "direction": {
                            "type": "string",
                            "enum": [
                              "inbound",
                              "outbound",
                              "internal"
                            ]
                          },
                          "subject": {
                            "type": "string"
                          },
                          "summary": {
                            "type": "string"
                          },
                          "assertionKind": {
                            "type": "string",
                            "enum": [
                              "observed",
                              "inferred",
                              "imported",
                              "user_supplied"
                            ]
                          },
                          "occurredAt": {
                            "type": "string"
                          },
                          "sourceId": {
                            "type": "string"
                          },
                          "createdByActorId": {
                            "type": "string"
                          },
                          "actor": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string"
                              },
                              "kind": {
                                "type": "string",
                                "enum": [
                                  "human",
                                  "agent",
                                  "api_token",
                                  "system"
                                ]
                              },
                              "label": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "id",
                              "kind",
                              "label"
                            ],
                            "additionalProperties": true
                          },
                          "links": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "objectType": {
                                  "type": "string",
                                  "enum": [
                                    "company",
                                    "contact",
                                    "opportunity"
                                  ]
                                },
                                "objectId": {
                                  "type": "string"
                                }
                              },
                              "required": [
                                "objectType",
                                "objectId"
                              ],
                              "additionalProperties": true
                            }
                          },
                          "createdAt": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "interactionType",
                          "direction",
                          "subject",
                          "summary",
                          "assertionKind",
                          "occurredAt",
                          "sourceId",
                          "createdByActorId",
                          "links",
                          "createdAt"
                        ],
                        "additionalProperties": true
                      },
                      "description": "The most recent interactions, newest first, capped. Summaries and metadata only: this product never stores a message body or a transcript."
                    },
                    "ownRecords": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "typeKey": {
                            "type": "string"
                          },
                          "displayName": {
                            "type": "string"
                          },
                          "via": {
                            "type": "string"
                          },
                          "items": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "id": {
                                  "type": "string"
                                },
                                "version": {
                                  "type": "integer"
                                },
                                "createdAt": {
                                  "type": "string"
                                },
                                "updatedAt": {
                                  "type": "string"
                                },
                                "archivedAt": {
                                  "type": "string"
                                },
                                "values": {
                                  "type": "object",
                                  "additionalProperties": {}
                                },
                                "links": {
                                  "type": "object",
                                  "additionalProperties": {
                                    "type": "array",
                                    "items": {
                                      "type": "string"
                                    }
                                  }
                                },
                                "lastActor": {
                                  "type": "object",
                                  "properties": {
                                    "id": {
                                      "type": "string"
                                    },
                                    "kind": {
                                      "type": "string",
                                      "enum": [
                                        "human",
                                        "agent",
                                        "api_token",
                                        "system"
                                      ]
                                    },
                                    "label": {
                                      "type": "string"
                                    }
                                  },
                                  "required": [
                                    "id",
                                    "kind",
                                    "label"
                                  ],
                                  "additionalProperties": true
                                },
                                "stage": {
                                  "type": "object",
                                  "properties": {
                                    "pipelineId": {
                                      "type": "string"
                                    },
                                    "stageId": {
                                      "type": "string"
                                    },
                                    "status": {
                                      "type": "string",
                                      "enum": [
                                        "open",
                                        "won",
                                        "lost"
                                      ]
                                    }
                                  },
                                  "required": [
                                    "pipelineId",
                                    "stageId",
                                    "status"
                                  ],
                                  "additionalProperties": true
                                }
                              },
                              "required": [
                                "id",
                                "version",
                                "createdAt",
                                "updatedAt",
                                "archivedAt",
                                "values",
                                "links"
                              ],
                              "additionalProperties": true
                            }
                          },
                          "truncated": {
                            "type": "boolean"
                          }
                        },
                        "required": [
                          "typeKey",
                          "displayName",
                          "via",
                          "items",
                          "truncated"
                        ],
                        "additionalProperties": true
                      },
                      "description": "Records of types THIS workspace defined that point at the company, grouped by type. Always present and empty when the workspace has modelled none, because absent and empty are different statements."
                    },
                    "standing": {
                      "type": "object",
                      "additionalProperties": {
                        "type": "object",
                        "properties": {
                          "assertionKind": {
                            "type": "string",
                            "enum": [
                              "observed",
                              "inferred",
                              "imported",
                              "user_supplied",
                              "confirmed"
                            ]
                          },
                          "actorId": {
                            "type": "string"
                          },
                          "assertedAt": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "assertionKind",
                          "actorId",
                          "assertedAt"
                        ],
                        "additionalProperties": true
                      },
                      "description": "Per field: which kind of claim is standing on it, who asserted it, and when. This is the provenance the product is sold on, keyed by column name so it lines up with `changes`, `held[]` and the unconfirmed queue. `confirmed` means a person checked it and outranks everything an agent can assert; `inferred` is the weakest and is what an agent's own conclusion should carry. A write whose claim ranks below what is here is held rather than applied."
                    },
                    "limits": {
                      "type": "object",
                      "properties": {
                        "interactions": {
                          "type": "integer"
                        },
                        "openTasks": {
                          "type": "integer"
                        },
                        "openOpportunities": {
                          "type": "integer"
                        },
                        "relatedContacts": {
                          "type": "integer"
                        }
                      },
                      "required": [
                        "interactions",
                        "openTasks",
                        "openOpportunities",
                        "relatedContacts"
                      ],
                      "additionalProperties": true,
                      "description": "The cap applied to each collection above, so a caller can tell a short list from a truncated one without guessing."
                    },
                    "truncated": {
                      "type": "object",
                      "additionalProperties": {
                        "type": "boolean"
                      },
                      "description": "Which collections hit their cap, keyed by name. True means there is more that is not here, so do not conclude from this response that a company has three contacts."
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "company",
                    "contacts",
                    "openOpportunities",
                    "openTasks",
                    "recentInteractions",
                    "ownRecords",
                    "standing",
                    "limits",
                    "truncated",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such record, or it belongs to another workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/companies/{id}/interactions": {
      "get": {
        "summary": "Recent interactions for a company",
        "description": "What was said, newest first, for one company. Interactions are summaries a caller wrote, never raw messages: Indraft never connects to mail and stores no transcript.",
        "tags": [
          "companies"
        ],
        "operationId": "get_v1_companies__id__interactions",
        "x-indraft-capability": "crm:read",
        "x-indraft-scopes": [
          "crm:read",
          "crm:write",
          "crm:configure",
          "crm:admin",
          "crm:revert",
          "data:export"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The company id, as returned by the call that created or matched it.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "description": "How many to return. The page bound is published in the schema call, and asking for more is refused rather than quietly truncated."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "interactions": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "interactionType": {
                            "type": "string",
                            "enum": [
                              "email",
                              "call",
                              "meeting",
                              "message",
                              "note"
                            ]
                          },
                          "direction": {
                            "type": "string",
                            "enum": [
                              "inbound",
                              "outbound",
                              "internal"
                            ]
                          },
                          "subject": {
                            "type": "string"
                          },
                          "summary": {
                            "type": "string"
                          },
                          "assertionKind": {
                            "type": "string",
                            "enum": [
                              "observed",
                              "inferred",
                              "imported",
                              "user_supplied"
                            ]
                          },
                          "occurredAt": {
                            "type": "string"
                          },
                          "sourceId": {
                            "type": "string"
                          },
                          "createdByActorId": {
                            "type": "string"
                          },
                          "actor": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string"
                              },
                              "kind": {
                                "type": "string",
                                "enum": [
                                  "human",
                                  "agent",
                                  "api_token",
                                  "system"
                                ]
                              },
                              "label": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "id",
                              "kind",
                              "label"
                            ],
                            "additionalProperties": true
                          },
                          "links": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "objectType": {
                                  "type": "string",
                                  "enum": [
                                    "company",
                                    "contact",
                                    "opportunity"
                                  ]
                                },
                                "objectId": {
                                  "type": "string"
                                }
                              },
                              "required": [
                                "objectType",
                                "objectId"
                              ],
                              "additionalProperties": true
                            }
                          },
                          "createdAt": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "interactionType",
                          "direction",
                          "subject",
                          "summary",
                          "assertionKind",
                          "occurredAt",
                          "sourceId",
                          "createdByActorId",
                          "links",
                          "createdAt"
                        ],
                        "additionalProperties": true
                      }
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "interactions",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such record, or it belongs to another workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/companies:merge": {
      "post": {
        "summary": "Merge a duplicate company into a target",
        "description": "Merge a duplicate company into a target. References move to the target and the source is archived. Not undoable by revert_change; use unmerge.",
        "tags": [
          "companies"
        ],
        "operationId": "post_v1_companies_merge",
        "x-indraft-capability": "crm:write",
        "x-indraft-scopes": [
          "crm:write",
          "crm:admin"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "idempotencyKey": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 200,
                    "description": "Your own name for this write, so retrying it cannot do it twice. Send the same key again and you get the SAME result back rather than a second record, which is what makes a re-run safe after a timeout you never saw the answer to. Derive it from what the write is about, not from the clock: `nightly-sync-halden` retries correctly and a timestamp does not."
                  },
                  "expectedVersion": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "The version you read before deciding to write. If the record has moved since, the write is refused instead of overwriting whatever changed. Send it whenever you read, reasoned, and then wrote: without it the last writer wins and neither of you finds out."
                  },
                  "sourceId": {
                    "type": "string",
                    "minLength": 1
                  },
                  "assertionKind": {
                    "type": "string",
                    "enum": [
                      "observed",
                      "inferred",
                      "imported",
                      "user_supplied"
                    ],
                    "description": "HOW YOU KNOW. This is the field the product is built around, so say what is true rather than what is strongest: `observed` you saw it stated directly, `imported` it came from a file or another system, `inferred` you worked it out, `user_supplied` a person told you in so many words. They rank, weakest first: inferred < imported < observed < user_supplied < confirmed. A weaker claim does not overwrite a stronger one; it is reported in `held[]` and the stored value stands, so an unattended re-run converges instead of eroding what somebody checked. `confirmed` is not accepted here: it means a person checked the value, and only a signed-in person can set it."
                  },
                  "attributionLabel": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120,
                    "description": "A short name for the work this write belongs to, shown beside the actor so one credential can distinguish separate jobs. It is recorded as CALLER-SUPPLIED and grants nothing: it changes no permission, no idempotency scope and no quota."
                  },
                  "dryRun": {
                    "type": "boolean",
                    "description": "Report what this write WOULD do and commit nothing. The response carries the same change list, held fields and refusals as the real call, so it is the way to check a risky write, or a whole import, before it lands. Nothing is metered."
                  },
                  "overrideStanding": {
                    "type": "boolean",
                    "description": "Apply this write even when the value standing in the record was asserted more strongly than this one. Absent means no, which is the safe answer for a re-run. WITHOUT IT, a write can be accepted and change nothing: precedence is confirmed > user_supplied > observed > imported > inferred, and a weaker claim leaves the standing value in place and reports the field in `held[]` rather than failing. That is the whole of why a write can return 200 and not take. WITH it, this write wins regardless of what it is overruling, INCLUDING a value a person confirmed, so an agent that sets it by default has switched the provenance mechanism off. Set it per write, when the caller knows its claim supersedes what is there."
                  },
                  "targetId": {
                    "type": "string",
                    "minLength": 1
                  }
                },
                "required": [
                  "sourceId",
                  "targetId"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "record": {
                      "type": "object",
                      "properties": {
                        "mergeId": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "mergeId"
                      ],
                      "additionalProperties": true
                    },
                    "mutation": {
                      "type": "object",
                      "properties": {
                        "mutationId": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "created",
                            "updated",
                            "matched",
                            "archived",
                            "merged",
                            "reverted",
                            "noop"
                          ],
                          "description": "What the write did. `noop` means it was accepted and changed nothing, because every value it carried already matched what was stored. IT IS NOT METERED: a noop does not count against your monthly change allowance, so a nightly sync that finds nothing new costs nothing. Neither does a write that only REDUCES what a workspace holds. `matched` means an upsert found an existing record on real identity evidence rather than creating a second one; `reverted` and `merged` are the undo and duplicate paths, and both are ordinary writes that count."
                        },
                        "targetId": {
                          "type": "string"
                        },
                        "record": {},
                        "changes": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "before": {},
                              "after": {}
                            },
                            "required": [
                              "field"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "held": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "kept": {},
                              "proposed": {},
                              "standing": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "incoming": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "actorId": {
                                "type": "string",
                                "minLength": 1
                              },
                              "assertedAt": {
                                "type": "string",
                                "minLength": 1
                              }
                            },
                            "required": [
                              "field",
                              "standing",
                              "incoming",
                              "actorId",
                              "assertedAt"
                            ],
                            "additionalProperties": false
                          },
                          "description": "Fields this write asked to change and did not, because the value standing in the record was asserted more strongly. THIS IS WHY A WRITE CAN RETURN 200 AND CHANGE NOTHING, and a caller that ignores it will believe it wrote something it did not. Precedence is confirmed > user_supplied > observed > imported > inferred, and a write carrying no `assertionKind` is weakest of all. Each entry reports the field, what the record still says, what you proposed, which claim won, and who made it. Send `overrideStanding` to write anyway, per write, when your claim really does supersede theirs."
                        },
                        "matchedBy": {
                          "type": "string",
                          "enum": [
                            "email",
                            "domain",
                            "external_id",
                            "idempotency_key",
                            "explicit_id"
                          ]
                        },
                        "reversible": {
                          "type": "boolean"
                        },
                        "replayed": {
                          "type": "boolean"
                        },
                        "dryRun": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "mutationId",
                        "status",
                        "reversible"
                      ],
                      "additionalProperties": false
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "mutation",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "A product quota is spent, or the subscription is not active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A conflict the caller can resolve: a stale expectedVersion, an idempotency key reused for different input, an ambiguous or duplicate identity, or a merge that no longer applies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The body, or a single record inside it, exceeds its bound.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "507": {
            "description": "The workspace is at its storage ceiling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/contacts": {
      "get": {
        "summary": "List contacts",
        "description": "List contacts, newest first, with a cursor for the next page. Use this to walk the people you know; search_crm answers a keyword question and cannot enumerate. Narrow with filter, for example filter: ['owner_actor_id:eq:act_...', 'expected_close_date:isNotNull'] and sort: '-expected_close_date'; get_crm_schema lists the fields each type accepts.",
        "tags": [
          "contacts"
        ],
        "operationId": "get_v1_contacts",
        "x-indraft-capability": "crm:read",
        "x-indraft-scopes": [
          "crm:read",
          "crm:write",
          "crm:configure",
          "crm:admin",
          "crm:revert",
          "data:export"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "description": "How many to return. The page bound is published in the schema call, and asking for more is refused rather than quietly truncated."
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "The opaque marker from the previous page. Store it and hand it back; do not parse it. A cursor is only ever emitted when another row really exists, so a page you were given is never empty."
            }
          },
          {
            "name": "updatedSince",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 40,
              "description": "Only rows changed after this instant. The incremental read: without it a service syncing a large workspace has to walk all of it every time."
            }
          },
          {
            "name": "lastInteractionBefore",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 40,
              "description": "Only records whose most recent interaction is older than this, including those with none at all."
            }
          },
          {
            "name": "includeArchived",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "Include archived rows. Off by default, because a list is what you are working on and history is somewhere you go deliberately."
            }
          },
          {
            "name": "filter",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 560
                },
                {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 560
                  },
                  "maxItems": 8
                }
              ],
              "description": "Predicates, all of which must hold, written field:op:value. Only fields an index serves are accepted, and asking for one that is not names the ones that are."
            }
          },
          {
            "name": "or",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 560
                },
                {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 560
                  },
                  "maxItems": 4
                }
              ],
              "description": "Alternatives, ORed with each other and ANDed with filter. One level and never a tree: owned by me or owned by nobody is the question people ask, and anything deeper has a cost the caller cannot read off it."
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 65,
              "description": "A field to order by, with a leading minus for descending. Indexed fields only, for the same reason as filter."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "displayName": {
                            "type": "string"
                          },
                          "primaryEmail": {
                            "type": "string"
                          },
                          "emailNormalized": {
                            "type": "string"
                          },
                          "phone": {
                            "type": "string"
                          },
                          "phoneNormalized": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "companyName": {
                            "type": "string"
                          },
                          "lifecycle": {
                            "type": "object",
                            "properties": {
                              "category": {
                                "type": "string"
                              },
                              "label": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "category"
                            ],
                            "additionalProperties": true
                          },
                          "ownerActorId": {
                            "type": "string"
                          },
                          "externalProvider": {
                            "type": "string"
                          },
                          "externalId": {
                            "type": "string"
                          },
                          "version": {
                            "type": "integer"
                          },
                          "createdAt": {
                            "type": "string"
                          },
                          "updatedAt": {
                            "type": "string"
                          },
                          "archivedAt": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "displayName",
                          "primaryEmail",
                          "emailNormalized",
                          "phone",
                          "phoneNormalized",
                          "title",
                          "lifecycle",
                          "ownerActorId",
                          "externalProvider",
                          "externalId",
                          "version",
                          "createdAt",
                          "updatedAt",
                          "archivedAt"
                        ],
                        "additionalProperties": true
                      },
                      "description": "This page of results, in the order you asked for."
                    },
                    "nextCursor": {
                      "type": "string",
                      "description": "Hand this back to get the next page, or null when there is no next page. Null is the end of the list and an empty `items` is not: a cursor is only emitted when another row really exists."
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "items",
                    "nextCursor",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/contacts:upsert": {
      "post": {
        "summary": "Create or safely match a contact",
        "description": "Create a contact, or match and update an existing one. Matching uses the normalized email, never name similarity. An ambiguous identity returns candidates and writes nothing.",
        "tags": [
          "contacts"
        ],
        "operationId": "post_v1_contacts_upsert",
        "x-indraft-capability": "crm:write",
        "x-indraft-scopes": [
          "crm:write",
          "crm:admin"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "idempotencyKey": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 200,
                    "description": "Your own name for this write, so retrying it cannot do it twice. Send the same key again and you get the SAME result back rather than a second record, which is what makes a re-run safe after a timeout you never saw the answer to. Derive it from what the write is about, not from the clock: `nightly-sync-halden` retries correctly and a timestamp does not."
                  },
                  "expectedVersion": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "The version you read before deciding to write. If the record has moved since, the write is refused instead of overwriting whatever changed. Send it whenever you read, reasoned, and then wrote: without it the last writer wins and neither of you finds out."
                  },
                  "sourceId": {
                    "type": "string",
                    "description": "The recorded source this claim came from, if one exists. It attaches evidence to the write, so a person reading the field later can see where it came from rather than only who sent it."
                  },
                  "assertionKind": {
                    "type": "string",
                    "enum": [
                      "observed",
                      "inferred",
                      "imported",
                      "user_supplied"
                    ],
                    "description": "HOW YOU KNOW. This is the field the product is built around, so say what is true rather than what is strongest: `observed` you saw it stated directly, `imported` it came from a file or another system, `inferred` you worked it out, `user_supplied` a person told you in so many words. They rank, weakest first: inferred < imported < observed < user_supplied < confirmed. A weaker claim does not overwrite a stronger one; it is reported in `held[]` and the stored value stands, so an unattended re-run converges instead of eroding what somebody checked. `confirmed` is not accepted here: it means a person checked the value, and only a signed-in person can set it."
                  },
                  "attributionLabel": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120,
                    "description": "A short name for the work this write belongs to, shown beside the actor so one credential can distinguish separate jobs. It is recorded as CALLER-SUPPLIED and grants nothing: it changes no permission, no idempotency scope and no quota."
                  },
                  "dryRun": {
                    "type": "boolean",
                    "description": "Report what this write WOULD do and commit nothing. The response carries the same change list, held fields and refusals as the real call, so it is the way to check a risky write, or a whole import, before it lands. Nothing is metered."
                  },
                  "overrideStanding": {
                    "type": "boolean",
                    "description": "Apply this write even when the value standing in the record was asserted more strongly than this one. Absent means no, which is the safe answer for a re-run. WITHOUT IT, a write can be accepted and change nothing: precedence is confirmed > user_supplied > observed > imported > inferred, and a weaker claim leaves the standing value in place and reports the field in `held[]` rather than failing. That is the whole of why a write can return 200 and not take. WITH it, this write wins regardless of what it is overruling, INCLUDING a value a person confirmed, so an agent that sets it by default has switched the provenance mechanism off. Set it per write, when the caller knows its claim supersedes what is there."
                  },
                  "id": {
                    "type": "string"
                  },
                  "displayName": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 300
                  },
                  "email": {
                    "type": "string",
                    "maxLength": 200
                  },
                  "phone": {
                    "type": "string",
                    "maxLength": 60
                  },
                  "title": {
                    "type": "string",
                    "maxLength": 200
                  },
                  "lifecycle": {
                    "type": "object",
                    "properties": {
                      "category": {
                        "type": "string",
                        "enum": [
                          "lead",
                          "prospect",
                          "customer",
                          "former_customer",
                          "partner",
                          "other"
                        ],
                        "description": "Where this stands with you, from a fixed list so it can be counted and filtered across the workspace."
                      },
                      "label": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 200,
                        "description": "Your own word for it, shown to people. The category is what the product reasons with; this is what your team calls it."
                      }
                    },
                    "required": [
                      "category"
                    ],
                    "additionalProperties": false
                  },
                  "companyId": {
                    "type": "string"
                  },
                  "companyRole": {
                    "type": "string",
                    "enum": [
                      "employee",
                      "founder",
                      "executive",
                      "advisor",
                      "other"
                    ]
                  },
                  "ownerActorId": {
                    "type": "string",
                    "minLength": 1
                  },
                  "customFields": {
                    "type": "object",
                    "additionalProperties": {
                      "anyOf": [
                        {
                          "type": "string",
                          "maxLength": 2000
                        },
                        {
                          "type": "integer"
                        },
                        {
                          "type": "boolean"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "description": "Values for fields this workspace defined, keyed by the field's key. Read the schema first: a key that is not declared is REFUSED, with the available keys in the error, rather than stored where nobody will find it. Send null to clear one."
                  },
                  "tags": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 60
                    },
                    "maxItems": 50
                  },
                  "externalProvider": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120,
                    "description": "Which system issued `externalId`, for example `salesforce` or `stripe`. Required with it: two systems each numbering their records from one is the normal case, so an id without its issuer is not an identity and is refused."
                  },
                  "externalId": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200,
                    "description": "This record's id in that other system. Matched on BEFORE domain or email, so an integration can sync without remembering our ids."
                  },
                  "createDistinct": {
                    "type": "boolean",
                    "description": "Create a new record even though the evidence matches an existing one. For the case where you know two look alike and really are different. Absent means match, which is the safe answer for a re-run."
                  }
                },
                "required": [
                  "displayName"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": [
                        "created",
                        "matched",
                        "ambiguous"
                      ],
                      "description": "Whether this created a record, matched an existing one on real identity evidence, or found several and committed nothing. `ambiguous` is not an error: it means the evidence you sent fits more than one record, and `candidates` lists them so a caller can choose rather than have one picked for it."
                    },
                    "record": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "displayName": {
                          "type": "string"
                        },
                        "primaryEmail": {
                          "type": "string"
                        },
                        "emailNormalized": {
                          "type": "string"
                        },
                        "phone": {
                          "type": "string"
                        },
                        "phoneNormalized": {
                          "type": "string"
                        },
                        "title": {
                          "type": "string"
                        },
                        "companyName": {
                          "type": "string"
                        },
                        "lifecycle": {
                          "type": "object",
                          "properties": {
                            "category": {
                              "type": "string"
                            },
                            "label": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "category"
                          ],
                          "additionalProperties": true
                        },
                        "ownerActorId": {
                          "type": "string"
                        },
                        "externalProvider": {
                          "type": "string"
                        },
                        "externalId": {
                          "type": "string"
                        },
                        "version": {
                          "type": "integer"
                        },
                        "createdAt": {
                          "type": "string"
                        },
                        "updatedAt": {
                          "type": "string"
                        },
                        "archivedAt": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id",
                        "displayName",
                        "primaryEmail",
                        "emailNormalized",
                        "phone",
                        "phoneNormalized",
                        "title",
                        "lifecycle",
                        "ownerActorId",
                        "externalProvider",
                        "externalId",
                        "version",
                        "createdAt",
                        "updatedAt",
                        "archivedAt"
                      ],
                      "additionalProperties": true,
                      "description": "The record as it stands. Absent on an ambiguous upsert and on a dry run."
                    },
                    "mutation": {
                      "type": "object",
                      "properties": {
                        "mutationId": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "created",
                            "updated",
                            "matched",
                            "archived",
                            "merged",
                            "reverted",
                            "noop"
                          ],
                          "description": "What the write did. `noop` means it was accepted and changed nothing, because every value it carried already matched what was stored. IT IS NOT METERED: a noop does not count against your monthly change allowance, so a nightly sync that finds nothing new costs nothing. Neither does a write that only REDUCES what a workspace holds. `matched` means an upsert found an existing record on real identity evidence rather than creating a second one; `reverted` and `merged` are the undo and duplicate paths, and both are ordinary writes that count."
                        },
                        "targetId": {
                          "type": "string"
                        },
                        "record": {},
                        "changes": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "before": {},
                              "after": {}
                            },
                            "required": [
                              "field"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "held": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "kept": {},
                              "proposed": {},
                              "standing": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "incoming": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "actorId": {
                                "type": "string",
                                "minLength": 1
                              },
                              "assertedAt": {
                                "type": "string",
                                "minLength": 1
                              }
                            },
                            "required": [
                              "field",
                              "standing",
                              "incoming",
                              "actorId",
                              "assertedAt"
                            ],
                            "additionalProperties": false
                          },
                          "description": "Fields this write asked to change and did not, because the value standing in the record was asserted more strongly. THIS IS WHY A WRITE CAN RETURN 200 AND CHANGE NOTHING, and a caller that ignores it will believe it wrote something it did not. Precedence is confirmed > user_supplied > observed > imported > inferred, and a write carrying no `assertionKind` is weakest of all. Each entry reports the field, what the record still says, what you proposed, which claim won, and who made it. Send `overrideStanding` to write anyway, per write, when your claim really does supersede theirs."
                        },
                        "matchedBy": {
                          "type": "string",
                          "enum": [
                            "email",
                            "domain",
                            "external_id",
                            "idempotency_key",
                            "explicit_id"
                          ]
                        },
                        "reversible": {
                          "type": "boolean"
                        },
                        "replayed": {
                          "type": "boolean"
                        },
                        "dryRun": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "mutationId",
                        "status",
                        "reversible"
                      ],
                      "additionalProperties": false,
                      "description": "What the write did. Absent when nothing was written, which is the ambiguous case."
                    },
                    "candidates": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "minLength": 1
                          },
                          "label": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 300
                          },
                          "matchedOn": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 200
                          }
                        },
                        "required": [
                          "id",
                          "label",
                          "matchedOn"
                        ],
                        "additionalProperties": false
                      },
                      "description": "The records the evidence fits, when it fits more than one. Send the upsert again naming the `id` you mean."
                    },
                    "matchReason": {
                      "type": "string",
                      "description": "Why this matched the record it matched, in words, when it matched one."
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "status",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "A product quota is spent, or the subscription is not active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A conflict the caller can resolve: a stale expectedVersion, an idempotency key reused for different input, an ambiguous or duplicate identity, or a merge that no longer applies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The body, or a single record inside it, exceeds its bound.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "507": {
            "description": "The workspace is at its storage ceiling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/contacts/{id}": {
      "get": {
        "summary": "Read one contact",
        "description": "One contact by its id. A person's company affiliation is a separate record, so a contact moving employer keeps their history rather than being duplicated.",
        "tags": [
          "contacts"
        ],
        "operationId": "get_v1_contacts__id_",
        "x-indraft-capability": "crm:read",
        "x-indraft-scopes": [
          "crm:read",
          "crm:write",
          "crm:configure",
          "crm:admin",
          "crm:revert",
          "data:export"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The contact id, as returned by the call that created or matched it.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "contact": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "displayName": {
                          "type": "string"
                        },
                        "primaryEmail": {
                          "type": "string"
                        },
                        "emailNormalized": {
                          "type": "string"
                        },
                        "phone": {
                          "type": "string"
                        },
                        "phoneNormalized": {
                          "type": "string"
                        },
                        "title": {
                          "type": "string"
                        },
                        "companyName": {
                          "type": "string"
                        },
                        "lifecycle": {
                          "type": "object",
                          "properties": {
                            "category": {
                              "type": "string"
                            },
                            "label": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "category"
                          ],
                          "additionalProperties": true
                        },
                        "ownerActorId": {
                          "type": "string"
                        },
                        "externalProvider": {
                          "type": "string"
                        },
                        "externalId": {
                          "type": "string"
                        },
                        "version": {
                          "type": "integer"
                        },
                        "createdAt": {
                          "type": "string"
                        },
                        "updatedAt": {
                          "type": "string"
                        },
                        "archivedAt": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id",
                        "displayName",
                        "primaryEmail",
                        "emailNormalized",
                        "phone",
                        "phoneNormalized",
                        "title",
                        "lifecycle",
                        "ownerActorId",
                        "externalProvider",
                        "externalId",
                        "version",
                        "createdAt",
                        "updatedAt",
                        "archivedAt"
                      ],
                      "additionalProperties": true
                    },
                    "customFields": {
                      "type": "object",
                      "additionalProperties": {}
                    },
                    "tags": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "derived": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string"
                          },
                          "value": {
                            "type": "integer"
                          },
                          "unit": {
                            "type": "string",
                            "enum": [
                              "minor_units",
                              "days"
                            ]
                          },
                          "currency": {
                            "type": "string"
                          },
                          "inputs": {
                            "type": "object",
                            "additionalProperties": {
                              "anyOf": [
                                {
                                  "type": "integer"
                                },
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            }
                          }
                        },
                        "required": [
                          "name",
                          "value",
                          "unit",
                          "currency",
                          "inputs"
                        ],
                        "additionalProperties": true
                      }
                    },
                    "standing": {
                      "type": "object",
                      "additionalProperties": {
                        "type": "object",
                        "properties": {
                          "assertionKind": {
                            "type": "string",
                            "enum": [
                              "observed",
                              "inferred",
                              "imported",
                              "user_supplied",
                              "confirmed"
                            ]
                          },
                          "actorId": {
                            "type": "string"
                          },
                          "assertedAt": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "assertionKind",
                          "actorId",
                          "assertedAt"
                        ],
                        "additionalProperties": true
                      },
                      "description": "Per field: which kind of claim is standing on it, who asserted it, and when. This is the provenance the product is sold on, keyed by column name so it lines up with `changes`, `held[]` and the unconfirmed queue. `confirmed` means a person checked it and outranks everything an agent can assert; `inferred` is the weakest and is what an agent's own conclusion should carry. A write whose claim ranks below what is here is held rather than applied."
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "contact",
                    "customFields",
                    "tags",
                    "derived",
                    "standing",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such record, or it belongs to another workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/contacts/{id}/context": {
      "get": {
        "summary": "Bounded contact context for an agent",
        "description": "One bounded view of a contact: the record, its companies, open opportunities, open tasks, and recent interactions.",
        "tags": [
          "contacts"
        ],
        "operationId": "get_v1_contacts__id__context",
        "x-indraft-capability": "crm:read",
        "x-indraft-scopes": [
          "crm:read",
          "crm:write",
          "crm:configure",
          "crm:admin",
          "crm:revert",
          "data:export"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The contact id, as returned by the call that created or matched it.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "interactions",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "description": "How many recent interactions to include in the brief. Bounded, and the answer says when the bound bit rather than implying it returned everything."
            }
          },
          {
            "name": "openTasks",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "description": "How many open tasks to include in the brief, bounded the same way."
            }
          },
          {
            "name": "openOpportunities",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "description": "How many open deals to include in the brief, bounded the same way."
            }
          },
          {
            "name": "relatedContacts",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "description": "How many of the account's contacts to include in the brief, bounded the same way."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "contact": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "displayName": {
                          "type": "string"
                        },
                        "primaryEmail": {
                          "type": "string"
                        },
                        "emailNormalized": {
                          "type": "string"
                        },
                        "phone": {
                          "type": "string"
                        },
                        "phoneNormalized": {
                          "type": "string"
                        },
                        "title": {
                          "type": "string"
                        },
                        "companyName": {
                          "type": "string"
                        },
                        "lifecycle": {
                          "type": "object",
                          "properties": {
                            "category": {
                              "type": "string"
                            },
                            "label": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "category"
                          ],
                          "additionalProperties": true
                        },
                        "ownerActorId": {
                          "type": "string"
                        },
                        "externalProvider": {
                          "type": "string"
                        },
                        "externalId": {
                          "type": "string"
                        },
                        "version": {
                          "type": "integer"
                        },
                        "createdAt": {
                          "type": "string"
                        },
                        "updatedAt": {
                          "type": "string"
                        },
                        "archivedAt": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id",
                        "displayName",
                        "primaryEmail",
                        "emailNormalized",
                        "phone",
                        "phoneNormalized",
                        "title",
                        "lifecycle",
                        "ownerActorId",
                        "externalProvider",
                        "externalId",
                        "version",
                        "createdAt",
                        "updatedAt",
                        "archivedAt"
                      ],
                      "additionalProperties": true,
                      "description": "The contact record itself, with its custom values and tags."
                    },
                    "companies": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "domain": {
                            "type": "string"
                          },
                          "domainNormalized": {
                            "type": "string"
                          },
                          "website": {
                            "type": "string"
                          },
                          "industry": {
                            "type": "string"
                          },
                          "lifecycle": {
                            "type": "object",
                            "properties": {
                              "category": {
                                "type": "string"
                              },
                              "label": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "category"
                            ],
                            "additionalProperties": true
                          },
                          "ownerActorId": {
                            "type": "string"
                          },
                          "externalProvider": {
                            "type": "string"
                          },
                          "externalId": {
                            "type": "string"
                          },
                          "version": {
                            "type": "integer"
                          },
                          "createdAt": {
                            "type": "string"
                          },
                          "updatedAt": {
                            "type": "string"
                          },
                          "archivedAt": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "name",
                          "domain",
                          "domainNormalized",
                          "website",
                          "industry",
                          "lifecycle",
                          "ownerActorId",
                          "externalProvider",
                          "externalId",
                          "version",
                          "createdAt",
                          "updatedAt",
                          "archivedAt"
                        ],
                        "additionalProperties": true
                      },
                      "description": "Companies this person is attached to. A contact may belong to more than one."
                    },
                    "openOpportunities": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "pipelineId": {
                            "type": "string"
                          },
                          "stageId": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "open",
                              "won",
                              "lost"
                            ]
                          },
                          "amountMinor": {
                            "type": "integer"
                          },
                          "currency": {
                            "type": "string"
                          },
                          "probabilityBps": {
                            "type": "integer"
                          },
                          "expectedCloseDate": {
                            "type": "string"
                          },
                          "companyName": {
                            "type": "string"
                          },
                          "lastActor": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string"
                              },
                              "kind": {
                                "type": "string",
                                "enum": [
                                  "human",
                                  "agent",
                                  "api_token",
                                  "system"
                                ]
                              },
                              "label": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "id",
                              "kind",
                              "label"
                            ],
                            "additionalProperties": true
                          },
                          "ownerActorId": {
                            "type": "string"
                          },
                          "externalProvider": {
                            "type": "string"
                          },
                          "externalId": {
                            "type": "string"
                          },
                          "version": {
                            "type": "integer"
                          },
                          "createdAt": {
                            "type": "string"
                          },
                          "updatedAt": {
                            "type": "string"
                          },
                          "archivedAt": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "name",
                          "pipelineId",
                          "stageId",
                          "status",
                          "amountMinor",
                          "currency",
                          "probabilityBps",
                          "expectedCloseDate",
                          "ownerActorId",
                          "externalProvider",
                          "externalId",
                          "version",
                          "createdAt",
                          "updatedAt",
                          "archivedAt"
                        ],
                        "additionalProperties": true
                      },
                      "description": "Deals still open that this person is on, capped."
                    },
                    "openTasks": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "open",
                              "done",
                              "cancelled"
                            ]
                          },
                          "assigneeActorId": {
                            "type": "string"
                          },
                          "assignee": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string"
                              },
                              "kind": {
                                "type": "string",
                                "enum": [
                                  "human",
                                  "agent",
                                  "api_token",
                                  "system"
                                ]
                              },
                              "label": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "id",
                              "kind",
                              "label"
                            ],
                            "additionalProperties": true
                          },
                          "dueAt": {
                            "type": "string"
                          },
                          "priority": {
                            "type": "string",
                            "enum": [
                              "low",
                              "normal",
                              "high"
                            ]
                          },
                          "completedAt": {
                            "type": "string"
                          },
                          "ownerActorId": {
                            "type": "string"
                          },
                          "version": {
                            "type": "integer"
                          },
                          "links": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "objectType": {
                                  "type": "string",
                                  "enum": [
                                    "company",
                                    "contact",
                                    "opportunity"
                                  ]
                                },
                                "objectId": {
                                  "type": "string"
                                }
                              },
                              "required": [
                                "objectType",
                                "objectId"
                              ],
                              "additionalProperties": true
                            }
                          },
                          "createdAt": {
                            "type": "string"
                          },
                          "updatedAt": {
                            "type": "string"
                          },
                          "archivedAt": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "title",
                          "status",
                          "assigneeActorId",
                          "dueAt",
                          "priority",
                          "completedAt",
                          "ownerActorId",
                          "version",
                          "links",
                          "createdAt",
                          "updatedAt",
                          "archivedAt"
                        ],
                        "additionalProperties": true
                      },
                      "description": "Work still outstanding on this person, capped."
                    },
                    "recentInteractions": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "interactionType": {
                            "type": "string",
                            "enum": [
                              "email",
                              "call",
                              "meeting",
                              "message",
                              "note"
                            ]
                          },
                          "direction": {
                            "type": "string",
                            "enum": [
                              "inbound",
                              "outbound",
                              "internal"
                            ]
                          },
                          "subject": {
                            "type": "string"
                          },
                          "summary": {
                            "type": "string"
                          },
                          "assertionKind": {
                            "type": "string",
                            "enum": [
                              "observed",
                              "inferred",
                              "imported",
                              "user_supplied"
                            ]
                          },
                          "occurredAt": {
                            "type": "string"
                          },
                          "sourceId": {
                            "type": "string"
                          },
                          "createdByActorId": {
                            "type": "string"
                          },
                          "actor": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string"
                              },
                              "kind": {
                                "type": "string",
                                "enum": [
                                  "human",
                                  "agent",
                                  "api_token",
                                  "system"
                                ]
                              },
                              "label": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "id",
                              "kind",
                              "label"
                            ],
                            "additionalProperties": true
                          },
                          "links": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "objectType": {
                                  "type": "string",
                                  "enum": [
                                    "company",
                                    "contact",
                                    "opportunity"
                                  ]
                                },
                                "objectId": {
                                  "type": "string"
                                }
                              },
                              "required": [
                                "objectType",
                                "objectId"
                              ],
                              "additionalProperties": true
                            }
                          },
                          "createdAt": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "interactionType",
                          "direction",
                          "subject",
                          "summary",
                          "assertionKind",
                          "occurredAt",
                          "sourceId",
                          "createdByActorId",
                          "links",
                          "createdAt"
                        ],
                        "additionalProperties": true
                      },
                      "description": "The most recent interactions with this person, newest first, capped. Summaries and metadata only: this product never stores a message body or a transcript."
                    },
                    "standing": {
                      "type": "object",
                      "additionalProperties": {
                        "type": "object",
                        "properties": {
                          "assertionKind": {
                            "type": "string",
                            "enum": [
                              "observed",
                              "inferred",
                              "imported",
                              "user_supplied",
                              "confirmed"
                            ]
                          },
                          "actorId": {
                            "type": "string"
                          },
                          "assertedAt": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "assertionKind",
                          "actorId",
                          "assertedAt"
                        ],
                        "additionalProperties": true
                      },
                      "description": "Per field: which kind of claim is standing on it, who asserted it, and when. This is the provenance the product is sold on, keyed by column name so it lines up with `changes`, `held[]` and the unconfirmed queue. `confirmed` means a person checked it and outranks everything an agent can assert; `inferred` is the weakest and is what an agent's own conclusion should carry. A write whose claim ranks below what is here is held rather than applied."
                    },
                    "limits": {
                      "type": "object",
                      "properties": {
                        "interactions": {
                          "type": "integer"
                        },
                        "openTasks": {
                          "type": "integer"
                        },
                        "openOpportunities": {
                          "type": "integer"
                        },
                        "relatedContacts": {
                          "type": "integer"
                        }
                      },
                      "required": [
                        "interactions",
                        "openTasks",
                        "openOpportunities",
                        "relatedContacts"
                      ],
                      "additionalProperties": true,
                      "description": "The cap applied to each collection above."
                    },
                    "truncated": {
                      "type": "object",
                      "additionalProperties": {
                        "type": "boolean"
                      },
                      "description": "Which collections hit their cap, keyed by name. True means there is more that is not here."
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "contact",
                    "companies",
                    "openOpportunities",
                    "openTasks",
                    "recentInteractions",
                    "standing",
                    "limits",
                    "truncated",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such record, or it belongs to another workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/companies/{id}/archive": {
      "post": {
        "summary": "Archive a company, or restore it",
        "description": "Archive a company or contact, or restore one with restore=true. For a record of a type this workspace defined for itself, use archive_object_record instead. An archived record keeps its history, stays readable, and stops counting toward the workspace's record limit, so this is how a workspace gets back under a limit without deleting anything.",
        "tags": [
          "companies"
        ],
        "operationId": "post_v1_companies__id__archive",
        "x-indraft-capability": "crm:write",
        "x-indraft-scopes": [
          "crm:write",
          "crm:admin"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The company id, as returned by the call that created or matched it.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "idempotencyKey": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 200,
                    "description": "Your own name for this write, so retrying it cannot do it twice. Send the same key again and you get the SAME result back rather than a second record, which is what makes a re-run safe after a timeout you never saw the answer to. Derive it from what the write is about, not from the clock: `nightly-sync-halden` retries correctly and a timestamp does not."
                  },
                  "expectedVersion": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "The version you read before deciding to write. If the record has moved since, the write is refused instead of overwriting whatever changed. Send it whenever you read, reasoned, and then wrote: without it the last writer wins and neither of you finds out."
                  },
                  "sourceId": {
                    "type": "string",
                    "description": "The recorded source this claim came from, if one exists. It attaches evidence to the write, so a person reading the field later can see where it came from rather than only who sent it."
                  },
                  "assertionKind": {
                    "type": "string",
                    "enum": [
                      "observed",
                      "inferred",
                      "imported",
                      "user_supplied"
                    ],
                    "description": "HOW YOU KNOW. This is the field the product is built around, so say what is true rather than what is strongest: `observed` you saw it stated directly, `imported` it came from a file or another system, `inferred` you worked it out, `user_supplied` a person told you in so many words. They rank, weakest first: inferred < imported < observed < user_supplied < confirmed. A weaker claim does not overwrite a stronger one; it is reported in `held[]` and the stored value stands, so an unattended re-run converges instead of eroding what somebody checked. `confirmed` is not accepted here: it means a person checked the value, and only a signed-in person can set it."
                  },
                  "attributionLabel": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120,
                    "description": "A short name for the work this write belongs to, shown beside the actor so one credential can distinguish separate jobs. It is recorded as CALLER-SUPPLIED and grants nothing: it changes no permission, no idempotency scope and no quota."
                  },
                  "dryRun": {
                    "type": "boolean",
                    "description": "Report what this write WOULD do and commit nothing. The response carries the same change list, held fields and refusals as the real call, so it is the way to check a risky write, or a whole import, before it lands. Nothing is metered."
                  },
                  "overrideStanding": {
                    "type": "boolean",
                    "description": "Apply this write even when the value standing in the record was asserted more strongly than this one. Absent means no, which is the safe answer for a re-run. WITHOUT IT, a write can be accepted and change nothing: precedence is confirmed > user_supplied > observed > imported > inferred, and a weaker claim leaves the standing value in place and reports the field in `held[]` rather than failing. That is the whole of why a write can return 200 and not take. WITH it, this write wins regardless of what it is overruling, INCLUDING a value a person confirmed, so an agent that sets it by default has switched the provenance mechanism off. Set it per write, when the caller knows its claim supersedes what is there."
                  },
                  "restore": {
                    "type": "boolean"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "record": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "name": {
                          "type": "string"
                        },
                        "domain": {
                          "type": "string"
                        },
                        "domainNormalized": {
                          "type": "string"
                        },
                        "website": {
                          "type": "string"
                        },
                        "industry": {
                          "type": "string"
                        },
                        "lifecycle": {
                          "type": "object",
                          "properties": {
                            "category": {
                              "type": "string"
                            },
                            "label": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "category"
                          ],
                          "additionalProperties": true
                        },
                        "ownerActorId": {
                          "type": "string"
                        },
                        "externalProvider": {
                          "type": "string"
                        },
                        "externalId": {
                          "type": "string"
                        },
                        "version": {
                          "type": "integer"
                        },
                        "createdAt": {
                          "type": "string"
                        },
                        "updatedAt": {
                          "type": "string"
                        },
                        "archivedAt": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id",
                        "name",
                        "domain",
                        "domainNormalized",
                        "website",
                        "industry",
                        "lifecycle",
                        "ownerActorId",
                        "externalProvider",
                        "externalId",
                        "version",
                        "createdAt",
                        "updatedAt",
                        "archivedAt"
                      ],
                      "additionalProperties": true,
                      "description": "The record as it stands after the write. Absent on a dry run, which commits nothing."
                    },
                    "mutation": {
                      "type": "object",
                      "properties": {
                        "mutationId": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "created",
                            "updated",
                            "matched",
                            "archived",
                            "merged",
                            "reverted",
                            "noop"
                          ],
                          "description": "What the write did. `noop` means it was accepted and changed nothing, because every value it carried already matched what was stored. IT IS NOT METERED: a noop does not count against your monthly change allowance, so a nightly sync that finds nothing new costs nothing. Neither does a write that only REDUCES what a workspace holds. `matched` means an upsert found an existing record on real identity evidence rather than creating a second one; `reverted` and `merged` are the undo and duplicate paths, and both are ordinary writes that count."
                        },
                        "targetId": {
                          "type": "string"
                        },
                        "record": {},
                        "changes": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "before": {},
                              "after": {}
                            },
                            "required": [
                              "field"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "held": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "kept": {},
                              "proposed": {},
                              "standing": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "incoming": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "actorId": {
                                "type": "string",
                                "minLength": 1
                              },
                              "assertedAt": {
                                "type": "string",
                                "minLength": 1
                              }
                            },
                            "required": [
                              "field",
                              "standing",
                              "incoming",
                              "actorId",
                              "assertedAt"
                            ],
                            "additionalProperties": false
                          },
                          "description": "Fields this write asked to change and did not, because the value standing in the record was asserted more strongly. THIS IS WHY A WRITE CAN RETURN 200 AND CHANGE NOTHING, and a caller that ignores it will believe it wrote something it did not. Precedence is confirmed > user_supplied > observed > imported > inferred, and a write carrying no `assertionKind` is weakest of all. Each entry reports the field, what the record still says, what you proposed, which claim won, and who made it. Send `overrideStanding` to write anyway, per write, when your claim really does supersede theirs."
                        },
                        "matchedBy": {
                          "type": "string",
                          "enum": [
                            "email",
                            "domain",
                            "external_id",
                            "idempotency_key",
                            "explicit_id"
                          ]
                        },
                        "reversible": {
                          "type": "boolean"
                        },
                        "replayed": {
                          "type": "boolean"
                        },
                        "dryRun": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "mutationId",
                        "status",
                        "reversible"
                      ],
                      "additionalProperties": false,
                      "description": "What the write actually DID. Read `status` before you conclude anything: `noop` means it was accepted and changed nothing. `changes` is the field-level diff that was recorded, and `held` names any field whose stored value outranked the claim you sent and therefore did not move. A 200 with an empty `changes` and a populated `held` is the product working, not the call failing."
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "mutation",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "A product quota is spent, or the subscription is not active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such record, or it belongs to another workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A conflict the caller can resolve: a stale expectedVersion, an idempotency key reused for different input, an ambiguous or duplicate identity, or a merge that no longer applies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The body, or a single record inside it, exceeds its bound.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "507": {
            "description": "The workspace is at its storage ceiling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/contacts:merge": {
      "post": {
        "summary": "Merge a duplicate contact into a target",
        "description": "Merge a duplicate contact into a target. References move to the target and the source is archived. Not undoable by revert_change; use unmerge.",
        "tags": [
          "contacts"
        ],
        "operationId": "post_v1_contacts_merge",
        "x-indraft-capability": "crm:write",
        "x-indraft-scopes": [
          "crm:write",
          "crm:admin"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "idempotencyKey": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 200,
                    "description": "Your own name for this write, so retrying it cannot do it twice. Send the same key again and you get the SAME result back rather than a second record, which is what makes a re-run safe after a timeout you never saw the answer to. Derive it from what the write is about, not from the clock: `nightly-sync-halden` retries correctly and a timestamp does not."
                  },
                  "expectedVersion": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "The version you read before deciding to write. If the record has moved since, the write is refused instead of overwriting whatever changed. Send it whenever you read, reasoned, and then wrote: without it the last writer wins and neither of you finds out."
                  },
                  "sourceId": {
                    "type": "string",
                    "minLength": 1
                  },
                  "assertionKind": {
                    "type": "string",
                    "enum": [
                      "observed",
                      "inferred",
                      "imported",
                      "user_supplied"
                    ],
                    "description": "HOW YOU KNOW. This is the field the product is built around, so say what is true rather than what is strongest: `observed` you saw it stated directly, `imported` it came from a file or another system, `inferred` you worked it out, `user_supplied` a person told you in so many words. They rank, weakest first: inferred < imported < observed < user_supplied < confirmed. A weaker claim does not overwrite a stronger one; it is reported in `held[]` and the stored value stands, so an unattended re-run converges instead of eroding what somebody checked. `confirmed` is not accepted here: it means a person checked the value, and only a signed-in person can set it."
                  },
                  "attributionLabel": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120,
                    "description": "A short name for the work this write belongs to, shown beside the actor so one credential can distinguish separate jobs. It is recorded as CALLER-SUPPLIED and grants nothing: it changes no permission, no idempotency scope and no quota."
                  },
                  "dryRun": {
                    "type": "boolean",
                    "description": "Report what this write WOULD do and commit nothing. The response carries the same change list, held fields and refusals as the real call, so it is the way to check a risky write, or a whole import, before it lands. Nothing is metered."
                  },
                  "overrideStanding": {
                    "type": "boolean",
                    "description": "Apply this write even when the value standing in the record was asserted more strongly than this one. Absent means no, which is the safe answer for a re-run. WITHOUT IT, a write can be accepted and change nothing: precedence is confirmed > user_supplied > observed > imported > inferred, and a weaker claim leaves the standing value in place and reports the field in `held[]` rather than failing. That is the whole of why a write can return 200 and not take. WITH it, this write wins regardless of what it is overruling, INCLUDING a value a person confirmed, so an agent that sets it by default has switched the provenance mechanism off. Set it per write, when the caller knows its claim supersedes what is there."
                  },
                  "targetId": {
                    "type": "string",
                    "minLength": 1
                  }
                },
                "required": [
                  "sourceId",
                  "targetId"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "record": {
                      "type": "object",
                      "properties": {
                        "mergeId": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "mergeId"
                      ],
                      "additionalProperties": true
                    },
                    "mutation": {
                      "type": "object",
                      "properties": {
                        "mutationId": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "created",
                            "updated",
                            "matched",
                            "archived",
                            "merged",
                            "reverted",
                            "noop"
                          ],
                          "description": "What the write did. `noop` means it was accepted and changed nothing, because every value it carried already matched what was stored. IT IS NOT METERED: a noop does not count against your monthly change allowance, so a nightly sync that finds nothing new costs nothing. Neither does a write that only REDUCES what a workspace holds. `matched` means an upsert found an existing record on real identity evidence rather than creating a second one; `reverted` and `merged` are the undo and duplicate paths, and both are ordinary writes that count."
                        },
                        "targetId": {
                          "type": "string"
                        },
                        "record": {},
                        "changes": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "before": {},
                              "after": {}
                            },
                            "required": [
                              "field"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "held": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "kept": {},
                              "proposed": {},
                              "standing": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "incoming": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "actorId": {
                                "type": "string",
                                "minLength": 1
                              },
                              "assertedAt": {
                                "type": "string",
                                "minLength": 1
                              }
                            },
                            "required": [
                              "field",
                              "standing",
                              "incoming",
                              "actorId",
                              "assertedAt"
                            ],
                            "additionalProperties": false
                          },
                          "description": "Fields this write asked to change and did not, because the value standing in the record was asserted more strongly. THIS IS WHY A WRITE CAN RETURN 200 AND CHANGE NOTHING, and a caller that ignores it will believe it wrote something it did not. Precedence is confirmed > user_supplied > observed > imported > inferred, and a write carrying no `assertionKind` is weakest of all. Each entry reports the field, what the record still says, what you proposed, which claim won, and who made it. Send `overrideStanding` to write anyway, per write, when your claim really does supersede theirs."
                        },
                        "matchedBy": {
                          "type": "string",
                          "enum": [
                            "email",
                            "domain",
                            "external_id",
                            "idempotency_key",
                            "explicit_id"
                          ]
                        },
                        "reversible": {
                          "type": "boolean"
                        },
                        "replayed": {
                          "type": "boolean"
                        },
                        "dryRun": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "mutationId",
                        "status",
                        "reversible"
                      ],
                      "additionalProperties": false
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "mutation",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "A product quota is spent, or the subscription is not active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A conflict the caller can resolve: a stale expectedVersion, an idempotency key reused for different input, an ambiguous or duplicate identity, or a merge that no longer applies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The body, or a single record inside it, exceeds its bound.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "507": {
            "description": "The workspace is at its storage ceiling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/contacts/{id}/archive": {
      "post": {
        "summary": "Archive a contact, or restore it",
        "description": "Archived means gone from every list and every count while staying fully readable, and restorable. It is the honest ending for somebody who left, where erasure is for somebody exercising a right.",
        "tags": [
          "contacts"
        ],
        "operationId": "post_v1_contacts__id__archive",
        "x-indraft-capability": "crm:write",
        "x-indraft-scopes": [
          "crm:write",
          "crm:admin"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The contact id, as returned by the call that created or matched it.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "idempotencyKey": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 200,
                    "description": "Your own name for this write, so retrying it cannot do it twice. Send the same key again and you get the SAME result back rather than a second record, which is what makes a re-run safe after a timeout you never saw the answer to. Derive it from what the write is about, not from the clock: `nightly-sync-halden` retries correctly and a timestamp does not."
                  },
                  "expectedVersion": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "The version you read before deciding to write. If the record has moved since, the write is refused instead of overwriting whatever changed. Send it whenever you read, reasoned, and then wrote: without it the last writer wins and neither of you finds out."
                  },
                  "sourceId": {
                    "type": "string",
                    "description": "The recorded source this claim came from, if one exists. It attaches evidence to the write, so a person reading the field later can see where it came from rather than only who sent it."
                  },
                  "assertionKind": {
                    "type": "string",
                    "enum": [
                      "observed",
                      "inferred",
                      "imported",
                      "user_supplied"
                    ],
                    "description": "HOW YOU KNOW. This is the field the product is built around, so say what is true rather than what is strongest: `observed` you saw it stated directly, `imported` it came from a file or another system, `inferred` you worked it out, `user_supplied` a person told you in so many words. They rank, weakest first: inferred < imported < observed < user_supplied < confirmed. A weaker claim does not overwrite a stronger one; it is reported in `held[]` and the stored value stands, so an unattended re-run converges instead of eroding what somebody checked. `confirmed` is not accepted here: it means a person checked the value, and only a signed-in person can set it."
                  },
                  "attributionLabel": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120,
                    "description": "A short name for the work this write belongs to, shown beside the actor so one credential can distinguish separate jobs. It is recorded as CALLER-SUPPLIED and grants nothing: it changes no permission, no idempotency scope and no quota."
                  },
                  "dryRun": {
                    "type": "boolean",
                    "description": "Report what this write WOULD do and commit nothing. The response carries the same change list, held fields and refusals as the real call, so it is the way to check a risky write, or a whole import, before it lands. Nothing is metered."
                  },
                  "overrideStanding": {
                    "type": "boolean",
                    "description": "Apply this write even when the value standing in the record was asserted more strongly than this one. Absent means no, which is the safe answer for a re-run. WITHOUT IT, a write can be accepted and change nothing: precedence is confirmed > user_supplied > observed > imported > inferred, and a weaker claim leaves the standing value in place and reports the field in `held[]` rather than failing. That is the whole of why a write can return 200 and not take. WITH it, this write wins regardless of what it is overruling, INCLUDING a value a person confirmed, so an agent that sets it by default has switched the provenance mechanism off. Set it per write, when the caller knows its claim supersedes what is there."
                  },
                  "restore": {
                    "type": "boolean"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "record": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "displayName": {
                          "type": "string"
                        },
                        "primaryEmail": {
                          "type": "string"
                        },
                        "emailNormalized": {
                          "type": "string"
                        },
                        "phone": {
                          "type": "string"
                        },
                        "phoneNormalized": {
                          "type": "string"
                        },
                        "title": {
                          "type": "string"
                        },
                        "companyName": {
                          "type": "string"
                        },
                        "lifecycle": {
                          "type": "object",
                          "properties": {
                            "category": {
                              "type": "string"
                            },
                            "label": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "category"
                          ],
                          "additionalProperties": true
                        },
                        "ownerActorId": {
                          "type": "string"
                        },
                        "externalProvider": {
                          "type": "string"
                        },
                        "externalId": {
                          "type": "string"
                        },
                        "version": {
                          "type": "integer"
                        },
                        "createdAt": {
                          "type": "string"
                        },
                        "updatedAt": {
                          "type": "string"
                        },
                        "archivedAt": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id",
                        "displayName",
                        "primaryEmail",
                        "emailNormalized",
                        "phone",
                        "phoneNormalized",
                        "title",
                        "lifecycle",
                        "ownerActorId",
                        "externalProvider",
                        "externalId",
                        "version",
                        "createdAt",
                        "updatedAt",
                        "archivedAt"
                      ],
                      "additionalProperties": true,
                      "description": "The record as it stands after the write. Absent on a dry run, which commits nothing."
                    },
                    "mutation": {
                      "type": "object",
                      "properties": {
                        "mutationId": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "created",
                            "updated",
                            "matched",
                            "archived",
                            "merged",
                            "reverted",
                            "noop"
                          ],
                          "description": "What the write did. `noop` means it was accepted and changed nothing, because every value it carried already matched what was stored. IT IS NOT METERED: a noop does not count against your monthly change allowance, so a nightly sync that finds nothing new costs nothing. Neither does a write that only REDUCES what a workspace holds. `matched` means an upsert found an existing record on real identity evidence rather than creating a second one; `reverted` and `merged` are the undo and duplicate paths, and both are ordinary writes that count."
                        },
                        "targetId": {
                          "type": "string"
                        },
                        "record": {},
                        "changes": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "before": {},
                              "after": {}
                            },
                            "required": [
                              "field"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "held": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "kept": {},
                              "proposed": {},
                              "standing": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "incoming": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "actorId": {
                                "type": "string",
                                "minLength": 1
                              },
                              "assertedAt": {
                                "type": "string",
                                "minLength": 1
                              }
                            },
                            "required": [
                              "field",
                              "standing",
                              "incoming",
                              "actorId",
                              "assertedAt"
                            ],
                            "additionalProperties": false
                          },
                          "description": "Fields this write asked to change and did not, because the value standing in the record was asserted more strongly. THIS IS WHY A WRITE CAN RETURN 200 AND CHANGE NOTHING, and a caller that ignores it will believe it wrote something it did not. Precedence is confirmed > user_supplied > observed > imported > inferred, and a write carrying no `assertionKind` is weakest of all. Each entry reports the field, what the record still says, what you proposed, which claim won, and who made it. Send `overrideStanding` to write anyway, per write, when your claim really does supersede theirs."
                        },
                        "matchedBy": {
                          "type": "string",
                          "enum": [
                            "email",
                            "domain",
                            "external_id",
                            "idempotency_key",
                            "explicit_id"
                          ]
                        },
                        "reversible": {
                          "type": "boolean"
                        },
                        "replayed": {
                          "type": "boolean"
                        },
                        "dryRun": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "mutationId",
                        "status",
                        "reversible"
                      ],
                      "additionalProperties": false,
                      "description": "What the write actually DID. Read `status` before you conclude anything: `noop` means it was accepted and changed nothing. `changes` is the field-level diff that was recorded, and `held` names any field whose stored value outranked the claim you sent and therefore did not move. A 200 with an empty `changes` and a populated `held` is the product working, not the call failing."
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "mutation",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "A product quota is spent, or the subscription is not active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such record, or it belongs to another workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A conflict the caller can resolve: a stale expectedVersion, an idempotency key reused for different input, an ambiguous or duplicate identity, or a merge that no longer applies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The body, or a single record inside it, exceeds its bound.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "507": {
            "description": "The workspace is at its storage ceiling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/contacts/{id}/erasure": {
      "post": {
        "summary": "Erase this person: destroy every value that identifies them, keep the ledger's shape, and return a receipt. Cannot be undone",
        "description": "Destroys every value that identifies the person and keeps the ledger's shape, so the history still says a change happened and no longer says who it was about. The receipt is what you show a regulator. Nothing undoes it, including us.",
        "tags": [
          "contacts"
        ],
        "operationId": "post_v1_contacts__id__erasure",
        "x-indraft-capability": "crm:erase",
        "x-indraft-scopes": [],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The contact id, as returned by the call that created or matched it.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "idempotencyKey": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 200,
                    "description": "Your own name for this write, so retrying it cannot do it twice. Send the same key again and you get the SAME result back rather than a second record, which is what makes a re-run safe after a timeout you never saw the answer to. Derive it from what the write is about, not from the clock: `nightly-sync-halden` retries correctly and a timestamp does not."
                  },
                  "expectedVersion": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "The version you read before deciding to write. If the record has moved since, the write is refused instead of overwriting whatever changed. Send it whenever you read, reasoned, and then wrote: without it the last writer wins and neither of you finds out."
                  },
                  "sourceId": {
                    "type": "string",
                    "description": "The recorded source this claim came from, if one exists. It attaches evidence to the write, so a person reading the field later can see where it came from rather than only who sent it."
                  },
                  "assertionKind": {
                    "type": "string",
                    "enum": [
                      "observed",
                      "inferred",
                      "imported",
                      "user_supplied"
                    ],
                    "description": "HOW YOU KNOW. This is the field the product is built around, so say what is true rather than what is strongest: `observed` you saw it stated directly, `imported` it came from a file or another system, `inferred` you worked it out, `user_supplied` a person told you in so many words. They rank, weakest first: inferred < imported < observed < user_supplied < confirmed. A weaker claim does not overwrite a stronger one; it is reported in `held[]` and the stored value stands, so an unattended re-run converges instead of eroding what somebody checked. `confirmed` is not accepted here: it means a person checked the value, and only a signed-in person can set it."
                  },
                  "attributionLabel": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120,
                    "description": "A short name for the work this write belongs to, shown beside the actor so one credential can distinguish separate jobs. It is recorded as CALLER-SUPPLIED and grants nothing: it changes no permission, no idempotency scope and no quota."
                  },
                  "dryRun": {
                    "type": "boolean",
                    "description": "Report what this write WOULD do and commit nothing. The response carries the same change list, held fields and refusals as the real call, so it is the way to check a risky write, or a whole import, before it lands. Nothing is metered."
                  },
                  "overrideStanding": {
                    "type": "boolean",
                    "description": "Apply this write even when the value standing in the record was asserted more strongly than this one. Absent means no, which is the safe answer for a re-run. WITHOUT IT, a write can be accepted and change nothing: precedence is confirmed > user_supplied > observed > imported > inferred, and a weaker claim leaves the standing value in place and reports the field in `held[]` rather than failing. That is the whole of why a write can return 200 and not take. WITH it, this write wins regardless of what it is overruling, INCLUDING a value a person confirmed, so an agent that sets it by default has switched the provenance mechanism off. Set it per write, when the caller knows its claim supersedes what is there."
                  },
                  "confirmation": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "declaredCompanyId": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 64
                  }
                },
                "required": [
                  "confirmation"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "receipt": {
                      "type": "object",
                      "properties": {
                        "subjectId": {
                          "type": "string",
                          "minLength": 1
                        },
                        "declaredCompanyId": {
                          "type": "string",
                          "minLength": 1
                        },
                        "erasedAt": {
                          "type": "string",
                          "minLength": 1
                        },
                        "actorId": {
                          "type": "string",
                          "minLength": 1
                        },
                        "accessPath": {
                          "type": "string",
                          "enum": [
                            "rest",
                            "mcp",
                            "web",
                            "system"
                          ]
                        },
                        "mutationId": {
                          "type": "string",
                          "minLength": 1
                        },
                        "counts": {
                          "type": "object",
                          "properties": {
                            "recordColumns": {
                              "type": "integer",
                              "minimum": 0
                            },
                            "customFieldValues": {
                              "type": "integer",
                              "minimum": 0
                            },
                            "ledgerValues": {
                              "type": "integer",
                              "minimum": 0
                            },
                            "standingRows": {
                              "type": "integer",
                              "minimum": 0
                            },
                            "interactionTexts": {
                              "type": "integer",
                              "minimum": 0
                            },
                            "taskTitles": {
                              "type": "integer",
                              "minimum": 0
                            },
                            "evidenceSnippets": {
                              "type": "integer",
                              "minimum": 0
                            },
                            "mutationRequests": {
                              "type": "integer",
                              "minimum": 0
                            },
                            "webhookPayloads": {
                              "type": "integer",
                              "minimum": 0
                            },
                            "indexEntries": {
                              "type": "integer",
                              "minimum": 0
                            }
                          },
                          "required": [
                            "recordColumns",
                            "customFieldValues",
                            "ledgerValues",
                            "standingRows",
                            "interactionTexts",
                            "taskTitles",
                            "evidenceSnippets",
                            "mutationRequests",
                            "webhookPayloads",
                            "indexEntries"
                          ],
                          "additionalProperties": false
                        },
                        "affected": {
                          "type": "object",
                          "properties": {
                            "shared": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "objectType": {
                                    "type": "string",
                                    "minLength": 1
                                  },
                                  "id": {
                                    "type": "string",
                                    "minLength": 1
                                  }
                                },
                                "required": [
                                  "objectType",
                                  "id"
                                ],
                                "additionalProperties": false
                              }
                            },
                            "mentions": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "objectType": {
                                    "type": "string",
                                    "minLength": 1
                                  },
                                  "id": {
                                    "type": "string",
                                    "minLength": 1
                                  }
                                },
                                "required": [
                                  "objectType",
                                  "id"
                                ],
                                "additionalProperties": false
                              }
                            },
                            "sharedCount": {
                              "type": "integer",
                              "minimum": 0
                            },
                            "mentionCount": {
                              "type": "integer",
                              "minimum": 0
                            },
                            "truncated": {
                              "type": "boolean"
                            }
                          },
                          "required": [
                            "shared",
                            "mentions",
                            "sharedCount",
                            "mentionCount",
                            "truncated"
                          ],
                          "additionalProperties": false
                        },
                        "deliveredTo": {
                          "type": "array",
                          "items": {
                            "type": "string",
                            "minLength": 1
                          }
                        },
                        "limitations": {
                          "type": "array",
                          "items": {
                            "type": "string",
                            "minLength": 1
                          }
                        }
                      },
                      "required": [
                        "subjectId",
                        "declaredCompanyId",
                        "erasedAt",
                        "actorId",
                        "accessPath",
                        "mutationId",
                        "counts",
                        "affected",
                        "deliveredTo",
                        "limitations"
                      ],
                      "additionalProperties": false
                    },
                    "mutation": {
                      "type": "object",
                      "properties": {
                        "mutationId": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "created",
                            "updated",
                            "matched",
                            "archived",
                            "merged",
                            "reverted",
                            "noop"
                          ],
                          "description": "What the write did. `noop` means it was accepted and changed nothing, because every value it carried already matched what was stored. IT IS NOT METERED: a noop does not count against your monthly change allowance, so a nightly sync that finds nothing new costs nothing. Neither does a write that only REDUCES what a workspace holds. `matched` means an upsert found an existing record on real identity evidence rather than creating a second one; `reverted` and `merged` are the undo and duplicate paths, and both are ordinary writes that count."
                        },
                        "targetId": {
                          "type": "string"
                        },
                        "record": {},
                        "changes": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "before": {},
                              "after": {}
                            },
                            "required": [
                              "field"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "held": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "kept": {},
                              "proposed": {},
                              "standing": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "incoming": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "actorId": {
                                "type": "string",
                                "minLength": 1
                              },
                              "assertedAt": {
                                "type": "string",
                                "minLength": 1
                              }
                            },
                            "required": [
                              "field",
                              "standing",
                              "incoming",
                              "actorId",
                              "assertedAt"
                            ],
                            "additionalProperties": false
                          },
                          "description": "Fields this write asked to change and did not, because the value standing in the record was asserted more strongly. THIS IS WHY A WRITE CAN RETURN 200 AND CHANGE NOTHING, and a caller that ignores it will believe it wrote something it did not. Precedence is confirmed > user_supplied > observed > imported > inferred, and a write carrying no `assertionKind` is weakest of all. Each entry reports the field, what the record still says, what you proposed, which claim won, and who made it. Send `overrideStanding` to write anyway, per write, when your claim really does supersede theirs."
                        },
                        "matchedBy": {
                          "type": "string",
                          "enum": [
                            "email",
                            "domain",
                            "external_id",
                            "idempotency_key",
                            "explicit_id"
                          ]
                        },
                        "reversible": {
                          "type": "boolean"
                        },
                        "replayed": {
                          "type": "boolean"
                        },
                        "dryRun": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "mutationId",
                        "status",
                        "reversible"
                      ],
                      "additionalProperties": false
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "receipt",
                    "mutation",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "A product quota is spent, or the subscription is not active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such record, or it belongs to another workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A conflict the caller can resolve: a stale expectedVersion, an idempotency key reused for different input, an ambiguous or duplicate identity, or a merge that no longer applies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The body, or a single record inside it, exceeds its bound.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "507": {
            "description": "The workspace is at its storage ceiling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/merges/{id}/unmerge": {
      "post": {
        "summary": "Invert a merge, restoring exactly the references it moved",
        "description": "Invert a merge, restoring exactly the references it moved. Refused if the merge has already been undone.",
        "tags": [
          "merges"
        ],
        "operationId": "post_v1_merges__id__unmerge",
        "x-indraft-capability": "crm:write",
        "x-indraft-scopes": [
          "crm:write",
          "crm:admin"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The merge id, as returned by the call that created or matched it.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "idempotencyKey": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 200,
                    "description": "Your own name for this write, so retrying it cannot do it twice. Send the same key again and you get the SAME result back rather than a second record, which is what makes a re-run safe after a timeout you never saw the answer to. Derive it from what the write is about, not from the clock: `nightly-sync-halden` retries correctly and a timestamp does not."
                  },
                  "expectedVersion": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "The version you read before deciding to write. If the record has moved since, the write is refused instead of overwriting whatever changed. Send it whenever you read, reasoned, and then wrote: without it the last writer wins and neither of you finds out."
                  },
                  "sourceId": {
                    "type": "string",
                    "description": "The recorded source this claim came from, if one exists. It attaches evidence to the write, so a person reading the field later can see where it came from rather than only who sent it."
                  },
                  "assertionKind": {
                    "type": "string",
                    "enum": [
                      "observed",
                      "inferred",
                      "imported",
                      "user_supplied"
                    ],
                    "description": "HOW YOU KNOW. This is the field the product is built around, so say what is true rather than what is strongest: `observed` you saw it stated directly, `imported` it came from a file or another system, `inferred` you worked it out, `user_supplied` a person told you in so many words. They rank, weakest first: inferred < imported < observed < user_supplied < confirmed. A weaker claim does not overwrite a stronger one; it is reported in `held[]` and the stored value stands, so an unattended re-run converges instead of eroding what somebody checked. `confirmed` is not accepted here: it means a person checked the value, and only a signed-in person can set it."
                  },
                  "attributionLabel": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120,
                    "description": "A short name for the work this write belongs to, shown beside the actor so one credential can distinguish separate jobs. It is recorded as CALLER-SUPPLIED and grants nothing: it changes no permission, no idempotency scope and no quota."
                  },
                  "dryRun": {
                    "type": "boolean",
                    "description": "Report what this write WOULD do and commit nothing. The response carries the same change list, held fields and refusals as the real call, so it is the way to check a risky write, or a whole import, before it lands. Nothing is metered."
                  },
                  "overrideStanding": {
                    "type": "boolean",
                    "description": "Apply this write even when the value standing in the record was asserted more strongly than this one. Absent means no, which is the safe answer for a re-run. WITHOUT IT, a write can be accepted and change nothing: precedence is confirmed > user_supplied > observed > imported > inferred, and a weaker claim leaves the standing value in place and reports the field in `held[]` rather than failing. That is the whole of why a write can return 200 and not take. WITH it, this write wins regardless of what it is overruling, INCLUDING a value a person confirmed, so an agent that sets it by default has switched the provenance mechanism off. Set it per write, when the caller knows its claim supersedes what is there."
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "record": {
                      "type": "object",
                      "properties": {
                        "mergeId": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "mergeId"
                      ],
                      "additionalProperties": true
                    },
                    "mutation": {
                      "type": "object",
                      "properties": {
                        "mutationId": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "created",
                            "updated",
                            "matched",
                            "archived",
                            "merged",
                            "reverted",
                            "noop"
                          ],
                          "description": "What the write did. `noop` means it was accepted and changed nothing, because every value it carried already matched what was stored. IT IS NOT METERED: a noop does not count against your monthly change allowance, so a nightly sync that finds nothing new costs nothing. Neither does a write that only REDUCES what a workspace holds. `matched` means an upsert found an existing record on real identity evidence rather than creating a second one; `reverted` and `merged` are the undo and duplicate paths, and both are ordinary writes that count."
                        },
                        "targetId": {
                          "type": "string"
                        },
                        "record": {},
                        "changes": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "before": {},
                              "after": {}
                            },
                            "required": [
                              "field"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "held": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "kept": {},
                              "proposed": {},
                              "standing": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "incoming": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "actorId": {
                                "type": "string",
                                "minLength": 1
                              },
                              "assertedAt": {
                                "type": "string",
                                "minLength": 1
                              }
                            },
                            "required": [
                              "field",
                              "standing",
                              "incoming",
                              "actorId",
                              "assertedAt"
                            ],
                            "additionalProperties": false
                          },
                          "description": "Fields this write asked to change and did not, because the value standing in the record was asserted more strongly. THIS IS WHY A WRITE CAN RETURN 200 AND CHANGE NOTHING, and a caller that ignores it will believe it wrote something it did not. Precedence is confirmed > user_supplied > observed > imported > inferred, and a write carrying no `assertionKind` is weakest of all. Each entry reports the field, what the record still says, what you proposed, which claim won, and who made it. Send `overrideStanding` to write anyway, per write, when your claim really does supersede theirs."
                        },
                        "matchedBy": {
                          "type": "string",
                          "enum": [
                            "email",
                            "domain",
                            "external_id",
                            "idempotency_key",
                            "explicit_id"
                          ]
                        },
                        "reversible": {
                          "type": "boolean"
                        },
                        "replayed": {
                          "type": "boolean"
                        },
                        "dryRun": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "mutationId",
                        "status",
                        "reversible"
                      ],
                      "additionalProperties": false
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "mutation",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "A product quota is spent, or the subscription is not active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such record, or it belongs to another workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A conflict the caller can resolve: a stale expectedVersion, an idempotency key reused for different input, an ambiguous or duplicate identity, or a merge that no longer applies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The body, or a single record inside it, exceeds its bound.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "507": {
            "description": "The workspace is at its storage ceiling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/opportunities": {
      "get": {
        "summary": "List opportunities",
        "description": "List opportunities by stage or status, newest first, with a cursor for the next page. Narrow with filter, for example filter: ['owner_actor_id:eq:act_...', 'expected_close_date:isNotNull'] and sort: '-expected_close_date'; get_crm_schema lists the fields each type accepts.",
        "tags": [
          "opportunities"
        ],
        "operationId": "get_v1_opportunities",
        "x-indraft-capability": "crm:read",
        "x-indraft-scopes": [
          "crm:read",
          "crm:write",
          "crm:configure",
          "crm:admin",
          "crm:revert",
          "data:export"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "description": "How many to return. The page bound is published in the schema call, and asking for more is refused rather than quietly truncated."
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "The opaque marker from the previous page. Store it and hand it back; do not parse it. A cursor is only ever emitted when another row really exists, so a page you were given is never empty."
            }
          },
          {
            "name": "updatedSince",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 40,
              "description": "Only rows changed after this instant. The incremental read: without it a service syncing a large workspace has to walk all of it every time."
            }
          },
          {
            "name": "lastInteractionBefore",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 40,
              "description": "Only records whose most recent interaction is older than this, including those with none at all."
            }
          },
          {
            "name": "stageId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "Only records in this stage. Stage ids come from the schema call, which lists every pipeline and its stages in order."
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "open",
                "won",
                "lost"
              ],
              "description": "Only records with this status. Status is derived from the stage's kind rather than set separately, so a deal cannot be open and won at once."
            }
          },
          {
            "name": "filter",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 560
                },
                {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 560
                  },
                  "maxItems": 8
                }
              ],
              "description": "Predicates, all of which must hold, written field:op:value. Only fields an index serves are accepted, and asking for one that is not names the ones that are."
            }
          },
          {
            "name": "or",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 560
                },
                {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 560
                  },
                  "maxItems": 4
                }
              ],
              "description": "Alternatives, ORed with each other and ANDed with filter. One level and never a tree: owned by me or owned by nobody is the question people ask, and anything deeper has a cost the caller cannot read off it."
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 65,
              "description": "A field to order by, with a leading minus for descending. Indexed fields only, for the same reason as filter."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "pipelineId": {
                            "type": "string"
                          },
                          "stageId": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "open",
                              "won",
                              "lost"
                            ]
                          },
                          "amountMinor": {
                            "type": "integer"
                          },
                          "currency": {
                            "type": "string"
                          },
                          "probabilityBps": {
                            "type": "integer"
                          },
                          "expectedCloseDate": {
                            "type": "string"
                          },
                          "companyName": {
                            "type": "string"
                          },
                          "lastActor": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string"
                              },
                              "kind": {
                                "type": "string",
                                "enum": [
                                  "human",
                                  "agent",
                                  "api_token",
                                  "system"
                                ]
                              },
                              "label": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "id",
                              "kind",
                              "label"
                            ],
                            "additionalProperties": true
                          },
                          "ownerActorId": {
                            "type": "string"
                          },
                          "externalProvider": {
                            "type": "string"
                          },
                          "externalId": {
                            "type": "string"
                          },
                          "version": {
                            "type": "integer"
                          },
                          "createdAt": {
                            "type": "string"
                          },
                          "updatedAt": {
                            "type": "string"
                          },
                          "archivedAt": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "name",
                          "pipelineId",
                          "stageId",
                          "status",
                          "amountMinor",
                          "currency",
                          "probabilityBps",
                          "expectedCloseDate",
                          "ownerActorId",
                          "externalProvider",
                          "externalId",
                          "version",
                          "createdAt",
                          "updatedAt",
                          "archivedAt"
                        ],
                        "additionalProperties": true
                      },
                      "description": "This page of results, in the order you asked for."
                    },
                    "nextCursor": {
                      "type": "string",
                      "description": "Hand this back to get the next page, or null when there is no next page. Null is the end of the list and an empty `items` is not: a cursor is only emitted when another row really exists."
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "items",
                    "nextCursor",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Create an opportunity",
        "description": "Create an opportunity, always as a new one. If another system already knows this deal and you are syncing it, use upsert_opportunity, which matches on that system's identity instead of creating a second copy. Omit stageId to use the first open stage of the default pipeline. Amount is an integer in minor units and requires a currency. Set ownerActorId and expectedCloseDate here rather than in a second call: both are filterable and sortable, and recording one fact as two assertions makes the history harder to read than the API.",
        "tags": [
          "opportunities"
        ],
        "operationId": "post_v1_opportunities",
        "x-indraft-capability": "crm:write",
        "x-indraft-scopes": [
          "crm:write",
          "crm:admin"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "idempotencyKey": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 200,
                    "description": "Your own name for this write, so retrying it cannot do it twice. Send the same key again and you get the SAME result back rather than a second record, which is what makes a re-run safe after a timeout you never saw the answer to. Derive it from what the write is about, not from the clock: `nightly-sync-halden` retries correctly and a timestamp does not."
                  },
                  "expectedVersion": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "The version you read before deciding to write. If the record has moved since, the write is refused instead of overwriting whatever changed. Send it whenever you read, reasoned, and then wrote: without it the last writer wins and neither of you finds out."
                  },
                  "sourceId": {
                    "type": "string",
                    "description": "The recorded source this claim came from, if one exists. It attaches evidence to the write, so a person reading the field later can see where it came from rather than only who sent it."
                  },
                  "assertionKind": {
                    "type": "string",
                    "enum": [
                      "observed",
                      "inferred",
                      "imported",
                      "user_supplied"
                    ],
                    "description": "HOW YOU KNOW. This is the field the product is built around, so say what is true rather than what is strongest: `observed` you saw it stated directly, `imported` it came from a file or another system, `inferred` you worked it out, `user_supplied` a person told you in so many words. They rank, weakest first: inferred < imported < observed < user_supplied < confirmed. A weaker claim does not overwrite a stronger one; it is reported in `held[]` and the stored value stands, so an unattended re-run converges instead of eroding what somebody checked. `confirmed` is not accepted here: it means a person checked the value, and only a signed-in person can set it."
                  },
                  "attributionLabel": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120,
                    "description": "A short name for the work this write belongs to, shown beside the actor so one credential can distinguish separate jobs. It is recorded as CALLER-SUPPLIED and grants nothing: it changes no permission, no idempotency scope and no quota."
                  },
                  "dryRun": {
                    "type": "boolean",
                    "description": "Report what this write WOULD do and commit nothing. The response carries the same change list, held fields and refusals as the real call, so it is the way to check a risky write, or a whole import, before it lands. Nothing is metered."
                  },
                  "overrideStanding": {
                    "type": "boolean",
                    "description": "Apply this write even when the value standing in the record was asserted more strongly than this one. Absent means no, which is the safe answer for a re-run. WITHOUT IT, a write can be accepted and change nothing: precedence is confirmed > user_supplied > observed > imported > inferred, and a weaker claim leaves the standing value in place and reports the field in `held[]` rather than failing. That is the whole of why a write can return 200 and not take. WITH it, this write wins regardless of what it is overruling, INCLUDING a value a person confirmed, so an agent that sets it by default has switched the provenance mechanism off. Set it per write, when the caller knows its claim supersedes what is there."
                  },
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 300
                  },
                  "stageId": {
                    "type": "string",
                    "description": "Only records in this stage. Stage ids come from the schema call, which lists every pipeline and its stages in order."
                  },
                  "companyId": {
                    "type": "string"
                  },
                  "amountMinor": {
                    "type": "integer",
                    "minimum": -9007199254740991,
                    "maximum": 9007199254740991
                  },
                  "currency": {
                    "type": "string",
                    "pattern": "^[A-Z]{3}$"
                  },
                  "expectedCloseDate": {
                    "type": "string"
                  },
                  "ownerActorId": {
                    "type": "string",
                    "minLength": 1
                  },
                  "probabilityBps": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 10000
                  },
                  "customFields": {
                    "type": "object",
                    "additionalProperties": {
                      "anyOf": [
                        {
                          "type": "string",
                          "maxLength": 2000
                        },
                        {
                          "type": "integer"
                        },
                        {
                          "type": "boolean"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "description": "Values for fields this workspace defined, keyed by the field's key. Read the schema first: a key that is not declared is REFUSED, with the available keys in the error, rather than stored where nobody will find it. Send null to clear one."
                  }
                },
                "required": [
                  "name"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "record": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "name": {
                          "type": "string"
                        },
                        "pipelineId": {
                          "type": "string"
                        },
                        "stageId": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "open",
                            "won",
                            "lost"
                          ]
                        },
                        "amountMinor": {
                          "type": "integer"
                        },
                        "currency": {
                          "type": "string"
                        },
                        "probabilityBps": {
                          "type": "integer"
                        },
                        "expectedCloseDate": {
                          "type": "string"
                        },
                        "companyName": {
                          "type": "string"
                        },
                        "lastActor": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string"
                            },
                            "kind": {
                              "type": "string",
                              "enum": [
                                "human",
                                "agent",
                                "api_token",
                                "system"
                              ]
                            },
                            "label": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "id",
                            "kind",
                            "label"
                          ],
                          "additionalProperties": true
                        },
                        "ownerActorId": {
                          "type": "string"
                        },
                        "externalProvider": {
                          "type": "string"
                        },
                        "externalId": {
                          "type": "string"
                        },
                        "version": {
                          "type": "integer"
                        },
                        "createdAt": {
                          "type": "string"
                        },
                        "updatedAt": {
                          "type": "string"
                        },
                        "archivedAt": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id",
                        "name",
                        "pipelineId",
                        "stageId",
                        "status",
                        "amountMinor",
                        "currency",
                        "probabilityBps",
                        "expectedCloseDate",
                        "ownerActorId",
                        "externalProvider",
                        "externalId",
                        "version",
                        "createdAt",
                        "updatedAt",
                        "archivedAt"
                      ],
                      "additionalProperties": true,
                      "description": "The record as it stands after the write. Absent on a dry run, which commits nothing."
                    },
                    "mutation": {
                      "type": "object",
                      "properties": {
                        "mutationId": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "created",
                            "updated",
                            "matched",
                            "archived",
                            "merged",
                            "reverted",
                            "noop"
                          ],
                          "description": "What the write did. `noop` means it was accepted and changed nothing, because every value it carried already matched what was stored. IT IS NOT METERED: a noop does not count against your monthly change allowance, so a nightly sync that finds nothing new costs nothing. Neither does a write that only REDUCES what a workspace holds. `matched` means an upsert found an existing record on real identity evidence rather than creating a second one; `reverted` and `merged` are the undo and duplicate paths, and both are ordinary writes that count."
                        },
                        "targetId": {
                          "type": "string"
                        },
                        "record": {},
                        "changes": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "before": {},
                              "after": {}
                            },
                            "required": [
                              "field"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "held": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "kept": {},
                              "proposed": {},
                              "standing": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "incoming": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "actorId": {
                                "type": "string",
                                "minLength": 1
                              },
                              "assertedAt": {
                                "type": "string",
                                "minLength": 1
                              }
                            },
                            "required": [
                              "field",
                              "standing",
                              "incoming",
                              "actorId",
                              "assertedAt"
                            ],
                            "additionalProperties": false
                          },
                          "description": "Fields this write asked to change and did not, because the value standing in the record was asserted more strongly. THIS IS WHY A WRITE CAN RETURN 200 AND CHANGE NOTHING, and a caller that ignores it will believe it wrote something it did not. Precedence is confirmed > user_supplied > observed > imported > inferred, and a write carrying no `assertionKind` is weakest of all. Each entry reports the field, what the record still says, what you proposed, which claim won, and who made it. Send `overrideStanding` to write anyway, per write, when your claim really does supersede theirs."
                        },
                        "matchedBy": {
                          "type": "string",
                          "enum": [
                            "email",
                            "domain",
                            "external_id",
                            "idempotency_key",
                            "explicit_id"
                          ]
                        },
                        "reversible": {
                          "type": "boolean"
                        },
                        "replayed": {
                          "type": "boolean"
                        },
                        "dryRun": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "mutationId",
                        "status",
                        "reversible"
                      ],
                      "additionalProperties": false,
                      "description": "What the write actually DID. Read `status` before you conclude anything: `noop` means it was accepted and changed nothing. `changes` is the field-level diff that was recorded, and `held` names any field whose stored value outranked the claim you sent and therefore did not move. A 200 with an empty `changes` and a populated `held` is the product working, not the call failing."
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "mutation",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "A product quota is spent, or the subscription is not active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A conflict the caller can resolve: a stale expectedVersion, an idempotency key reused for different input, an ambiguous or duplicate identity, or a merge that no longer applies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The body, or a single record inside it, exceeds its bound.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "507": {
            "description": "The workspace is at its storage ceiling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/opportunities:upsert": {
      "post": {
        "summary": "Create or safely match a deal on an external identity",
        "description": "Create a deal, or find the one another system already knows about and update it. Match is on the identity that system issued (externalProvider plus externalId) or on an explicit id, and never on the name: two deals with the same name are routinely two deals. Use create_opportunity when you mean to create one regardless.",
        "tags": [
          "opportunities"
        ],
        "operationId": "post_v1_opportunities_upsert",
        "x-indraft-capability": "crm:write",
        "x-indraft-scopes": [
          "crm:write",
          "crm:admin"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "idempotencyKey": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 200,
                    "description": "Your own name for this write, so retrying it cannot do it twice. Send the same key again and you get the SAME result back rather than a second record, which is what makes a re-run safe after a timeout you never saw the answer to. Derive it from what the write is about, not from the clock: `nightly-sync-halden` retries correctly and a timestamp does not."
                  },
                  "expectedVersion": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "The version you read before deciding to write. If the record has moved since, the write is refused instead of overwriting whatever changed. Send it whenever you read, reasoned, and then wrote: without it the last writer wins and neither of you finds out."
                  },
                  "sourceId": {
                    "type": "string",
                    "description": "The recorded source this claim came from, if one exists. It attaches evidence to the write, so a person reading the field later can see where it came from rather than only who sent it."
                  },
                  "assertionKind": {
                    "type": "string",
                    "enum": [
                      "observed",
                      "inferred",
                      "imported",
                      "user_supplied"
                    ],
                    "description": "HOW YOU KNOW. This is the field the product is built around, so say what is true rather than what is strongest: `observed` you saw it stated directly, `imported` it came from a file or another system, `inferred` you worked it out, `user_supplied` a person told you in so many words. They rank, weakest first: inferred < imported < observed < user_supplied < confirmed. A weaker claim does not overwrite a stronger one; it is reported in `held[]` and the stored value stands, so an unattended re-run converges instead of eroding what somebody checked. `confirmed` is not accepted here: it means a person checked the value, and only a signed-in person can set it."
                  },
                  "attributionLabel": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120,
                    "description": "A short name for the work this write belongs to, shown beside the actor so one credential can distinguish separate jobs. It is recorded as CALLER-SUPPLIED and grants nothing: it changes no permission, no idempotency scope and no quota."
                  },
                  "dryRun": {
                    "type": "boolean",
                    "description": "Report what this write WOULD do and commit nothing. The response carries the same change list, held fields and refusals as the real call, so it is the way to check a risky write, or a whole import, before it lands. Nothing is metered."
                  },
                  "overrideStanding": {
                    "type": "boolean",
                    "description": "Apply this write even when the value standing in the record was asserted more strongly than this one. Absent means no, which is the safe answer for a re-run. WITHOUT IT, a write can be accepted and change nothing: precedence is confirmed > user_supplied > observed > imported > inferred, and a weaker claim leaves the standing value in place and reports the field in `held[]` rather than failing. That is the whole of why a write can return 200 and not take. WITH it, this write wins regardless of what it is overruling, INCLUDING a value a person confirmed, so an agent that sets it by default has switched the provenance mechanism off. Set it per write, when the caller knows its claim supersedes what is there."
                  },
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 300
                  },
                  "stageId": {
                    "type": "string",
                    "description": "Only records in this stage. Stage ids come from the schema call, which lists every pipeline and its stages in order."
                  },
                  "companyId": {
                    "type": "string"
                  },
                  "amountMinor": {
                    "type": "integer",
                    "minimum": -9007199254740991,
                    "maximum": 9007199254740991
                  },
                  "currency": {
                    "type": "string",
                    "pattern": "^[A-Z]{3}$"
                  },
                  "expectedCloseDate": {
                    "type": "string"
                  },
                  "ownerActorId": {
                    "type": "string",
                    "minLength": 1
                  },
                  "probabilityBps": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 10000
                  },
                  "customFields": {
                    "type": "object",
                    "additionalProperties": {
                      "anyOf": [
                        {
                          "type": "string",
                          "maxLength": 2000
                        },
                        {
                          "type": "integer"
                        },
                        {
                          "type": "boolean"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "description": "Values for fields this workspace defined, keyed by the field's key. Read the schema first: a key that is not declared is REFUSED, with the available keys in the error, rather than stored where nobody will find it. Send null to clear one."
                  },
                  "id": {
                    "type": "string"
                  },
                  "externalProvider": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120
                  },
                  "externalId": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  }
                },
                "required": [
                  "name"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": [
                        "created",
                        "matched",
                        "ambiguous"
                      ],
                      "description": "Whether this created a record, matched an existing one on real identity evidence, or found several and committed nothing. `ambiguous` is not an error: it means the evidence you sent fits more than one record, and `candidates` lists them so a caller can choose rather than have one picked for it."
                    },
                    "record": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "name": {
                          "type": "string"
                        },
                        "pipelineId": {
                          "type": "string"
                        },
                        "stageId": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "open",
                            "won",
                            "lost"
                          ]
                        },
                        "amountMinor": {
                          "type": "integer"
                        },
                        "currency": {
                          "type": "string"
                        },
                        "probabilityBps": {
                          "type": "integer"
                        },
                        "expectedCloseDate": {
                          "type": "string"
                        },
                        "companyName": {
                          "type": "string"
                        },
                        "lastActor": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string"
                            },
                            "kind": {
                              "type": "string",
                              "enum": [
                                "human",
                                "agent",
                                "api_token",
                                "system"
                              ]
                            },
                            "label": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "id",
                            "kind",
                            "label"
                          ],
                          "additionalProperties": true
                        },
                        "ownerActorId": {
                          "type": "string"
                        },
                        "externalProvider": {
                          "type": "string"
                        },
                        "externalId": {
                          "type": "string"
                        },
                        "version": {
                          "type": "integer"
                        },
                        "createdAt": {
                          "type": "string"
                        },
                        "updatedAt": {
                          "type": "string"
                        },
                        "archivedAt": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id",
                        "name",
                        "pipelineId",
                        "stageId",
                        "status",
                        "amountMinor",
                        "currency",
                        "probabilityBps",
                        "expectedCloseDate",
                        "ownerActorId",
                        "externalProvider",
                        "externalId",
                        "version",
                        "createdAt",
                        "updatedAt",
                        "archivedAt"
                      ],
                      "additionalProperties": true,
                      "description": "The record as it stands. Absent on an ambiguous upsert and on a dry run."
                    },
                    "mutation": {
                      "type": "object",
                      "properties": {
                        "mutationId": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "created",
                            "updated",
                            "matched",
                            "archived",
                            "merged",
                            "reverted",
                            "noop"
                          ],
                          "description": "What the write did. `noop` means it was accepted and changed nothing, because every value it carried already matched what was stored. IT IS NOT METERED: a noop does not count against your monthly change allowance, so a nightly sync that finds nothing new costs nothing. Neither does a write that only REDUCES what a workspace holds. `matched` means an upsert found an existing record on real identity evidence rather than creating a second one; `reverted` and `merged` are the undo and duplicate paths, and both are ordinary writes that count."
                        },
                        "targetId": {
                          "type": "string"
                        },
                        "record": {},
                        "changes": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "before": {},
                              "after": {}
                            },
                            "required": [
                              "field"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "held": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "kept": {},
                              "proposed": {},
                              "standing": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "incoming": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "actorId": {
                                "type": "string",
                                "minLength": 1
                              },
                              "assertedAt": {
                                "type": "string",
                                "minLength": 1
                              }
                            },
                            "required": [
                              "field",
                              "standing",
                              "incoming",
                              "actorId",
                              "assertedAt"
                            ],
                            "additionalProperties": false
                          },
                          "description": "Fields this write asked to change and did not, because the value standing in the record was asserted more strongly. THIS IS WHY A WRITE CAN RETURN 200 AND CHANGE NOTHING, and a caller that ignores it will believe it wrote something it did not. Precedence is confirmed > user_supplied > observed > imported > inferred, and a write carrying no `assertionKind` is weakest of all. Each entry reports the field, what the record still says, what you proposed, which claim won, and who made it. Send `overrideStanding` to write anyway, per write, when your claim really does supersede theirs."
                        },
                        "matchedBy": {
                          "type": "string",
                          "enum": [
                            "email",
                            "domain",
                            "external_id",
                            "idempotency_key",
                            "explicit_id"
                          ]
                        },
                        "reversible": {
                          "type": "boolean"
                        },
                        "replayed": {
                          "type": "boolean"
                        },
                        "dryRun": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "mutationId",
                        "status",
                        "reversible"
                      ],
                      "additionalProperties": false,
                      "description": "What the write did. Absent when nothing was written, which is the ambiguous case."
                    },
                    "candidates": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "minLength": 1
                          },
                          "label": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 300
                          },
                          "matchedOn": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 200
                          }
                        },
                        "required": [
                          "id",
                          "label",
                          "matchedOn"
                        ],
                        "additionalProperties": false
                      },
                      "description": "The records the evidence fits, when it fits more than one. Send the upsert again naming the `id` you mean."
                    },
                    "matchReason": {
                      "type": "string",
                      "description": "Why this matched the record it matched, in words, when it matched one."
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "status",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "A product quota is spent, or the subscription is not active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A conflict the caller can resolve: a stale expectedVersion, an idempotency key reused for different input, an ambiguous or duplicate identity, or a merge that no longer applies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The body, or a single record inside it, exceeds its bound.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "507": {
            "description": "The workspace is at its storage ceiling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/opportunities/{id}": {
      "get": {
        "summary": "Read one opportunity",
        "description": "One deal by its id. Its stage carries a status derived from the stage's kind, so a deal cannot be open and won at the same time.",
        "tags": [
          "opportunities"
        ],
        "operationId": "get_v1_opportunities__id_",
        "x-indraft-capability": "crm:read",
        "x-indraft-scopes": [
          "crm:read",
          "crm:write",
          "crm:configure",
          "crm:admin",
          "crm:revert",
          "data:export"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The opportunity id, as returned by the call that created or matched it.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "opportunity": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "name": {
                          "type": "string"
                        },
                        "pipelineId": {
                          "type": "string"
                        },
                        "stageId": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "open",
                            "won",
                            "lost"
                          ]
                        },
                        "amountMinor": {
                          "type": "integer"
                        },
                        "currency": {
                          "type": "string"
                        },
                        "probabilityBps": {
                          "type": "integer"
                        },
                        "expectedCloseDate": {
                          "type": "string"
                        },
                        "companyName": {
                          "type": "string"
                        },
                        "lastActor": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string"
                            },
                            "kind": {
                              "type": "string",
                              "enum": [
                                "human",
                                "agent",
                                "api_token",
                                "system"
                              ]
                            },
                            "label": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "id",
                            "kind",
                            "label"
                          ],
                          "additionalProperties": true
                        },
                        "ownerActorId": {
                          "type": "string"
                        },
                        "externalProvider": {
                          "type": "string"
                        },
                        "externalId": {
                          "type": "string"
                        },
                        "version": {
                          "type": "integer"
                        },
                        "createdAt": {
                          "type": "string"
                        },
                        "updatedAt": {
                          "type": "string"
                        },
                        "archivedAt": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id",
                        "name",
                        "pipelineId",
                        "stageId",
                        "status",
                        "amountMinor",
                        "currency",
                        "probabilityBps",
                        "expectedCloseDate",
                        "ownerActorId",
                        "externalProvider",
                        "externalId",
                        "version",
                        "createdAt",
                        "updatedAt",
                        "archivedAt"
                      ],
                      "additionalProperties": true
                    },
                    "derived": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string"
                          },
                          "value": {
                            "type": "integer"
                          },
                          "unit": {
                            "type": "string",
                            "enum": [
                              "minor_units",
                              "days"
                            ]
                          },
                          "currency": {
                            "type": "string"
                          },
                          "inputs": {
                            "type": "object",
                            "additionalProperties": {
                              "anyOf": [
                                {
                                  "type": "integer"
                                },
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            }
                          }
                        },
                        "required": [
                          "name",
                          "value",
                          "unit",
                          "currency",
                          "inputs"
                        ],
                        "additionalProperties": true
                      }
                    },
                    "standing": {
                      "type": "object",
                      "additionalProperties": {
                        "type": "object",
                        "properties": {
                          "assertionKind": {
                            "type": "string",
                            "enum": [
                              "observed",
                              "inferred",
                              "imported",
                              "user_supplied",
                              "confirmed"
                            ]
                          },
                          "actorId": {
                            "type": "string"
                          },
                          "assertedAt": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "assertionKind",
                          "actorId",
                          "assertedAt"
                        ],
                        "additionalProperties": true
                      },
                      "description": "Per field: which kind of claim is standing on it, who asserted it, and when. This is the provenance the product is sold on, keyed by column name so it lines up with `changes`, `held[]` and the unconfirmed queue. `confirmed` means a person checked it and outranks everything an agent can assert; `inferred` is the weakest and is what an agent's own conclusion should carry. A write whose claim ranks below what is here is held rather than applied."
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "opportunity",
                    "derived",
                    "standing",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such record, or it belongs to another workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "summary": "Change an opportunity's name, amount, probability, or close date",
        "description": "Change an opportunity's name, amount, probability, expected close date, or owner. Pass expectedVersion to refuse the write if someone else changed it first.",
        "tags": [
          "opportunities"
        ],
        "operationId": "patch_v1_opportunities__id_",
        "x-indraft-capability": "crm:write",
        "x-indraft-scopes": [
          "crm:write",
          "crm:admin"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The opportunity id, as returned by the call that created or matched it.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "idempotencyKey": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 200,
                    "description": "Your own name for this write, so retrying it cannot do it twice. Send the same key again and you get the SAME result back rather than a second record, which is what makes a re-run safe after a timeout you never saw the answer to. Derive it from what the write is about, not from the clock: `nightly-sync-halden` retries correctly and a timestamp does not."
                  },
                  "expectedVersion": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "The version you read before deciding to write. If the record has moved since, the write is refused instead of overwriting whatever changed. Send it whenever you read, reasoned, and then wrote: without it the last writer wins and neither of you finds out."
                  },
                  "sourceId": {
                    "type": "string",
                    "description": "The recorded source this claim came from, if one exists. It attaches evidence to the write, so a person reading the field later can see where it came from rather than only who sent it."
                  },
                  "assertionKind": {
                    "type": "string",
                    "enum": [
                      "observed",
                      "inferred",
                      "imported",
                      "user_supplied"
                    ],
                    "description": "HOW YOU KNOW. This is the field the product is built around, so say what is true rather than what is strongest: `observed` you saw it stated directly, `imported` it came from a file or another system, `inferred` you worked it out, `user_supplied` a person told you in so many words. They rank, weakest first: inferred < imported < observed < user_supplied < confirmed. A weaker claim does not overwrite a stronger one; it is reported in `held[]` and the stored value stands, so an unattended re-run converges instead of eroding what somebody checked. `confirmed` is not accepted here: it means a person checked the value, and only a signed-in person can set it."
                  },
                  "attributionLabel": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120,
                    "description": "A short name for the work this write belongs to, shown beside the actor so one credential can distinguish separate jobs. It is recorded as CALLER-SUPPLIED and grants nothing: it changes no permission, no idempotency scope and no quota."
                  },
                  "dryRun": {
                    "type": "boolean",
                    "description": "Report what this write WOULD do and commit nothing. The response carries the same change list, held fields and refusals as the real call, so it is the way to check a risky write, or a whole import, before it lands. Nothing is metered."
                  },
                  "overrideStanding": {
                    "type": "boolean",
                    "description": "Apply this write even when the value standing in the record was asserted more strongly than this one. Absent means no, which is the safe answer for a re-run. WITHOUT IT, a write can be accepted and change nothing: precedence is confirmed > user_supplied > observed > imported > inferred, and a weaker claim leaves the standing value in place and reports the field in `held[]` rather than failing. That is the whole of why a write can return 200 and not take. WITH it, this write wins regardless of what it is overruling, INCLUDING a value a person confirmed, so an agent that sets it by default has switched the provenance mechanism off. Set it per write, when the caller knows its claim supersedes what is there."
                  },
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 300
                  },
                  "amountMinor": {
                    "type": "integer",
                    "minimum": -9007199254740991,
                    "maximum": 9007199254740991
                  },
                  "currency": {
                    "type": "string",
                    "pattern": "^[A-Z]{3}$"
                  },
                  "probabilityBps": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 10000
                  },
                  "expectedCloseDate": {
                    "type": "string"
                  },
                  "ownerActorId": {
                    "type": "string",
                    "minLength": 1
                  },
                  "customFields": {
                    "type": "object",
                    "additionalProperties": {
                      "anyOf": [
                        {
                          "type": "string",
                          "maxLength": 2000
                        },
                        {
                          "type": "integer"
                        },
                        {
                          "type": "boolean"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "description": "Values for fields this workspace defined, keyed by the field's key. Read the schema first: a key that is not declared is REFUSED, with the available keys in the error, rather than stored where nobody will find it. Send null to clear one."
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "record": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "name": {
                          "type": "string"
                        },
                        "pipelineId": {
                          "type": "string"
                        },
                        "stageId": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "open",
                            "won",
                            "lost"
                          ]
                        },
                        "amountMinor": {
                          "type": "integer"
                        },
                        "currency": {
                          "type": "string"
                        },
                        "probabilityBps": {
                          "type": "integer"
                        },
                        "expectedCloseDate": {
                          "type": "string"
                        },
                        "companyName": {
                          "type": "string"
                        },
                        "lastActor": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string"
                            },
                            "kind": {
                              "type": "string",
                              "enum": [
                                "human",
                                "agent",
                                "api_token",
                                "system"
                              ]
                            },
                            "label": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "id",
                            "kind",
                            "label"
                          ],
                          "additionalProperties": true
                        },
                        "ownerActorId": {
                          "type": "string"
                        },
                        "externalProvider": {
                          "type": "string"
                        },
                        "externalId": {
                          "type": "string"
                        },
                        "version": {
                          "type": "integer"
                        },
                        "createdAt": {
                          "type": "string"
                        },
                        "updatedAt": {
                          "type": "string"
                        },
                        "archivedAt": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id",
                        "name",
                        "pipelineId",
                        "stageId",
                        "status",
                        "amountMinor",
                        "currency",
                        "probabilityBps",
                        "expectedCloseDate",
                        "ownerActorId",
                        "externalProvider",
                        "externalId",
                        "version",
                        "createdAt",
                        "updatedAt",
                        "archivedAt"
                      ],
                      "additionalProperties": true,
                      "description": "The record as it stands after the write. Absent on a dry run, which commits nothing."
                    },
                    "mutation": {
                      "type": "object",
                      "properties": {
                        "mutationId": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "created",
                            "updated",
                            "matched",
                            "archived",
                            "merged",
                            "reverted",
                            "noop"
                          ],
                          "description": "What the write did. `noop` means it was accepted and changed nothing, because every value it carried already matched what was stored. IT IS NOT METERED: a noop does not count against your monthly change allowance, so a nightly sync that finds nothing new costs nothing. Neither does a write that only REDUCES what a workspace holds. `matched` means an upsert found an existing record on real identity evidence rather than creating a second one; `reverted` and `merged` are the undo and duplicate paths, and both are ordinary writes that count."
                        },
                        "targetId": {
                          "type": "string"
                        },
                        "record": {},
                        "changes": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "before": {},
                              "after": {}
                            },
                            "required": [
                              "field"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "held": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "kept": {},
                              "proposed": {},
                              "standing": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "incoming": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "actorId": {
                                "type": "string",
                                "minLength": 1
                              },
                              "assertedAt": {
                                "type": "string",
                                "minLength": 1
                              }
                            },
                            "required": [
                              "field",
                              "standing",
                              "incoming",
                              "actorId",
                              "assertedAt"
                            ],
                            "additionalProperties": false
                          },
                          "description": "Fields this write asked to change and did not, because the value standing in the record was asserted more strongly. THIS IS WHY A WRITE CAN RETURN 200 AND CHANGE NOTHING, and a caller that ignores it will believe it wrote something it did not. Precedence is confirmed > user_supplied > observed > imported > inferred, and a write carrying no `assertionKind` is weakest of all. Each entry reports the field, what the record still says, what you proposed, which claim won, and who made it. Send `overrideStanding` to write anyway, per write, when your claim really does supersede theirs."
                        },
                        "matchedBy": {
                          "type": "string",
                          "enum": [
                            "email",
                            "domain",
                            "external_id",
                            "idempotency_key",
                            "explicit_id"
                          ]
                        },
                        "reversible": {
                          "type": "boolean"
                        },
                        "replayed": {
                          "type": "boolean"
                        },
                        "dryRun": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "mutationId",
                        "status",
                        "reversible"
                      ],
                      "additionalProperties": false,
                      "description": "What the write actually DID. Read `status` before you conclude anything: `noop` means it was accepted and changed nothing. `changes` is the field-level diff that was recorded, and `held` names any field whose stored value outranked the claim you sent and therefore did not move. A 200 with an empty `changes` and a populated `held` is the product working, not the call failing."
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "mutation",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "A product quota is spent, or the subscription is not active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such record, or it belongs to another workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A conflict the caller can resolve: a stale expectedVersion, an idempotency key reused for different input, an ambiguous or duplicate identity, or a merge that no longer applies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The body, or a single record inside it, exceeds its bound.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "507": {
            "description": "The workspace is at its storage ceiling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/opportunities/{id}/advance": {
      "post": {
        "summary": "Move an opportunity to a stage",
        "description": "Move an opportunity to a stage. Status (open, won, lost) is derived from the stage, so this is how a deal is won or lost.",
        "tags": [
          "opportunities"
        ],
        "operationId": "post_v1_opportunities__id__advance",
        "x-indraft-capability": "crm:write",
        "x-indraft-scopes": [
          "crm:write",
          "crm:admin"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The opportunity id, as returned by the call that created or matched it.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "idempotencyKey": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 200,
                    "description": "Your own name for this write, so retrying it cannot do it twice. Send the same key again and you get the SAME result back rather than a second record, which is what makes a re-run safe after a timeout you never saw the answer to. Derive it from what the write is about, not from the clock: `nightly-sync-halden` retries correctly and a timestamp does not."
                  },
                  "expectedVersion": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "The version you read before deciding to write. If the record has moved since, the write is refused instead of overwriting whatever changed. Send it whenever you read, reasoned, and then wrote: without it the last writer wins and neither of you finds out."
                  },
                  "sourceId": {
                    "type": "string",
                    "description": "The recorded source this claim came from, if one exists. It attaches evidence to the write, so a person reading the field later can see where it came from rather than only who sent it."
                  },
                  "assertionKind": {
                    "type": "string",
                    "enum": [
                      "observed",
                      "inferred",
                      "imported",
                      "user_supplied"
                    ],
                    "description": "HOW YOU KNOW. This is the field the product is built around, so say what is true rather than what is strongest: `observed` you saw it stated directly, `imported` it came from a file or another system, `inferred` you worked it out, `user_supplied` a person told you in so many words. They rank, weakest first: inferred < imported < observed < user_supplied < confirmed. A weaker claim does not overwrite a stronger one; it is reported in `held[]` and the stored value stands, so an unattended re-run converges instead of eroding what somebody checked. `confirmed` is not accepted here: it means a person checked the value, and only a signed-in person can set it."
                  },
                  "attributionLabel": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120,
                    "description": "A short name for the work this write belongs to, shown beside the actor so one credential can distinguish separate jobs. It is recorded as CALLER-SUPPLIED and grants nothing: it changes no permission, no idempotency scope and no quota."
                  },
                  "dryRun": {
                    "type": "boolean",
                    "description": "Report what this write WOULD do and commit nothing. The response carries the same change list, held fields and refusals as the real call, so it is the way to check a risky write, or a whole import, before it lands. Nothing is metered."
                  },
                  "overrideStanding": {
                    "type": "boolean",
                    "description": "Apply this write even when the value standing in the record was asserted more strongly than this one. Absent means no, which is the safe answer for a re-run. WITHOUT IT, a write can be accepted and change nothing: precedence is confirmed > user_supplied > observed > imported > inferred, and a weaker claim leaves the standing value in place and reports the field in `held[]` rather than failing. That is the whole of why a write can return 200 and not take. WITH it, this write wins regardless of what it is overruling, INCLUDING a value a person confirmed, so an agent that sets it by default has switched the provenance mechanism off. Set it per write, when the caller knows its claim supersedes what is there."
                  },
                  "stageId": {
                    "type": "string",
                    "minLength": 1
                  }
                },
                "required": [
                  "stageId"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "record": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "name": {
                          "type": "string"
                        },
                        "pipelineId": {
                          "type": "string"
                        },
                        "stageId": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "open",
                            "won",
                            "lost"
                          ]
                        },
                        "amountMinor": {
                          "type": "integer"
                        },
                        "currency": {
                          "type": "string"
                        },
                        "probabilityBps": {
                          "type": "integer"
                        },
                        "expectedCloseDate": {
                          "type": "string"
                        },
                        "companyName": {
                          "type": "string"
                        },
                        "lastActor": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string"
                            },
                            "kind": {
                              "type": "string",
                              "enum": [
                                "human",
                                "agent",
                                "api_token",
                                "system"
                              ]
                            },
                            "label": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "id",
                            "kind",
                            "label"
                          ],
                          "additionalProperties": true
                        },
                        "ownerActorId": {
                          "type": "string"
                        },
                        "externalProvider": {
                          "type": "string"
                        },
                        "externalId": {
                          "type": "string"
                        },
                        "version": {
                          "type": "integer"
                        },
                        "createdAt": {
                          "type": "string"
                        },
                        "updatedAt": {
                          "type": "string"
                        },
                        "archivedAt": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id",
                        "name",
                        "pipelineId",
                        "stageId",
                        "status",
                        "amountMinor",
                        "currency",
                        "probabilityBps",
                        "expectedCloseDate",
                        "ownerActorId",
                        "externalProvider",
                        "externalId",
                        "version",
                        "createdAt",
                        "updatedAt",
                        "archivedAt"
                      ],
                      "additionalProperties": true,
                      "description": "The record as it stands after the write. Absent on a dry run, which commits nothing."
                    },
                    "mutation": {
                      "type": "object",
                      "properties": {
                        "mutationId": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "created",
                            "updated",
                            "matched",
                            "archived",
                            "merged",
                            "reverted",
                            "noop"
                          ],
                          "description": "What the write did. `noop` means it was accepted and changed nothing, because every value it carried already matched what was stored. IT IS NOT METERED: a noop does not count against your monthly change allowance, so a nightly sync that finds nothing new costs nothing. Neither does a write that only REDUCES what a workspace holds. `matched` means an upsert found an existing record on real identity evidence rather than creating a second one; `reverted` and `merged` are the undo and duplicate paths, and both are ordinary writes that count."
                        },
                        "targetId": {
                          "type": "string"
                        },
                        "record": {},
                        "changes": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "before": {},
                              "after": {}
                            },
                            "required": [
                              "field"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "held": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "kept": {},
                              "proposed": {},
                              "standing": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "incoming": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "actorId": {
                                "type": "string",
                                "minLength": 1
                              },
                              "assertedAt": {
                                "type": "string",
                                "minLength": 1
                              }
                            },
                            "required": [
                              "field",
                              "standing",
                              "incoming",
                              "actorId",
                              "assertedAt"
                            ],
                            "additionalProperties": false
                          },
                          "description": "Fields this write asked to change and did not, because the value standing in the record was asserted more strongly. THIS IS WHY A WRITE CAN RETURN 200 AND CHANGE NOTHING, and a caller that ignores it will believe it wrote something it did not. Precedence is confirmed > user_supplied > observed > imported > inferred, and a write carrying no `assertionKind` is weakest of all. Each entry reports the field, what the record still says, what you proposed, which claim won, and who made it. Send `overrideStanding` to write anyway, per write, when your claim really does supersede theirs."
                        },
                        "matchedBy": {
                          "type": "string",
                          "enum": [
                            "email",
                            "domain",
                            "external_id",
                            "idempotency_key",
                            "explicit_id"
                          ]
                        },
                        "reversible": {
                          "type": "boolean"
                        },
                        "replayed": {
                          "type": "boolean"
                        },
                        "dryRun": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "mutationId",
                        "status",
                        "reversible"
                      ],
                      "additionalProperties": false,
                      "description": "What the write actually DID. Read `status` before you conclude anything: `noop` means it was accepted and changed nothing. `changes` is the field-level diff that was recorded, and `held` names any field whose stored value outranked the claim you sent and therefore did not move. A 200 with an empty `changes` and a populated `held` is the product working, not the call failing."
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "mutation",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "A product quota is spent, or the subscription is not active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such record, or it belongs to another workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A conflict the caller can resolve: a stale expectedVersion, an idempotency key reused for different input, an ambiguous or duplicate identity, or a merge that no longer applies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The body, or a single record inside it, exceeds its bound.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "507": {
            "description": "The workspace is at its storage ceiling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/interactions": {
      "get": {
        "summary": "Every interaction in the workspace, newest first",
        "description": "Every interaction in the workspace, newest first, across all records. Use a company's own interactions when you want one account's history rather than the whole workspace's.",
        "tags": [
          "interactions"
        ],
        "operationId": "get_v1_interactions",
        "x-indraft-capability": "crm:read",
        "x-indraft-scopes": [
          "crm:read",
          "crm:write",
          "crm:configure",
          "crm:admin",
          "crm:revert",
          "data:export"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "description": "How many to return. The page bound is published in the schema call, and asking for more is refused rather than quietly truncated."
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "The opaque marker from the previous page. Store it and hand it back; do not parse it. A cursor is only ever emitted when another row really exists, so a page you were given is never empty."
            }
          },
          {
            "name": "updatedSince",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 40,
              "description": "Only rows changed after this instant. The incremental read: without it a service syncing a large workspace has to walk all of it every time."
            }
          },
          {
            "name": "lastInteractionBefore",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 40,
              "description": "Only records whose most recent interaction is older than this, including those with none at all."
            }
          },
          {
            "name": "includeArchived",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "Include archived rows. Off by default, because a list is what you are working on and history is somewhere you go deliberately."
            }
          },
          {
            "name": "filter",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 560
                },
                {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 560
                  },
                  "maxItems": 8
                }
              ],
              "description": "Predicates, all of which must hold, written field:op:value. Only fields an index serves are accepted, and asking for one that is not names the ones that are."
            }
          },
          {
            "name": "or",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 560
                },
                {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 560
                  },
                  "maxItems": 4
                }
              ],
              "description": "Alternatives, ORed with each other and ANDed with filter. One level and never a tree: owned by me or owned by nobody is the question people ask, and anything deeper has a cost the caller cannot read off it."
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 65,
              "description": "A field to order by, with a leading minus for descending. Indexed fields only, for the same reason as filter."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "interactionType": {
                            "type": "string",
                            "enum": [
                              "email",
                              "call",
                              "meeting",
                              "message",
                              "note"
                            ]
                          },
                          "direction": {
                            "type": "string",
                            "enum": [
                              "inbound",
                              "outbound",
                              "internal"
                            ]
                          },
                          "subject": {
                            "type": "string"
                          },
                          "summary": {
                            "type": "string"
                          },
                          "assertionKind": {
                            "type": "string",
                            "enum": [
                              "observed",
                              "inferred",
                              "imported",
                              "user_supplied"
                            ]
                          },
                          "occurredAt": {
                            "type": "string"
                          },
                          "sourceId": {
                            "type": "string"
                          },
                          "createdByActorId": {
                            "type": "string"
                          },
                          "actor": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string"
                              },
                              "kind": {
                                "type": "string",
                                "enum": [
                                  "human",
                                  "agent",
                                  "api_token",
                                  "system"
                                ]
                              },
                              "label": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "id",
                              "kind",
                              "label"
                            ],
                            "additionalProperties": true
                          },
                          "links": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "objectType": {
                                  "type": "string",
                                  "enum": [
                                    "company",
                                    "contact",
                                    "opportunity"
                                  ]
                                },
                                "objectId": {
                                  "type": "string"
                                }
                              },
                              "required": [
                                "objectType",
                                "objectId"
                              ],
                              "additionalProperties": true
                            }
                          },
                          "createdAt": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "interactionType",
                          "direction",
                          "subject",
                          "summary",
                          "assertionKind",
                          "occurredAt",
                          "sourceId",
                          "createdByActorId",
                          "links",
                          "createdAt"
                        ],
                        "additionalProperties": true
                      },
                      "description": "This page of results, in the order you asked for."
                    },
                    "nextCursor": {
                      "type": "string",
                      "description": "Hand this back to get the next page, or null when there is no next page. Null is the end of the list and an empty `items` is not: a cursor is only emitted when another row really exists."
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "items",
                    "nextCursor",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Record a normalized interaction",
        "description": "Record what happened: an email, call, meeting, message, or note, as a SUMMARY you write. Indraft never stores a raw message body, transcript, or attachment. Link it to the companies, contacts, and opportunities it concerns, and put the structured conclusion in customFields: disposition, meeting type and next step belong in fields you can group by rather than in prose.",
        "tags": [
          "interactions"
        ],
        "operationId": "post_v1_interactions",
        "x-indraft-capability": "crm:write",
        "x-indraft-scopes": [
          "crm:write",
          "crm:admin"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "idempotencyKey": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 200,
                    "description": "Your own name for this write, so retrying it cannot do it twice. Send the same key again and you get the SAME result back rather than a second record, which is what makes a re-run safe after a timeout you never saw the answer to. Derive it from what the write is about, not from the clock: `nightly-sync-halden` retries correctly and a timestamp does not."
                  },
                  "expectedVersion": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "The version you read before deciding to write. If the record has moved since, the write is refused instead of overwriting whatever changed. Send it whenever you read, reasoned, and then wrote: without it the last writer wins and neither of you finds out."
                  },
                  "sourceId": {
                    "type": "string",
                    "description": "The recorded source this claim came from, if one exists. It attaches evidence to the write, so a person reading the field later can see where it came from rather than only who sent it."
                  },
                  "assertionKind": {
                    "type": "string",
                    "enum": [
                      "observed",
                      "inferred",
                      "imported",
                      "user_supplied"
                    ],
                    "description": "HOW YOU KNOW. This is the field the product is built around, so say what is true rather than what is strongest: `observed` you saw it stated directly, `imported` it came from a file or another system, `inferred` you worked it out, `user_supplied` a person told you in so many words. They rank, weakest first: inferred < imported < observed < user_supplied < confirmed. A weaker claim does not overwrite a stronger one; it is reported in `held[]` and the stored value stands, so an unattended re-run converges instead of eroding what somebody checked. `confirmed` is not accepted here: it means a person checked the value, and only a signed-in person can set it."
                  },
                  "attributionLabel": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120,
                    "description": "A short name for the work this write belongs to, shown beside the actor so one credential can distinguish separate jobs. It is recorded as CALLER-SUPPLIED and grants nothing: it changes no permission, no idempotency scope and no quota."
                  },
                  "dryRun": {
                    "type": "boolean",
                    "description": "Report what this write WOULD do and commit nothing. The response carries the same change list, held fields and refusals as the real call, so it is the way to check a risky write, or a whole import, before it lands. Nothing is metered."
                  },
                  "overrideStanding": {
                    "type": "boolean",
                    "description": "Apply this write even when the value standing in the record was asserted more strongly than this one. Absent means no, which is the safe answer for a re-run. WITHOUT IT, a write can be accepted and change nothing: precedence is confirmed > user_supplied > observed > imported > inferred, and a weaker claim leaves the standing value in place and reports the field in `held[]` rather than failing. That is the whole of why a write can return 200 and not take. WITH it, this write wins regardless of what it is overruling, INCLUDING a value a person confirmed, so an agent that sets it by default has switched the provenance mechanism off. Set it per write, when the caller knows its claim supersedes what is there."
                  },
                  "interactionType": {
                    "type": "string",
                    "enum": [
                      "email",
                      "call",
                      "meeting",
                      "message",
                      "note"
                    ]
                  },
                  "direction": {
                    "type": "string",
                    "enum": [
                      "inbound",
                      "outbound",
                      "internal"
                    ]
                  },
                  "subject": {
                    "type": "string",
                    "maxLength": 200
                  },
                  "summary": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 4000
                  },
                  "occurredAt": {
                    "type": "string"
                  },
                  "provider": {
                    "type": "string",
                    "maxLength": 200
                  },
                  "externalId": {
                    "type": "string",
                    "maxLength": 200
                  },
                  "evidenceText": {
                    "type": "string",
                    "maxLength": 2000
                  },
                  "customFields": {
                    "type": "object",
                    "additionalProperties": {
                      "anyOf": [
                        {
                          "type": "string",
                          "maxLength": 2000
                        },
                        {
                          "type": "integer"
                        },
                        {
                          "type": "boolean"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "description": "Values for fields this workspace defined, keyed by the field's key. Read the schema first: a key that is not declared is REFUSED, with the available keys in the error, rather than stored where nobody will find it. Send null to clear one."
                  },
                  "companyIds": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "maxItems": 100
                  },
                  "contactIds": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "maxItems": 100
                  },
                  "opportunityIds": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "maxItems": 100
                  }
                },
                "required": [
                  "interactionType",
                  "summary",
                  "occurredAt"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "record": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "interactionType": {
                          "type": "string",
                          "enum": [
                            "email",
                            "call",
                            "meeting",
                            "message",
                            "note"
                          ]
                        },
                        "direction": {
                          "type": "string",
                          "enum": [
                            "inbound",
                            "outbound",
                            "internal"
                          ]
                        },
                        "subject": {
                          "type": "string"
                        },
                        "summary": {
                          "type": "string"
                        },
                        "assertionKind": {
                          "type": "string",
                          "enum": [
                            "observed",
                            "inferred",
                            "imported",
                            "user_supplied"
                          ]
                        },
                        "occurredAt": {
                          "type": "string"
                        },
                        "sourceId": {
                          "type": "string"
                        },
                        "createdByActorId": {
                          "type": "string"
                        },
                        "actor": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string"
                            },
                            "kind": {
                              "type": "string",
                              "enum": [
                                "human",
                                "agent",
                                "api_token",
                                "system"
                              ]
                            },
                            "label": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "id",
                            "kind",
                            "label"
                          ],
                          "additionalProperties": true
                        },
                        "links": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "objectType": {
                                "type": "string",
                                "enum": [
                                  "company",
                                  "contact",
                                  "opportunity"
                                ]
                              },
                              "objectId": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "objectType",
                              "objectId"
                            ],
                            "additionalProperties": true
                          }
                        },
                        "createdAt": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id",
                        "interactionType",
                        "direction",
                        "subject",
                        "summary",
                        "assertionKind",
                        "occurredAt",
                        "sourceId",
                        "createdByActorId",
                        "links",
                        "createdAt"
                      ],
                      "additionalProperties": true,
                      "description": "The record as it stands after the write. Absent on a dry run, which commits nothing."
                    },
                    "mutation": {
                      "type": "object",
                      "properties": {
                        "mutationId": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "created",
                            "updated",
                            "matched",
                            "archived",
                            "merged",
                            "reverted",
                            "noop"
                          ],
                          "description": "What the write did. `noop` means it was accepted and changed nothing, because every value it carried already matched what was stored. IT IS NOT METERED: a noop does not count against your monthly change allowance, so a nightly sync that finds nothing new costs nothing. Neither does a write that only REDUCES what a workspace holds. `matched` means an upsert found an existing record on real identity evidence rather than creating a second one; `reverted` and `merged` are the undo and duplicate paths, and both are ordinary writes that count."
                        },
                        "targetId": {
                          "type": "string"
                        },
                        "record": {},
                        "changes": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "before": {},
                              "after": {}
                            },
                            "required": [
                              "field"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "held": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "kept": {},
                              "proposed": {},
                              "standing": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "incoming": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "actorId": {
                                "type": "string",
                                "minLength": 1
                              },
                              "assertedAt": {
                                "type": "string",
                                "minLength": 1
                              }
                            },
                            "required": [
                              "field",
                              "standing",
                              "incoming",
                              "actorId",
                              "assertedAt"
                            ],
                            "additionalProperties": false
                          },
                          "description": "Fields this write asked to change and did not, because the value standing in the record was asserted more strongly. THIS IS WHY A WRITE CAN RETURN 200 AND CHANGE NOTHING, and a caller that ignores it will believe it wrote something it did not. Precedence is confirmed > user_supplied > observed > imported > inferred, and a write carrying no `assertionKind` is weakest of all. Each entry reports the field, what the record still says, what you proposed, which claim won, and who made it. Send `overrideStanding` to write anyway, per write, when your claim really does supersede theirs."
                        },
                        "matchedBy": {
                          "type": "string",
                          "enum": [
                            "email",
                            "domain",
                            "external_id",
                            "idempotency_key",
                            "explicit_id"
                          ]
                        },
                        "reversible": {
                          "type": "boolean"
                        },
                        "replayed": {
                          "type": "boolean"
                        },
                        "dryRun": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "mutationId",
                        "status",
                        "reversible"
                      ],
                      "additionalProperties": false,
                      "description": "What the write actually DID. Read `status` before you conclude anything: `noop` means it was accepted and changed nothing. `changes` is the field-level diff that was recorded, and `held` names any field whose stored value outranked the claim you sent and therefore did not move. A 200 with an empty `changes` and a populated `held` is the product working, not the call failing."
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "mutation",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "A product quota is spent, or the subscription is not active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A conflict the caller can resolve: a stale expectedVersion, an idempotency key reused for different input, an ambiguous or duplicate identity, or a merge that no longer applies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The body, or a single record inside it, exceeds its bound.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "507": {
            "description": "The workspace is at its storage ceiling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/tasks": {
      "get": {
        "summary": "List tasks",
        "description": "List tasks by status or assignee, newest first, with a cursor for the next page. Narrow with filter, for example filter: ['owner_actor_id:eq:act_...', 'expected_close_date:isNotNull'] and sort: '-expected_close_date'; get_crm_schema lists the fields each type accepts.",
        "tags": [
          "tasks"
        ],
        "operationId": "get_v1_tasks",
        "x-indraft-capability": "crm:read",
        "x-indraft-scopes": [
          "crm:read",
          "crm:write",
          "crm:configure",
          "crm:admin",
          "crm:revert",
          "data:export"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "description": "How many to return. The page bound is published in the schema call, and asking for more is refused rather than quietly truncated."
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "The opaque marker from the previous page. Store it and hand it back; do not parse it. A cursor is only ever emitted when another row really exists, so a page you were given is never empty."
            }
          },
          {
            "name": "updatedSince",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 40,
              "description": "Only rows changed after this instant. The incremental read: without it a service syncing a large workspace has to walk all of it every time."
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "open",
                "done",
                "cancelled"
              ],
              "description": "Only records with this status. Status is derived from the stage's kind rather than set separately, so a deal cannot be open and won at once."
            }
          },
          {
            "name": "assigneeActorId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "Only tasks assigned to this actor. The actor id comes back on every change and in the schema call for the caller themselves."
            }
          },
          {
            "name": "filter",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 560
                },
                {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 560
                  },
                  "maxItems": 8
                }
              ],
              "description": "Predicates, all of which must hold, written field:op:value. Only fields an index serves are accepted, and asking for one that is not names the ones that are."
            }
          },
          {
            "name": "or",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 560
                },
                {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 560
                  },
                  "maxItems": 4
                }
              ],
              "description": "Alternatives, ORed with each other and ANDed with filter. One level and never a tree: owned by me or owned by nobody is the question people ask, and anything deeper has a cost the caller cannot read off it."
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 65,
              "description": "A field to order by, with a leading minus for descending. Indexed fields only, for the same reason as filter."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "open",
                              "done",
                              "cancelled"
                            ]
                          },
                          "assigneeActorId": {
                            "type": "string"
                          },
                          "assignee": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string"
                              },
                              "kind": {
                                "type": "string",
                                "enum": [
                                  "human",
                                  "agent",
                                  "api_token",
                                  "system"
                                ]
                              },
                              "label": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "id",
                              "kind",
                              "label"
                            ],
                            "additionalProperties": true
                          },
                          "dueAt": {
                            "type": "string"
                          },
                          "priority": {
                            "type": "string",
                            "enum": [
                              "low",
                              "normal",
                              "high"
                            ]
                          },
                          "completedAt": {
                            "type": "string"
                          },
                          "ownerActorId": {
                            "type": "string"
                          },
                          "version": {
                            "type": "integer"
                          },
                          "links": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "objectType": {
                                  "type": "string",
                                  "enum": [
                                    "company",
                                    "contact",
                                    "opportunity"
                                  ]
                                },
                                "objectId": {
                                  "type": "string"
                                }
                              },
                              "required": [
                                "objectType",
                                "objectId"
                              ],
                              "additionalProperties": true
                            }
                          },
                          "createdAt": {
                            "type": "string"
                          },
                          "updatedAt": {
                            "type": "string"
                          },
                          "archivedAt": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "title",
                          "status",
                          "assigneeActorId",
                          "dueAt",
                          "priority",
                          "completedAt",
                          "ownerActorId",
                          "version",
                          "links",
                          "createdAt",
                          "updatedAt",
                          "archivedAt"
                        ],
                        "additionalProperties": true
                      },
                      "description": "This page of results, in the order you asked for."
                    },
                    "nextCursor": {
                      "type": "string",
                      "description": "Hand this back to get the next page, or null when there is no next page. Null is the end of the list and an empty `items` is not: a cursor is only emitted when another row really exists."
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "items",
                    "nextCursor",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Create a follow-up task",
        "description": "Create a follow-up, optionally due at a time and linked to CRM records.",
        "tags": [
          "tasks"
        ],
        "operationId": "post_v1_tasks",
        "x-indraft-capability": "crm:write",
        "x-indraft-scopes": [
          "crm:write",
          "crm:admin"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "idempotencyKey": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 200,
                    "description": "Your own name for this write, so retrying it cannot do it twice. Send the same key again and you get the SAME result back rather than a second record, which is what makes a re-run safe after a timeout you never saw the answer to. Derive it from what the write is about, not from the clock: `nightly-sync-halden` retries correctly and a timestamp does not."
                  },
                  "expectedVersion": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "The version you read before deciding to write. If the record has moved since, the write is refused instead of overwriting whatever changed. Send it whenever you read, reasoned, and then wrote: without it the last writer wins and neither of you finds out."
                  },
                  "sourceId": {
                    "type": "string",
                    "description": "The recorded source this claim came from, if one exists. It attaches evidence to the write, so a person reading the field later can see where it came from rather than only who sent it."
                  },
                  "assertionKind": {
                    "type": "string",
                    "enum": [
                      "observed",
                      "inferred",
                      "imported",
                      "user_supplied"
                    ],
                    "description": "HOW YOU KNOW. This is the field the product is built around, so say what is true rather than what is strongest: `observed` you saw it stated directly, `imported` it came from a file or another system, `inferred` you worked it out, `user_supplied` a person told you in so many words. They rank, weakest first: inferred < imported < observed < user_supplied < confirmed. A weaker claim does not overwrite a stronger one; it is reported in `held[]` and the stored value stands, so an unattended re-run converges instead of eroding what somebody checked. `confirmed` is not accepted here: it means a person checked the value, and only a signed-in person can set it."
                  },
                  "attributionLabel": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120,
                    "description": "A short name for the work this write belongs to, shown beside the actor so one credential can distinguish separate jobs. It is recorded as CALLER-SUPPLIED and grants nothing: it changes no permission, no idempotency scope and no quota."
                  },
                  "dryRun": {
                    "type": "boolean",
                    "description": "Report what this write WOULD do and commit nothing. The response carries the same change list, held fields and refusals as the real call, so it is the way to check a risky write, or a whole import, before it lands. Nothing is metered."
                  },
                  "overrideStanding": {
                    "type": "boolean",
                    "description": "Apply this write even when the value standing in the record was asserted more strongly than this one. Absent means no, which is the safe answer for a re-run. WITHOUT IT, a write can be accepted and change nothing: precedence is confirmed > user_supplied > observed > imported > inferred, and a weaker claim leaves the standing value in place and reports the field in `held[]` rather than failing. That is the whole of why a write can return 200 and not take. WITH it, this write wins regardless of what it is overruling, INCLUDING a value a person confirmed, so an agent that sets it by default has switched the provenance mechanism off. Set it per write, when the caller knows its claim supersedes what is there."
                  },
                  "title": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 300
                  },
                  "dueAt": {
                    "type": "string"
                  },
                  "assigneeActorId": {
                    "type": "string",
                    "description": "Only tasks assigned to this actor. The actor id comes back on every change and in the schema call for the caller themselves."
                  },
                  "priority": {
                    "type": "string",
                    "enum": [
                      "low",
                      "normal",
                      "high"
                    ]
                  },
                  "companyIds": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "maxItems": 100
                  },
                  "contactIds": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "maxItems": 100
                  },
                  "opportunityIds": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "maxItems": 100
                  },
                  "customFields": {
                    "type": "object",
                    "additionalProperties": {
                      "anyOf": [
                        {
                          "type": "string",
                          "maxLength": 2000
                        },
                        {
                          "type": "integer"
                        },
                        {
                          "type": "boolean"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "description": "Values for fields this workspace defined, keyed by the field's key. Read the schema first: a key that is not declared is REFUSED, with the available keys in the error, rather than stored where nobody will find it. Send null to clear one."
                  }
                },
                "required": [
                  "title"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "record": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "title": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "open",
                            "done",
                            "cancelled"
                          ]
                        },
                        "assigneeActorId": {
                          "type": "string"
                        },
                        "assignee": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string"
                            },
                            "kind": {
                              "type": "string",
                              "enum": [
                                "human",
                                "agent",
                                "api_token",
                                "system"
                              ]
                            },
                            "label": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "id",
                            "kind",
                            "label"
                          ],
                          "additionalProperties": true
                        },
                        "dueAt": {
                          "type": "string"
                        },
                        "priority": {
                          "type": "string",
                          "enum": [
                            "low",
                            "normal",
                            "high"
                          ]
                        },
                        "completedAt": {
                          "type": "string"
                        },
                        "ownerActorId": {
                          "type": "string"
                        },
                        "version": {
                          "type": "integer"
                        },
                        "links": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "objectType": {
                                "type": "string",
                                "enum": [
                                  "company",
                                  "contact",
                                  "opportunity"
                                ]
                              },
                              "objectId": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "objectType",
                              "objectId"
                            ],
                            "additionalProperties": true
                          }
                        },
                        "createdAt": {
                          "type": "string"
                        },
                        "updatedAt": {
                          "type": "string"
                        },
                        "archivedAt": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id",
                        "title",
                        "status",
                        "assigneeActorId",
                        "dueAt",
                        "priority",
                        "completedAt",
                        "ownerActorId",
                        "version",
                        "links",
                        "createdAt",
                        "updatedAt",
                        "archivedAt"
                      ],
                      "additionalProperties": true,
                      "description": "The record as it stands after the write. Absent on a dry run, which commits nothing."
                    },
                    "mutation": {
                      "type": "object",
                      "properties": {
                        "mutationId": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "created",
                            "updated",
                            "matched",
                            "archived",
                            "merged",
                            "reverted",
                            "noop"
                          ],
                          "description": "What the write did. `noop` means it was accepted and changed nothing, because every value it carried already matched what was stored. IT IS NOT METERED: a noop does not count against your monthly change allowance, so a nightly sync that finds nothing new costs nothing. Neither does a write that only REDUCES what a workspace holds. `matched` means an upsert found an existing record on real identity evidence rather than creating a second one; `reverted` and `merged` are the undo and duplicate paths, and both are ordinary writes that count."
                        },
                        "targetId": {
                          "type": "string"
                        },
                        "record": {},
                        "changes": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "before": {},
                              "after": {}
                            },
                            "required": [
                              "field"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "held": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "kept": {},
                              "proposed": {},
                              "standing": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "incoming": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "actorId": {
                                "type": "string",
                                "minLength": 1
                              },
                              "assertedAt": {
                                "type": "string",
                                "minLength": 1
                              }
                            },
                            "required": [
                              "field",
                              "standing",
                              "incoming",
                              "actorId",
                              "assertedAt"
                            ],
                            "additionalProperties": false
                          },
                          "description": "Fields this write asked to change and did not, because the value standing in the record was asserted more strongly. THIS IS WHY A WRITE CAN RETURN 200 AND CHANGE NOTHING, and a caller that ignores it will believe it wrote something it did not. Precedence is confirmed > user_supplied > observed > imported > inferred, and a write carrying no `assertionKind` is weakest of all. Each entry reports the field, what the record still says, what you proposed, which claim won, and who made it. Send `overrideStanding` to write anyway, per write, when your claim really does supersede theirs."
                        },
                        "matchedBy": {
                          "type": "string",
                          "enum": [
                            "email",
                            "domain",
                            "external_id",
                            "idempotency_key",
                            "explicit_id"
                          ]
                        },
                        "reversible": {
                          "type": "boolean"
                        },
                        "replayed": {
                          "type": "boolean"
                        },
                        "dryRun": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "mutationId",
                        "status",
                        "reversible"
                      ],
                      "additionalProperties": false,
                      "description": "What the write actually DID. Read `status` before you conclude anything: `noop` means it was accepted and changed nothing. `changes` is the field-level diff that was recorded, and `held` names any field whose stored value outranked the claim you sent and therefore did not move. A 200 with an empty `changes` and a populated `held` is the product working, not the call failing."
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "mutation",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "A product quota is spent, or the subscription is not active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A conflict the caller can resolve: a stale expectedVersion, an idempotency key reused for different input, an ambiguous or duplicate identity, or a merge that no longer applies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The body, or a single record inside it, exceeds its bound.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "507": {
            "description": "The workspace is at its storage ceiling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/tasks/{id}": {
      "get": {
        "summary": "Read one task",
        "description": "One task by its id, including the records it is linked to. A task can hang off several records at once, which is how a follow-up that concerns two accounts stays visible on both.",
        "tags": [
          "tasks"
        ],
        "operationId": "get_v1_tasks__id_",
        "x-indraft-capability": "crm:read",
        "x-indraft-scopes": [
          "crm:read",
          "crm:write",
          "crm:configure",
          "crm:admin",
          "crm:revert",
          "data:export"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The task id, as returned by the call that created or matched it.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "task": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "title": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "open",
                            "done",
                            "cancelled"
                          ]
                        },
                        "assigneeActorId": {
                          "type": "string"
                        },
                        "assignee": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string"
                            },
                            "kind": {
                              "type": "string",
                              "enum": [
                                "human",
                                "agent",
                                "api_token",
                                "system"
                              ]
                            },
                            "label": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "id",
                            "kind",
                            "label"
                          ],
                          "additionalProperties": true
                        },
                        "dueAt": {
                          "type": "string"
                        },
                        "priority": {
                          "type": "string",
                          "enum": [
                            "low",
                            "normal",
                            "high"
                          ]
                        },
                        "completedAt": {
                          "type": "string"
                        },
                        "ownerActorId": {
                          "type": "string"
                        },
                        "version": {
                          "type": "integer"
                        },
                        "links": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "objectType": {
                                "type": "string",
                                "enum": [
                                  "company",
                                  "contact",
                                  "opportunity"
                                ]
                              },
                              "objectId": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "objectType",
                              "objectId"
                            ],
                            "additionalProperties": true
                          }
                        },
                        "createdAt": {
                          "type": "string"
                        },
                        "updatedAt": {
                          "type": "string"
                        },
                        "archivedAt": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id",
                        "title",
                        "status",
                        "assigneeActorId",
                        "dueAt",
                        "priority",
                        "completedAt",
                        "ownerActorId",
                        "version",
                        "links",
                        "createdAt",
                        "updatedAt",
                        "archivedAt"
                      ],
                      "additionalProperties": true
                    },
                    "derived": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string"
                          },
                          "value": {
                            "type": "integer"
                          },
                          "unit": {
                            "type": "string",
                            "enum": [
                              "minor_units",
                              "days"
                            ]
                          },
                          "currency": {
                            "type": "string"
                          },
                          "inputs": {
                            "type": "object",
                            "additionalProperties": {
                              "anyOf": [
                                {
                                  "type": "integer"
                                },
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            }
                          }
                        },
                        "required": [
                          "name",
                          "value",
                          "unit",
                          "currency",
                          "inputs"
                        ],
                        "additionalProperties": true
                      }
                    },
                    "standing": {
                      "type": "object",
                      "additionalProperties": {
                        "type": "object",
                        "properties": {
                          "assertionKind": {
                            "type": "string",
                            "enum": [
                              "observed",
                              "inferred",
                              "imported",
                              "user_supplied",
                              "confirmed"
                            ]
                          },
                          "actorId": {
                            "type": "string"
                          },
                          "assertedAt": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "assertionKind",
                          "actorId",
                          "assertedAt"
                        ],
                        "additionalProperties": true
                      },
                      "description": "Per field: which kind of claim is standing on it, who asserted it, and when. This is the provenance the product is sold on, keyed by column name so it lines up with `changes`, `held[]` and the unconfirmed queue. `confirmed` means a person checked it and outranks everything an agent can assert; `inferred` is the weakest and is what an agent's own conclusion should carry. A write whose claim ranks below what is here is held rather than applied."
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "task",
                    "derived",
                    "standing",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such record, or it belongs to another workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "summary": "Correct a task",
        "description": "Correct a task that already exists: its title, when it is due, who owns it, or how urgent it is. Only the fields you send move, and an explicit null clears a due date or unassigns it. Use this when you got a detail wrong; use complete_task when the work is done and cancel_task when it is not going to be. A task that is already done or cancelled is refused rather than edited, because it records what happened.",
        "tags": [
          "tasks"
        ],
        "operationId": "patch_v1_tasks__id_",
        "x-indraft-capability": "crm:write",
        "x-indraft-scopes": [
          "crm:write",
          "crm:admin"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The task id, as returned by the call that created or matched it.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "idempotencyKey": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 200,
                    "description": "Your own name for this write, so retrying it cannot do it twice. Send the same key again and you get the SAME result back rather than a second record, which is what makes a re-run safe after a timeout you never saw the answer to. Derive it from what the write is about, not from the clock: `nightly-sync-halden` retries correctly and a timestamp does not."
                  },
                  "expectedVersion": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "The version you read before deciding to write. If the record has moved since, the write is refused instead of overwriting whatever changed. Send it whenever you read, reasoned, and then wrote: without it the last writer wins and neither of you finds out."
                  },
                  "sourceId": {
                    "type": "string",
                    "description": "The recorded source this claim came from, if one exists. It attaches evidence to the write, so a person reading the field later can see where it came from rather than only who sent it."
                  },
                  "assertionKind": {
                    "type": "string",
                    "enum": [
                      "observed",
                      "inferred",
                      "imported",
                      "user_supplied"
                    ],
                    "description": "HOW YOU KNOW. This is the field the product is built around, so say what is true rather than what is strongest: `observed` you saw it stated directly, `imported` it came from a file or another system, `inferred` you worked it out, `user_supplied` a person told you in so many words. They rank, weakest first: inferred < imported < observed < user_supplied < confirmed. A weaker claim does not overwrite a stronger one; it is reported in `held[]` and the stored value stands, so an unattended re-run converges instead of eroding what somebody checked. `confirmed` is not accepted here: it means a person checked the value, and only a signed-in person can set it."
                  },
                  "attributionLabel": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120,
                    "description": "A short name for the work this write belongs to, shown beside the actor so one credential can distinguish separate jobs. It is recorded as CALLER-SUPPLIED and grants nothing: it changes no permission, no idempotency scope and no quota."
                  },
                  "dryRun": {
                    "type": "boolean",
                    "description": "Report what this write WOULD do and commit nothing. The response carries the same change list, held fields and refusals as the real call, so it is the way to check a risky write, or a whole import, before it lands. Nothing is metered."
                  },
                  "overrideStanding": {
                    "type": "boolean",
                    "description": "Apply this write even when the value standing in the record was asserted more strongly than this one. Absent means no, which is the safe answer for a re-run. WITHOUT IT, a write can be accepted and change nothing: precedence is confirmed > user_supplied > observed > imported > inferred, and a weaker claim leaves the standing value in place and reports the field in `held[]` rather than failing. That is the whole of why a write can return 200 and not take. WITH it, this write wins regardless of what it is overruling, INCLUDING a value a person confirmed, so an agent that sets it by default has switched the provenance mechanism off. Set it per write, when the caller knows its claim supersedes what is there."
                  },
                  "title": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 300
                  },
                  "dueAt": {
                    "type": "string"
                  },
                  "assigneeActorId": {
                    "type": "string"
                  },
                  "priority": {
                    "type": "string",
                    "enum": [
                      "low",
                      "normal",
                      "high"
                    ]
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "record": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "title": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "open",
                            "done",
                            "cancelled"
                          ]
                        },
                        "assigneeActorId": {
                          "type": "string"
                        },
                        "assignee": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string"
                            },
                            "kind": {
                              "type": "string",
                              "enum": [
                                "human",
                                "agent",
                                "api_token",
                                "system"
                              ]
                            },
                            "label": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "id",
                            "kind",
                            "label"
                          ],
                          "additionalProperties": true
                        },
                        "dueAt": {
                          "type": "string"
                        },
                        "priority": {
                          "type": "string",
                          "enum": [
                            "low",
                            "normal",
                            "high"
                          ]
                        },
                        "completedAt": {
                          "type": "string"
                        },
                        "ownerActorId": {
                          "type": "string"
                        },
                        "version": {
                          "type": "integer"
                        },
                        "links": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "objectType": {
                                "type": "string",
                                "enum": [
                                  "company",
                                  "contact",
                                  "opportunity"
                                ]
                              },
                              "objectId": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "objectType",
                              "objectId"
                            ],
                            "additionalProperties": true
                          }
                        },
                        "createdAt": {
                          "type": "string"
                        },
                        "updatedAt": {
                          "type": "string"
                        },
                        "archivedAt": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id",
                        "title",
                        "status",
                        "assigneeActorId",
                        "dueAt",
                        "priority",
                        "completedAt",
                        "ownerActorId",
                        "version",
                        "links",
                        "createdAt",
                        "updatedAt",
                        "archivedAt"
                      ],
                      "additionalProperties": true,
                      "description": "The record as it stands after the write. Absent on a dry run, which commits nothing."
                    },
                    "mutation": {
                      "type": "object",
                      "properties": {
                        "mutationId": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "created",
                            "updated",
                            "matched",
                            "archived",
                            "merged",
                            "reverted",
                            "noop"
                          ],
                          "description": "What the write did. `noop` means it was accepted and changed nothing, because every value it carried already matched what was stored. IT IS NOT METERED: a noop does not count against your monthly change allowance, so a nightly sync that finds nothing new costs nothing. Neither does a write that only REDUCES what a workspace holds. `matched` means an upsert found an existing record on real identity evidence rather than creating a second one; `reverted` and `merged` are the undo and duplicate paths, and both are ordinary writes that count."
                        },
                        "targetId": {
                          "type": "string"
                        },
                        "record": {},
                        "changes": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "before": {},
                              "after": {}
                            },
                            "required": [
                              "field"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "held": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "kept": {},
                              "proposed": {},
                              "standing": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "incoming": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "actorId": {
                                "type": "string",
                                "minLength": 1
                              },
                              "assertedAt": {
                                "type": "string",
                                "minLength": 1
                              }
                            },
                            "required": [
                              "field",
                              "standing",
                              "incoming",
                              "actorId",
                              "assertedAt"
                            ],
                            "additionalProperties": false
                          },
                          "description": "Fields this write asked to change and did not, because the value standing in the record was asserted more strongly. THIS IS WHY A WRITE CAN RETURN 200 AND CHANGE NOTHING, and a caller that ignores it will believe it wrote something it did not. Precedence is confirmed > user_supplied > observed > imported > inferred, and a write carrying no `assertionKind` is weakest of all. Each entry reports the field, what the record still says, what you proposed, which claim won, and who made it. Send `overrideStanding` to write anyway, per write, when your claim really does supersede theirs."
                        },
                        "matchedBy": {
                          "type": "string",
                          "enum": [
                            "email",
                            "domain",
                            "external_id",
                            "idempotency_key",
                            "explicit_id"
                          ]
                        },
                        "reversible": {
                          "type": "boolean"
                        },
                        "replayed": {
                          "type": "boolean"
                        },
                        "dryRun": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "mutationId",
                        "status",
                        "reversible"
                      ],
                      "additionalProperties": false,
                      "description": "What the write actually DID. Read `status` before you conclude anything: `noop` means it was accepted and changed nothing. `changes` is the field-level diff that was recorded, and `held` names any field whose stored value outranked the claim you sent and therefore did not move. A 200 with an empty `changes` and a populated `held` is the product working, not the call failing."
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "mutation",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "A product quota is spent, or the subscription is not active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such record, or it belongs to another workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A conflict the caller can resolve: a stale expectedVersion, an idempotency key reused for different input, an ambiguous or duplicate identity, or a merge that no longer applies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The body, or a single record inside it, exceeds its bound.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "507": {
            "description": "The workspace is at its storage ceiling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/tasks/{id}/complete": {
      "post": {
        "summary": "Complete a task",
        "description": "Mark a task done. Completing a completed task is a no-op, not a second completion.",
        "tags": [
          "tasks"
        ],
        "operationId": "post_v1_tasks__id__complete",
        "x-indraft-capability": "crm:write",
        "x-indraft-scopes": [
          "crm:write",
          "crm:admin"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The task id, as returned by the call that created or matched it.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "idempotencyKey": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 200,
                    "description": "Your own name for this write, so retrying it cannot do it twice. Send the same key again and you get the SAME result back rather than a second record, which is what makes a re-run safe after a timeout you never saw the answer to. Derive it from what the write is about, not from the clock: `nightly-sync-halden` retries correctly and a timestamp does not."
                  },
                  "expectedVersion": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "The version you read before deciding to write. If the record has moved since, the write is refused instead of overwriting whatever changed. Send it whenever you read, reasoned, and then wrote: without it the last writer wins and neither of you finds out."
                  },
                  "sourceId": {
                    "type": "string",
                    "description": "The recorded source this claim came from, if one exists. It attaches evidence to the write, so a person reading the field later can see where it came from rather than only who sent it."
                  },
                  "assertionKind": {
                    "type": "string",
                    "enum": [
                      "observed",
                      "inferred",
                      "imported",
                      "user_supplied"
                    ],
                    "description": "HOW YOU KNOW. This is the field the product is built around, so say what is true rather than what is strongest: `observed` you saw it stated directly, `imported` it came from a file or another system, `inferred` you worked it out, `user_supplied` a person told you in so many words. They rank, weakest first: inferred < imported < observed < user_supplied < confirmed. A weaker claim does not overwrite a stronger one; it is reported in `held[]` and the stored value stands, so an unattended re-run converges instead of eroding what somebody checked. `confirmed` is not accepted here: it means a person checked the value, and only a signed-in person can set it."
                  },
                  "attributionLabel": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120,
                    "description": "A short name for the work this write belongs to, shown beside the actor so one credential can distinguish separate jobs. It is recorded as CALLER-SUPPLIED and grants nothing: it changes no permission, no idempotency scope and no quota."
                  },
                  "dryRun": {
                    "type": "boolean",
                    "description": "Report what this write WOULD do and commit nothing. The response carries the same change list, held fields and refusals as the real call, so it is the way to check a risky write, or a whole import, before it lands. Nothing is metered."
                  },
                  "overrideStanding": {
                    "type": "boolean",
                    "description": "Apply this write even when the value standing in the record was asserted more strongly than this one. Absent means no, which is the safe answer for a re-run. WITHOUT IT, a write can be accepted and change nothing: precedence is confirmed > user_supplied > observed > imported > inferred, and a weaker claim leaves the standing value in place and reports the field in `held[]` rather than failing. That is the whole of why a write can return 200 and not take. WITH it, this write wins regardless of what it is overruling, INCLUDING a value a person confirmed, so an agent that sets it by default has switched the provenance mechanism off. Set it per write, when the caller knows its claim supersedes what is there."
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "record": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "title": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "open",
                            "done",
                            "cancelled"
                          ]
                        },
                        "assigneeActorId": {
                          "type": "string"
                        },
                        "assignee": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string"
                            },
                            "kind": {
                              "type": "string",
                              "enum": [
                                "human",
                                "agent",
                                "api_token",
                                "system"
                              ]
                            },
                            "label": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "id",
                            "kind",
                            "label"
                          ],
                          "additionalProperties": true
                        },
                        "dueAt": {
                          "type": "string"
                        },
                        "priority": {
                          "type": "string",
                          "enum": [
                            "low",
                            "normal",
                            "high"
                          ]
                        },
                        "completedAt": {
                          "type": "string"
                        },
                        "ownerActorId": {
                          "type": "string"
                        },
                        "version": {
                          "type": "integer"
                        },
                        "links": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "objectType": {
                                "type": "string",
                                "enum": [
                                  "company",
                                  "contact",
                                  "opportunity"
                                ]
                              },
                              "objectId": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "objectType",
                              "objectId"
                            ],
                            "additionalProperties": true
                          }
                        },
                        "createdAt": {
                          "type": "string"
                        },
                        "updatedAt": {
                          "type": "string"
                        },
                        "archivedAt": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id",
                        "title",
                        "status",
                        "assigneeActorId",
                        "dueAt",
                        "priority",
                        "completedAt",
                        "ownerActorId",
                        "version",
                        "links",
                        "createdAt",
                        "updatedAt",
                        "archivedAt"
                      ],
                      "additionalProperties": true,
                      "description": "The record as it stands after the write. Absent on a dry run, which commits nothing."
                    },
                    "mutation": {
                      "type": "object",
                      "properties": {
                        "mutationId": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "created",
                            "updated",
                            "matched",
                            "archived",
                            "merged",
                            "reverted",
                            "noop"
                          ],
                          "description": "What the write did. `noop` means it was accepted and changed nothing, because every value it carried already matched what was stored. IT IS NOT METERED: a noop does not count against your monthly change allowance, so a nightly sync that finds nothing new costs nothing. Neither does a write that only REDUCES what a workspace holds. `matched` means an upsert found an existing record on real identity evidence rather than creating a second one; `reverted` and `merged` are the undo and duplicate paths, and both are ordinary writes that count."
                        },
                        "targetId": {
                          "type": "string"
                        },
                        "record": {},
                        "changes": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "before": {},
                              "after": {}
                            },
                            "required": [
                              "field"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "held": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "kept": {},
                              "proposed": {},
                              "standing": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "incoming": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "actorId": {
                                "type": "string",
                                "minLength": 1
                              },
                              "assertedAt": {
                                "type": "string",
                                "minLength": 1
                              }
                            },
                            "required": [
                              "field",
                              "standing",
                              "incoming",
                              "actorId",
                              "assertedAt"
                            ],
                            "additionalProperties": false
                          },
                          "description": "Fields this write asked to change and did not, because the value standing in the record was asserted more strongly. THIS IS WHY A WRITE CAN RETURN 200 AND CHANGE NOTHING, and a caller that ignores it will believe it wrote something it did not. Precedence is confirmed > user_supplied > observed > imported > inferred, and a write carrying no `assertionKind` is weakest of all. Each entry reports the field, what the record still says, what you proposed, which claim won, and who made it. Send `overrideStanding` to write anyway, per write, when your claim really does supersede theirs."
                        },
                        "matchedBy": {
                          "type": "string",
                          "enum": [
                            "email",
                            "domain",
                            "external_id",
                            "idempotency_key",
                            "explicit_id"
                          ]
                        },
                        "reversible": {
                          "type": "boolean"
                        },
                        "replayed": {
                          "type": "boolean"
                        },
                        "dryRun": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "mutationId",
                        "status",
                        "reversible"
                      ],
                      "additionalProperties": false,
                      "description": "What the write actually DID. Read `status` before you conclude anything: `noop` means it was accepted and changed nothing. `changes` is the field-level diff that was recorded, and `held` names any field whose stored value outranked the claim you sent and therefore did not move. A 200 with an empty `changes` and a populated `held` is the product working, not the call failing."
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "mutation",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "A product quota is spent, or the subscription is not active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such record, or it belongs to another workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A conflict the caller can resolve: a stale expectedVersion, an idempotency key reused for different input, an ambiguous or duplicate identity, or a merge that no longer applies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The body, or a single record inside it, exceeds its bound.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "507": {
            "description": "The workspace is at its storage ceiling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/aggregate": {
      "get": {
        "summary": "Count, sum, average, min or max, optionally grouped",
        "description": "Count, sum, average, min or max over one object type, grouped by up to TWO dimensions. Answers 'how is the quarter going', 'pipeline by owner by quarter', 'pipeline by customer segment' and 'how many have no owner' in ONE call, with the database doing the arithmetic. Use this instead of paging records and adding them up yourself: it is one call rather than hundreds, and the number is computed rather than estimated. Filters use the same field:op:value language as the list tools. groupBy takes one dimension or an array of two, and a dimension written as hop.field crosses one declared relationship, so opportunity can group by company.industry. Dates must be bucketed to day, week, month, quarter or year, and quarter and year follow the workspace's own fiscal calendar, which the answer states. Too many groups is refused rather than truncated, and the cap applies to the PRODUCT of two dimensions, because a truncated total reads exactly like a real one. convertTo totals across currencies at a rate this workspace STORED and names the rate it used; a currency with no stored rate is refused rather than converted, because Indraft never invents one. For weighted pipeline, reduce the DERIVED field weighted_amount_minor: 'sum weighted_amount_minor where status is open' is your weighted pipeline in one call, computed by the database as amount times probability, and it obeys the currency rule exactly as the unweighted amount does. Derived fields can be reduced and not grouped by, because they are measures rather than dimensions. get_crm_schema lists the dimensions, the hops, the derived fields, the fiscal calendar and the stored rates.",
        "tags": [
          "reporting"
        ],
        "operationId": "get_v1_aggregate",
        "x-indraft-capability": "crm:read",
        "x-indraft-scopes": [
          "crm:read",
          "crm:write",
          "crm:configure",
          "crm:admin",
          "crm:revert",
          "data:export"
        ],
        "parameters": [
          {
            "name": "objectType",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64,
              "pattern": "^[a-z][a-z0-9_]*$",
              "description": "What is being counted: a canonical type, or the key of a type this workspace defined."
            }
          },
          {
            "name": "function",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "count",
                "sum",
                "avg",
                "min",
                "max"
              ],
              "description": "The reduction. Count needs no field; the rest need one that carries a number."
            }
          },
          {
            "name": "field",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64,
              "description": "The field to reduce. Refused when the function needs one and the field cannot carry it, rather than returning zero."
            }
          },
          {
            "name": "groupBy",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 130
                },
                {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 130
                  }
                }
              ],
              "description": "A dimension to group by, repeatable for a second one. Only dimensions an index serves, and a request for one that is not names every dimension that is, including those one hop away on a related record."
            }
          },
          {
            "name": "bucket",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "day",
                "week",
                "month",
                "quarter",
                "year"
              ],
              "description": "How to cut a date dimension: day, week, month or quarter. Required when grouping by a date, because a raw instant produces one group per record, which is a list wearing an aggregate's clothes."
            }
          },
          {
            "name": "convertTo",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^[A-Z]{3}$",
              "description": "Express the total in one currency. Refused unless this workspace has asserted a rate for every currency in the answer: Indraft never invents a rate, and a converted number nobody chose is worse than no number."
            }
          },
          {
            "name": "rateAsOf",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
              "description": "Which asserted rates to convert at. Absent means the latest, which is what a live report wants and what a historical one must not use."
            }
          },
          {
            "name": "includeArchived",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "Include archived rows. Off by default, because a list is what you are working on and history is somewhere you go deliberately."
            }
          },
          {
            "name": "filter",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 560
                },
                {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 560
                  },
                  "maxItems": 8
                }
              ],
              "description": "Predicates, all of which must hold, written field:op:value. Only fields an index serves are accepted, and asking for one that is not names the ones that are."
            }
          },
          {
            "name": "or",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 560
                },
                {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 560
                  },
                  "maxItems": 4
                }
              ],
              "description": "Alternatives, ORed with each other and ANDed with filter. One level and never a tree: owned by me or owned by nobody is the question people ask, and anything deeper has a cost the caller cannot read off it."
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 65,
              "description": "A field to order by, with a leading minus for descending. Indexed fields only, for the same reason as filter."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "objectType": {
                      "type": "string"
                    },
                    "function": {
                      "type": "string",
                      "enum": [
                        "count",
                        "sum",
                        "avg",
                        "min",
                        "max"
                      ]
                    },
                    "field": {
                      "type": "string"
                    },
                    "matched": {
                      "type": "integer"
                    },
                    "value": {
                      "anyOf": [
                        {
                          "type": "integer"
                        },
                        {
                          "type": "string"
                        }
                      ]
                    },
                    "groupBy": {
                      "type": "object",
                      "properties": {
                        "field": {
                          "type": "string"
                        },
                        "bucket": {
                          "type": "string",
                          "enum": [
                            "day",
                            "week",
                            "month",
                            "quarter",
                            "year"
                          ]
                        },
                        "overlapping": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "field",
                        "bucket",
                        "overlapping"
                      ],
                      "additionalProperties": true
                    },
                    "dimensions": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "field": {
                            "type": "string"
                          },
                          "bucket": {
                            "type": "string",
                            "enum": [
                              "day",
                              "week",
                              "month",
                              "quarter",
                              "year"
                            ]
                          },
                          "overlapping": {
                            "type": "boolean"
                          },
                          "via": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "field",
                          "bucket",
                          "overlapping",
                          "via"
                        ],
                        "additionalProperties": true
                      }
                    },
                    "groups": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "key": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "integer"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "label": {
                            "type": "string"
                          },
                          "value": {
                            "anyOf": [
                              {
                                "type": "integer"
                              },
                              {
                                "type": "string"
                              }
                            ]
                          },
                          "count": {
                            "type": "integer"
                          },
                          "keys": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "field": {
                                  "type": "string"
                                },
                                "bucket": {
                                  "type": "string",
                                  "enum": [
                                    "day",
                                    "week",
                                    "month",
                                    "quarter",
                                    "year"
                                  ]
                                },
                                "key": {
                                  "anyOf": [
                                    {
                                      "type": "string"
                                    },
                                    {
                                      "type": "integer"
                                    },
                                    {
                                      "type": "null"
                                    }
                                  ]
                                },
                                "label": {
                                  "type": "string"
                                }
                              },
                              "required": [
                                "field",
                                "bucket",
                                "key",
                                "label"
                              ],
                              "additionalProperties": true
                            }
                          }
                        },
                        "required": [
                          "key",
                          "label",
                          "value",
                          "count"
                        ],
                        "additionalProperties": true
                      }
                    },
                    "calendar": {
                      "type": "object",
                      "properties": {
                        "fiscalYearStartMonth": {
                          "type": "integer",
                          "minimum": 1,
                          "maximum": 12
                        },
                        "isCalendarYear": {
                          "type": "boolean"
                        },
                        "note": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "fiscalYearStartMonth",
                        "isCalendarYear",
                        "note"
                      ],
                      "additionalProperties": true
                    },
                    "conversion": {
                      "type": "object",
                      "properties": {
                        "to": {
                          "type": "string"
                        },
                        "asOf": {
                          "type": "string"
                        },
                        "rates": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string"
                              },
                              "from": {
                                "type": "string"
                              },
                              "to": {
                                "type": "string"
                              },
                              "ratePpm": {
                                "type": "integer"
                              },
                              "effectiveFrom": {
                                "type": "string"
                              },
                              "sourceLabel": {
                                "type": "string"
                              },
                              "assertedByActorId": {
                                "type": "string"
                              },
                              "assertionKind": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "id",
                              "from",
                              "to",
                              "ratePpm",
                              "effectiveFrom",
                              "sourceLabel",
                              "assertedByActorId",
                              "assertionKind"
                            ],
                            "additionalProperties": true
                          }
                        }
                      },
                      "required": [
                        "to",
                        "asOf",
                        "rates"
                      ],
                      "additionalProperties": true
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "objectType",
                    "function",
                    "field",
                    "matched",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/tasks/{id}/cancel": {
      "post": {
        "summary": "Call a task off, which is not the same as completing it",
        "description": "Call a task off. Different from completing it: cancelled means the work was not done and is not going to be, and the ledger and every report built on it record which. Use this for a task you created in error or that no longer applies.",
        "tags": [
          "tasks"
        ],
        "operationId": "post_v1_tasks__id__cancel",
        "x-indraft-capability": "crm:write",
        "x-indraft-scopes": [
          "crm:write",
          "crm:admin"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The task id, as returned by the call that created or matched it.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "idempotencyKey": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 200,
                    "description": "Your own name for this write, so retrying it cannot do it twice. Send the same key again and you get the SAME result back rather than a second record, which is what makes a re-run safe after a timeout you never saw the answer to. Derive it from what the write is about, not from the clock: `nightly-sync-halden` retries correctly and a timestamp does not."
                  },
                  "expectedVersion": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "The version you read before deciding to write. If the record has moved since, the write is refused instead of overwriting whatever changed. Send it whenever you read, reasoned, and then wrote: without it the last writer wins and neither of you finds out."
                  },
                  "sourceId": {
                    "type": "string",
                    "description": "The recorded source this claim came from, if one exists. It attaches evidence to the write, so a person reading the field later can see where it came from rather than only who sent it."
                  },
                  "assertionKind": {
                    "type": "string",
                    "enum": [
                      "observed",
                      "inferred",
                      "imported",
                      "user_supplied"
                    ],
                    "description": "HOW YOU KNOW. This is the field the product is built around, so say what is true rather than what is strongest: `observed` you saw it stated directly, `imported` it came from a file or another system, `inferred` you worked it out, `user_supplied` a person told you in so many words. They rank, weakest first: inferred < imported < observed < user_supplied < confirmed. A weaker claim does not overwrite a stronger one; it is reported in `held[]` and the stored value stands, so an unattended re-run converges instead of eroding what somebody checked. `confirmed` is not accepted here: it means a person checked the value, and only a signed-in person can set it."
                  },
                  "attributionLabel": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120,
                    "description": "A short name for the work this write belongs to, shown beside the actor so one credential can distinguish separate jobs. It is recorded as CALLER-SUPPLIED and grants nothing: it changes no permission, no idempotency scope and no quota."
                  },
                  "dryRun": {
                    "type": "boolean",
                    "description": "Report what this write WOULD do and commit nothing. The response carries the same change list, held fields and refusals as the real call, so it is the way to check a risky write, or a whole import, before it lands. Nothing is metered."
                  },
                  "overrideStanding": {
                    "type": "boolean",
                    "description": "Apply this write even when the value standing in the record was asserted more strongly than this one. Absent means no, which is the safe answer for a re-run. WITHOUT IT, a write can be accepted and change nothing: precedence is confirmed > user_supplied > observed > imported > inferred, and a weaker claim leaves the standing value in place and reports the field in `held[]` rather than failing. That is the whole of why a write can return 200 and not take. WITH it, this write wins regardless of what it is overruling, INCLUDING a value a person confirmed, so an agent that sets it by default has switched the provenance mechanism off. Set it per write, when the caller knows its claim supersedes what is there."
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "record": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "title": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "open",
                            "done",
                            "cancelled"
                          ]
                        },
                        "assigneeActorId": {
                          "type": "string"
                        },
                        "assignee": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string"
                            },
                            "kind": {
                              "type": "string",
                              "enum": [
                                "human",
                                "agent",
                                "api_token",
                                "system"
                              ]
                            },
                            "label": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "id",
                            "kind",
                            "label"
                          ],
                          "additionalProperties": true
                        },
                        "dueAt": {
                          "type": "string"
                        },
                        "priority": {
                          "type": "string",
                          "enum": [
                            "low",
                            "normal",
                            "high"
                          ]
                        },
                        "completedAt": {
                          "type": "string"
                        },
                        "ownerActorId": {
                          "type": "string"
                        },
                        "version": {
                          "type": "integer"
                        },
                        "links": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "objectType": {
                                "type": "string",
                                "enum": [
                                  "company",
                                  "contact",
                                  "opportunity"
                                ]
                              },
                              "objectId": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "objectType",
                              "objectId"
                            ],
                            "additionalProperties": true
                          }
                        },
                        "createdAt": {
                          "type": "string"
                        },
                        "updatedAt": {
                          "type": "string"
                        },
                        "archivedAt": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id",
                        "title",
                        "status",
                        "assigneeActorId",
                        "dueAt",
                        "priority",
                        "completedAt",
                        "ownerActorId",
                        "version",
                        "links",
                        "createdAt",
                        "updatedAt",
                        "archivedAt"
                      ],
                      "additionalProperties": true,
                      "description": "The record as it stands after the write. Absent on a dry run, which commits nothing."
                    },
                    "mutation": {
                      "type": "object",
                      "properties": {
                        "mutationId": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "created",
                            "updated",
                            "matched",
                            "archived",
                            "merged",
                            "reverted",
                            "noop"
                          ],
                          "description": "What the write did. `noop` means it was accepted and changed nothing, because every value it carried already matched what was stored. IT IS NOT METERED: a noop does not count against your monthly change allowance, so a nightly sync that finds nothing new costs nothing. Neither does a write that only REDUCES what a workspace holds. `matched` means an upsert found an existing record on real identity evidence rather than creating a second one; `reverted` and `merged` are the undo and duplicate paths, and both are ordinary writes that count."
                        },
                        "targetId": {
                          "type": "string"
                        },
                        "record": {},
                        "changes": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "before": {},
                              "after": {}
                            },
                            "required": [
                              "field"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "held": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "kept": {},
                              "proposed": {},
                              "standing": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "incoming": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "actorId": {
                                "type": "string",
                                "minLength": 1
                              },
                              "assertedAt": {
                                "type": "string",
                                "minLength": 1
                              }
                            },
                            "required": [
                              "field",
                              "standing",
                              "incoming",
                              "actorId",
                              "assertedAt"
                            ],
                            "additionalProperties": false
                          },
                          "description": "Fields this write asked to change and did not, because the value standing in the record was asserted more strongly. THIS IS WHY A WRITE CAN RETURN 200 AND CHANGE NOTHING, and a caller that ignores it will believe it wrote something it did not. Precedence is confirmed > user_supplied > observed > imported > inferred, and a write carrying no `assertionKind` is weakest of all. Each entry reports the field, what the record still says, what you proposed, which claim won, and who made it. Send `overrideStanding` to write anyway, per write, when your claim really does supersede theirs."
                        },
                        "matchedBy": {
                          "type": "string",
                          "enum": [
                            "email",
                            "domain",
                            "external_id",
                            "idempotency_key",
                            "explicit_id"
                          ]
                        },
                        "reversible": {
                          "type": "boolean"
                        },
                        "replayed": {
                          "type": "boolean"
                        },
                        "dryRun": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "mutationId",
                        "status",
                        "reversible"
                      ],
                      "additionalProperties": false,
                      "description": "What the write actually DID. Read `status` before you conclude anything: `noop` means it was accepted and changed nothing. `changes` is the field-level diff that was recorded, and `held` names any field whose stored value outranked the claim you sent and therefore did not move. A 200 with an empty `changes` and a populated `held` is the product working, not the call failing."
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "mutation",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "A product quota is spent, or the subscription is not active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such record, or it belongs to another workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A conflict the caller can resolve: a stale expectedVersion, an idempotency key reused for different input, an ambiguous or duplicate identity, or a merge that no longer applies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The body, or a single record inside it, exceeds its bound.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "507": {
            "description": "The workspace is at its storage ceiling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/custom-fields/{id}": {
      "delete": {
        "summary": "Retire a custom field definition, keeping the values already written",
        "description": "Retire a custom field definition. Values already written stay readable and exportable, because a field somebody stopped using is history rather than a mistake. The field stops appearing in the schema, stops accepting new values, and frees its quota slot.",
        "tags": [
          "custom-fields"
        ],
        "operationId": "delete_v1_custom_fields__id_",
        "x-indraft-capability": "crm:configure",
        "x-indraft-scopes": [
          "crm:configure",
          "crm:admin"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The custom field id, as returned by the call that created or matched it.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "archived": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "key": {
                          "type": "string"
                        },
                        "archivedAt": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id",
                        "key",
                        "archivedAt"
                      ],
                      "additionalProperties": true
                    },
                    "mutation": {
                      "type": "object",
                      "properties": {
                        "mutationId": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "created",
                            "updated",
                            "matched",
                            "archived",
                            "merged",
                            "reverted",
                            "noop"
                          ],
                          "description": "What the write did. `noop` means it was accepted and changed nothing, because every value it carried already matched what was stored. IT IS NOT METERED: a noop does not count against your monthly change allowance, so a nightly sync that finds nothing new costs nothing. Neither does a write that only REDUCES what a workspace holds. `matched` means an upsert found an existing record on real identity evidence rather than creating a second one; `reverted` and `merged` are the undo and duplicate paths, and both are ordinary writes that count."
                        },
                        "targetId": {
                          "type": "string"
                        },
                        "record": {},
                        "changes": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "before": {},
                              "after": {}
                            },
                            "required": [
                              "field"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "held": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "kept": {},
                              "proposed": {},
                              "standing": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "incoming": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "actorId": {
                                "type": "string",
                                "minLength": 1
                              },
                              "assertedAt": {
                                "type": "string",
                                "minLength": 1
                              }
                            },
                            "required": [
                              "field",
                              "standing",
                              "incoming",
                              "actorId",
                              "assertedAt"
                            ],
                            "additionalProperties": false
                          },
                          "description": "Fields this write asked to change and did not, because the value standing in the record was asserted more strongly. THIS IS WHY A WRITE CAN RETURN 200 AND CHANGE NOTHING, and a caller that ignores it will believe it wrote something it did not. Precedence is confirmed > user_supplied > observed > imported > inferred, and a write carrying no `assertionKind` is weakest of all. Each entry reports the field, what the record still says, what you proposed, which claim won, and who made it. Send `overrideStanding` to write anyway, per write, when your claim really does supersede theirs."
                        },
                        "matchedBy": {
                          "type": "string",
                          "enum": [
                            "email",
                            "domain",
                            "external_id",
                            "idempotency_key",
                            "explicit_id"
                          ]
                        },
                        "reversible": {
                          "type": "boolean"
                        },
                        "replayed": {
                          "type": "boolean"
                        },
                        "dryRun": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "mutationId",
                        "status",
                        "reversible"
                      ],
                      "additionalProperties": false
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "archived",
                    "mutation",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "A product quota is spent, or the subscription is not active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such record, or it belongs to another workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A conflict the caller can resolve: a stale expectedVersion, an idempotency key reused for different input, an ambiguous or duplicate identity, or a merge that no longer applies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "507": {
            "description": "The workspace is at its storage ceiling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/contacts/{id}/company": {
      "post": {
        "summary": "Attach a contact to a company, detach them, or set which is primary",
        "description": "Attach a contact to a company, detach them, or change which company is their primary one. A person may be at several companies or none, with at most one primary. Set unlink to true to detach: an affiliation added by mistake was otherwise permanent, and somebody who changed jobs kept the old employer forever.",
        "tags": [
          "contacts"
        ],
        "operationId": "post_v1_contacts__id__company",
        "x-indraft-capability": "crm:write",
        "x-indraft-scopes": [
          "crm:write",
          "crm:admin"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The contact id, as returned by the call that created or matched it.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "idempotencyKey": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 200,
                    "description": "Your own name for this write, so retrying it cannot do it twice. Send the same key again and you get the SAME result back rather than a second record, which is what makes a re-run safe after a timeout you never saw the answer to. Derive it from what the write is about, not from the clock: `nightly-sync-halden` retries correctly and a timestamp does not."
                  },
                  "expectedVersion": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "The version you read before deciding to write. If the record has moved since, the write is refused instead of overwriting whatever changed. Send it whenever you read, reasoned, and then wrote: without it the last writer wins and neither of you finds out."
                  },
                  "sourceId": {
                    "type": "string",
                    "description": "The recorded source this claim came from, if one exists. It attaches evidence to the write, so a person reading the field later can see where it came from rather than only who sent it."
                  },
                  "assertionKind": {
                    "type": "string",
                    "enum": [
                      "observed",
                      "inferred",
                      "imported",
                      "user_supplied"
                    ],
                    "description": "HOW YOU KNOW. This is the field the product is built around, so say what is true rather than what is strongest: `observed` you saw it stated directly, `imported` it came from a file or another system, `inferred` you worked it out, `user_supplied` a person told you in so many words. They rank, weakest first: inferred < imported < observed < user_supplied < confirmed. A weaker claim does not overwrite a stronger one; it is reported in `held[]` and the stored value stands, so an unattended re-run converges instead of eroding what somebody checked. `confirmed` is not accepted here: it means a person checked the value, and only a signed-in person can set it."
                  },
                  "attributionLabel": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120,
                    "description": "A short name for the work this write belongs to, shown beside the actor so one credential can distinguish separate jobs. It is recorded as CALLER-SUPPLIED and grants nothing: it changes no permission, no idempotency scope and no quota."
                  },
                  "dryRun": {
                    "type": "boolean",
                    "description": "Report what this write WOULD do and commit nothing. The response carries the same change list, held fields and refusals as the real call, so it is the way to check a risky write, or a whole import, before it lands. Nothing is metered."
                  },
                  "overrideStanding": {
                    "type": "boolean",
                    "description": "Apply this write even when the value standing in the record was asserted more strongly than this one. Absent means no, which is the safe answer for a re-run. WITHOUT IT, a write can be accepted and change nothing: precedence is confirmed > user_supplied > observed > imported > inferred, and a weaker claim leaves the standing value in place and reports the field in `held[]` rather than failing. That is the whole of why a write can return 200 and not take. WITH it, this write wins regardless of what it is overruling, INCLUDING a value a person confirmed, so an agent that sets it by default has switched the provenance mechanism off. Set it per write, when the caller knows its claim supersedes what is there."
                  },
                  "companyId": {
                    "type": "string",
                    "minLength": 1
                  },
                  "role": {
                    "type": "string",
                    "enum": [
                      "employee",
                      "founder",
                      "executive",
                      "advisor",
                      "other"
                    ]
                  },
                  "isPrimary": {
                    "type": "boolean"
                  },
                  "unlink": {
                    "type": "boolean"
                  }
                },
                "required": [
                  "companyId"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "record": {
                      "type": "object",
                      "properties": {
                        "contactId": {
                          "type": "string"
                        },
                        "primaryCompanyId": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "contactId",
                        "primaryCompanyId"
                      ],
                      "additionalProperties": true
                    },
                    "mutation": {
                      "type": "object",
                      "properties": {
                        "mutationId": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "created",
                            "updated",
                            "matched",
                            "archived",
                            "merged",
                            "reverted",
                            "noop"
                          ],
                          "description": "What the write did. `noop` means it was accepted and changed nothing, because every value it carried already matched what was stored. IT IS NOT METERED: a noop does not count against your monthly change allowance, so a nightly sync that finds nothing new costs nothing. Neither does a write that only REDUCES what a workspace holds. `matched` means an upsert found an existing record on real identity evidence rather than creating a second one; `reverted` and `merged` are the undo and duplicate paths, and both are ordinary writes that count."
                        },
                        "targetId": {
                          "type": "string"
                        },
                        "record": {},
                        "changes": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "before": {},
                              "after": {}
                            },
                            "required": [
                              "field"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "held": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "kept": {},
                              "proposed": {},
                              "standing": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "incoming": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "actorId": {
                                "type": "string",
                                "minLength": 1
                              },
                              "assertedAt": {
                                "type": "string",
                                "minLength": 1
                              }
                            },
                            "required": [
                              "field",
                              "standing",
                              "incoming",
                              "actorId",
                              "assertedAt"
                            ],
                            "additionalProperties": false
                          },
                          "description": "Fields this write asked to change and did not, because the value standing in the record was asserted more strongly. THIS IS WHY A WRITE CAN RETURN 200 AND CHANGE NOTHING, and a caller that ignores it will believe it wrote something it did not. Precedence is confirmed > user_supplied > observed > imported > inferred, and a write carrying no `assertionKind` is weakest of all. Each entry reports the field, what the record still says, what you proposed, which claim won, and who made it. Send `overrideStanding` to write anyway, per write, when your claim really does supersede theirs."
                        },
                        "matchedBy": {
                          "type": "string",
                          "enum": [
                            "email",
                            "domain",
                            "external_id",
                            "idempotency_key",
                            "explicit_id"
                          ]
                        },
                        "reversible": {
                          "type": "boolean"
                        },
                        "replayed": {
                          "type": "boolean"
                        },
                        "dryRun": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "mutationId",
                        "status",
                        "reversible"
                      ],
                      "additionalProperties": false
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "record",
                    "mutation",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "A product quota is spent, or the subscription is not active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such record, or it belongs to another workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A conflict the caller can resolve: a stale expectedVersion, an idempotency key reused for different input, an ambiguous or duplicate identity, or a merge that no longer applies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The body, or a single record inside it, exceeds its bound.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "507": {
            "description": "The workspace is at its storage ceiling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/search": {
      "get": {
        "summary": "Search across the CRM",
        "description": "Search companies, contacts, opportunities, tasks, interaction summaries, and this workspace's own records by keyword. Matches whole words, prefixes, and substrings, so three characters from the middle of a name finds the record. Supports OR, a leading minus to exclude a term, a phrase in double quotes, and field qualifiers such as name:, domain: and email:. It finds records; it never decides that two records are the same one.",
        "tags": [
          "search"
        ],
        "operationId": "get_v1_search",
        "x-indraft-capability": "crm:read",
        "x-indraft-scopes": [
          "crm:read",
          "crm:write",
          "crm:configure",
          "crm:admin",
          "crm:revert",
          "data:export"
        ],
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "description": "The keyword. Matches whole words, prefixes and substrings, and supports OR, a leading minus to exclude, a quoted phrase, and field qualifiers. It finds records; it never decides two records are the same one."
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "description": "How many to return. The page bound is published in the schema call, and asking for more is refused rather than quietly truncated."
            }
          },
          {
            "name": "types",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "Which object types to search. Absent means all of them, including the types this workspace defined itself."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "results": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "type": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 48
                          },
                          "id": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "subtitle": {
                            "type": "string"
                          },
                          "matchedText": {
                            "type": "string"
                          },
                          "score": {
                            "type": "integer"
                          }
                        },
                        "required": [
                          "type",
                          "id",
                          "title",
                          "subtitle",
                          "score"
                        ],
                        "additionalProperties": true
                      }
                    },
                    "truncated": {
                      "type": "boolean"
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "results",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/duplicates": {
      "get": {
        "summary": "Propose pairs of records that look like the same record",
        "description": "Propose pairs of records that look like the same record, ranked by how alike their names are and whether they share a relationship. Works on companies, contacts, and a type this workspace defined. It PROPOSES only: nothing here merges anything, and the merge tools still require you to name both ids. Use it on a type with a declared identity too: the key cannot collide, so what is left to find is one person entered twice under two different keys. Walks the workspace a page at a time; pass the returned cursor to continue.",
        "tags": [
          "companies"
        ],
        "operationId": "get_v1_duplicates",
        "x-indraft-capability": "crm:read",
        "x-indraft-scopes": [
          "crm:read",
          "crm:write",
          "crm:configure",
          "crm:admin",
          "crm:revert",
          "data:export"
        ],
        "parameters": [
          {
            "name": "objectType",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64,
              "description": "What is being surveyed: a canonical type (company, contact), or the key of a type this workspace defined. A workspace's own type is surveyed on its first indexed text field, which is the name the search index holds for it."
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "description": "How many to return. The page bound is published in the schema call, and asking for more is refused rather than quietly truncated."
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "The opaque marker from the previous page. Store it and hand it back; do not parse it. A cursor is only ever emitted when another row really exists, so a page you were given is never empty."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "candidates": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "objectType": {
                            "type": "string",
                            "enum": [
                              "company",
                              "contact"
                            ]
                          },
                          "left": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string"
                              },
                              "label": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "id",
                              "label"
                            ],
                            "additionalProperties": true
                          },
                          "right": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string"
                              },
                              "label": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "id",
                              "label"
                            ],
                            "additionalProperties": true
                          },
                          "similarity": {
                            "type": "integer"
                          },
                          "reasons": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          }
                        },
                        "required": [
                          "objectType",
                          "left",
                          "right",
                          "similarity",
                          "reasons"
                        ],
                        "additionalProperties": true
                      }
                    },
                    "nextCursor": {
                      "type": "string"
                    },
                    "examined": {
                      "type": "integer"
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "candidates",
                    "nextCursor",
                    "examined",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/changes": {
      "get": {
        "summary": "Recent mutations and their diffs, or everything since a watermark",
        "description": "Inspect what changed and who changed it: the mutation, the actor, the access path, and the field-level diff. Use this to check your own work.",
        "tags": [
          "changes"
        ],
        "operationId": "get_v1_changes",
        "x-indraft-capability": "crm:read",
        "x-indraft-scopes": [
          "crm:read",
          "crm:write",
          "crm:configure",
          "crm:admin",
          "crm:revert",
          "data:export"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "description": "How many to return. The page bound is published in the schema call, and asking for more is refused rather than quietly truncated."
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "The opaque marker from the previous page. Store it and hand it back; do not parse it. A cursor is only ever emitted when another row really exists, so a page you were given is never empty."
            }
          },
          {
            "name": "since",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64,
              "description": "A watermark from a previous read. Everything that has happened after it, in order, which is what makes an outside copy possible without re-reading the world."
            }
          },
          {
            "name": "targetId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64,
              "description": "Only changes to this record. Use it to answer what happened to one account rather than to the workspace."
            }
          },
          {
            "name": "actorId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64,
              "description": "Only changes made by this actor."
            }
          },
          {
            "name": "targetType",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64,
              "description": "Only changes to this record type, including a workspace-defined type key."
            }
          },
          {
            "name": "assertionKind",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "observed",
                "inferred",
                "imported",
                "user_supplied",
                "confirmed"
              ],
              "description": "Only changes carrying this claim kind."
            }
          },
          {
            "name": "reversible",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ],
              "description": "Only changes that can, or cannot, be undone."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "actorId": {
                            "type": "string"
                          },
                          "operation": {
                            "type": "string"
                          },
                          "targetType": {
                            "type": "string"
                          },
                          "targetId": {
                            "type": "string"
                          },
                          "idempotencyKey": {
                            "type": "string"
                          },
                          "request": {},
                          "outcome": {
                            "type": "string",
                            "enum": [
                              "created",
                              "updated",
                              "matched",
                              "archived",
                              "merged",
                              "reverted",
                              "noop"
                            ],
                            "description": "What the write did. `noop` means it was accepted and changed nothing, because every value it carried already matched what was stored. IT IS NOT METERED: a noop does not count against your monthly change allowance, so a nightly sync that finds nothing new costs nothing. Neither does a write that only REDUCES what a workspace holds. `matched` means an upsert found an existing record on real identity evidence rather than creating a second one; `reverted` and `merged` are the undo and duplicate paths, and both are ordinary writes that count."
                          },
                          "accessPath": {
                            "type": "string",
                            "enum": [
                              "rest",
                              "mcp",
                              "app",
                              "system"
                            ]
                          },
                          "attributionLabel": {
                            "type": "string"
                          },
                          "sourceId": {
                            "type": "string"
                          },
                          "assertionKind": {
                            "type": "string",
                            "enum": [
                              "observed",
                              "inferred",
                              "imported",
                              "user_supplied"
                            ]
                          },
                          "reversible": {
                            "type": "boolean"
                          },
                          "overrideStanding": {
                            "type": "boolean"
                          },
                          "revertedBy": {
                            "type": "string"
                          },
                          "createdAt": {
                            "type": "string"
                          },
                          "actor": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string"
                              },
                              "kind": {
                                "type": "string",
                                "enum": [
                                  "human",
                                  "agent",
                                  "api_token",
                                  "system"
                                ]
                              },
                              "label": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "id",
                              "kind",
                              "label"
                            ],
                            "additionalProperties": true
                          },
                          "targetLabel": {
                            "type": "string"
                          },
                          "sourceLabel": {
                            "type": "string"
                          },
                          "changes": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "field": {
                                  "type": "string"
                                },
                                "before": {},
                                "after": {}
                              },
                              "required": [
                                "field"
                              ],
                              "additionalProperties": true
                            }
                          }
                        },
                        "required": [
                          "id",
                          "actorId",
                          "operation",
                          "targetType",
                          "targetId",
                          "idempotencyKey",
                          "outcome",
                          "accessPath",
                          "attributionLabel",
                          "sourceId",
                          "assertionKind",
                          "reversible",
                          "overrideStanding",
                          "revertedBy",
                          "createdAt",
                          "actor",
                          "targetLabel",
                          "sourceLabel",
                          "changes"
                        ],
                        "additionalProperties": true
                      }
                    },
                    "nextCursor": {
                      "type": "string"
                    },
                    "retention": {
                      "type": "object",
                      "properties": {
                        "oldestRetainedAt": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "oldestRetainedAt"
                      ],
                      "additionalProperties": true
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "items",
                    "nextCursor",
                    "retention",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/changes/{id}/revert": {
      "post": {
        "summary": "Compensate a reversible change",
        "description": "Compensate a previous field change. Refused if the mutation created a record, if it was a merge, or if any field it covered has changed since. Ask list_recent_changes for the mutation id.",
        "tags": [
          "changes"
        ],
        "operationId": "post_v1_changes__id__revert",
        "x-indraft-capability": "crm:revert",
        "x-indraft-scopes": [
          "crm:admin",
          "crm:revert"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The change id, as returned by the call that created or matched it.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "idempotencyKey": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 200,
                    "description": "Your own name for this write, so retrying it cannot do it twice. Send the same key again and you get the SAME result back rather than a second record, which is what makes a re-run safe after a timeout you never saw the answer to. Derive it from what the write is about, not from the clock: `nightly-sync-halden` retries correctly and a timestamp does not."
                  },
                  "expectedVersion": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "The version you read before deciding to write. If the record has moved since, the write is refused instead of overwriting whatever changed. Send it whenever you read, reasoned, and then wrote: without it the last writer wins and neither of you finds out."
                  },
                  "sourceId": {
                    "type": "string",
                    "description": "The recorded source this claim came from, if one exists. It attaches evidence to the write, so a person reading the field later can see where it came from rather than only who sent it."
                  },
                  "assertionKind": {
                    "type": "string",
                    "enum": [
                      "observed",
                      "inferred",
                      "imported",
                      "user_supplied"
                    ],
                    "description": "HOW YOU KNOW. This is the field the product is built around, so say what is true rather than what is strongest: `observed` you saw it stated directly, `imported` it came from a file or another system, `inferred` you worked it out, `user_supplied` a person told you in so many words. They rank, weakest first: inferred < imported < observed < user_supplied < confirmed. A weaker claim does not overwrite a stronger one; it is reported in `held[]` and the stored value stands, so an unattended re-run converges instead of eroding what somebody checked. `confirmed` is not accepted here: it means a person checked the value, and only a signed-in person can set it."
                  },
                  "attributionLabel": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120,
                    "description": "A short name for the work this write belongs to, shown beside the actor so one credential can distinguish separate jobs. It is recorded as CALLER-SUPPLIED and grants nothing: it changes no permission, no idempotency scope and no quota."
                  },
                  "dryRun": {
                    "type": "boolean",
                    "description": "Report what this write WOULD do and commit nothing. The response carries the same change list, held fields and refusals as the real call, so it is the way to check a risky write, or a whole import, before it lands. Nothing is metered."
                  },
                  "overrideStanding": {
                    "type": "boolean",
                    "description": "Apply this write even when the value standing in the record was asserted more strongly than this one. Absent means no, which is the safe answer for a re-run. WITHOUT IT, a write can be accepted and change nothing: precedence is confirmed > user_supplied > observed > imported > inferred, and a weaker claim leaves the standing value in place and reports the field in `held[]` rather than failing. That is the whole of why a write can return 200 and not take. WITH it, this write wins regardless of what it is overruling, INCLUDING a value a person confirmed, so an agent that sets it by default has switched the provenance mechanism off. Set it per write, when the caller knows its claim supersedes what is there."
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "record": {
                      "type": "object",
                      "properties": {
                        "revertedMutationId": {
                          "type": "string"
                        },
                        "fieldsRestored": {
                          "type": "integer"
                        }
                      },
                      "required": [
                        "revertedMutationId",
                        "fieldsRestored"
                      ],
                      "additionalProperties": true
                    },
                    "mutation": {
                      "type": "object",
                      "properties": {
                        "mutationId": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "created",
                            "updated",
                            "matched",
                            "archived",
                            "merged",
                            "reverted",
                            "noop"
                          ],
                          "description": "What the write did. `noop` means it was accepted and changed nothing, because every value it carried already matched what was stored. IT IS NOT METERED: a noop does not count against your monthly change allowance, so a nightly sync that finds nothing new costs nothing. Neither does a write that only REDUCES what a workspace holds. `matched` means an upsert found an existing record on real identity evidence rather than creating a second one; `reverted` and `merged` are the undo and duplicate paths, and both are ordinary writes that count."
                        },
                        "targetId": {
                          "type": "string"
                        },
                        "record": {},
                        "changes": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "before": {},
                              "after": {}
                            },
                            "required": [
                              "field"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "held": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "kept": {},
                              "proposed": {},
                              "standing": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "incoming": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "actorId": {
                                "type": "string",
                                "minLength": 1
                              },
                              "assertedAt": {
                                "type": "string",
                                "minLength": 1
                              }
                            },
                            "required": [
                              "field",
                              "standing",
                              "incoming",
                              "actorId",
                              "assertedAt"
                            ],
                            "additionalProperties": false
                          },
                          "description": "Fields this write asked to change and did not, because the value standing in the record was asserted more strongly. THIS IS WHY A WRITE CAN RETURN 200 AND CHANGE NOTHING, and a caller that ignores it will believe it wrote something it did not. Precedence is confirmed > user_supplied > observed > imported > inferred, and a write carrying no `assertionKind` is weakest of all. Each entry reports the field, what the record still says, what you proposed, which claim won, and who made it. Send `overrideStanding` to write anyway, per write, when your claim really does supersede theirs."
                        },
                        "matchedBy": {
                          "type": "string",
                          "enum": [
                            "email",
                            "domain",
                            "external_id",
                            "idempotency_key",
                            "explicit_id"
                          ]
                        },
                        "reversible": {
                          "type": "boolean"
                        },
                        "replayed": {
                          "type": "boolean"
                        },
                        "dryRun": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "mutationId",
                        "status",
                        "reversible"
                      ],
                      "additionalProperties": false
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "mutation",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "A product quota is spent, or the subscription is not active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such record, or it belongs to another workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A conflict the caller can resolve: a stale expectedVersion, an idempotency key reused for different input, an ambiguous or duplicate identity, or a merge that no longer applies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The body, or a single record inside it, exceeds its bound.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "507": {
            "description": "The workspace is at its storage ceiling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/pipelines": {
      "post": {
        "summary": "Create or reconfigure a pipeline and its ordered stages",
        "description": "Create or reconfigure a pipeline and its ordered stages. Every pipeline needs at least one open stage and both a won and a lost stage, or a record in it could never close. Set objectType to one of this workspace's own types to give that type a board of its own: a type with two relationships and a pipeline is a junction, so a Submission can carry the stage of a candidate against a requisition rather than either one carrying it alone.",
        "tags": [
          "pipelines"
        ],
        "operationId": "post_v1_pipelines",
        "x-indraft-capability": "crm:configure",
        "x-indraft-scopes": [
          "crm:configure",
          "crm:admin"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "idempotencyKey": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 200,
                    "description": "Your own name for this write, so retrying it cannot do it twice. Send the same key again and you get the SAME result back rather than a second record, which is what makes a re-run safe after a timeout you never saw the answer to. Derive it from what the write is about, not from the clock: `nightly-sync-halden` retries correctly and a timestamp does not."
                  },
                  "expectedVersion": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "The version you read before deciding to write. If the record has moved since, the write is refused instead of overwriting whatever changed. Send it whenever you read, reasoned, and then wrote: without it the last writer wins and neither of you finds out."
                  },
                  "sourceId": {
                    "type": "string",
                    "description": "The recorded source this claim came from, if one exists. It attaches evidence to the write, so a person reading the field later can see where it came from rather than only who sent it."
                  },
                  "assertionKind": {
                    "type": "string",
                    "enum": [
                      "observed",
                      "inferred",
                      "imported",
                      "user_supplied"
                    ],
                    "description": "HOW YOU KNOW. This is the field the product is built around, so say what is true rather than what is strongest: `observed` you saw it stated directly, `imported` it came from a file or another system, `inferred` you worked it out, `user_supplied` a person told you in so many words. They rank, weakest first: inferred < imported < observed < user_supplied < confirmed. A weaker claim does not overwrite a stronger one; it is reported in `held[]` and the stored value stands, so an unattended re-run converges instead of eroding what somebody checked. `confirmed` is not accepted here: it means a person checked the value, and only a signed-in person can set it."
                  },
                  "attributionLabel": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120,
                    "description": "A short name for the work this write belongs to, shown beside the actor so one credential can distinguish separate jobs. It is recorded as CALLER-SUPPLIED and grants nothing: it changes no permission, no idempotency scope and no quota."
                  },
                  "dryRun": {
                    "type": "boolean",
                    "description": "Report what this write WOULD do and commit nothing. The response carries the same change list, held fields and refusals as the real call, so it is the way to check a risky write, or a whole import, before it lands. Nothing is metered."
                  },
                  "overrideStanding": {
                    "type": "boolean",
                    "description": "Apply this write even when the value standing in the record was asserted more strongly than this one. Absent means no, which is the safe answer for a re-run. WITHOUT IT, a write can be accepted and change nothing: precedence is confirmed > user_supplied > observed > imported > inferred, and a weaker claim leaves the standing value in place and reports the field in `held[]` rather than failing. That is the whole of why a write can return 200 and not take. WITH it, this write wins regardless of what it is overruling, INCLUDING a value a person confirmed, so an agent that sets it by default has switched the provenance mechanism off. Set it per write, when the caller knows its claim supersedes what is there."
                  },
                  "id": {
                    "type": "string"
                  },
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "objectType": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 48,
                    "description": "What is being counted: a canonical type, or the key of a type this workspace defined."
                  },
                  "isDefault": {
                    "type": "boolean"
                  },
                  "stages": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "name": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 200
                        },
                        "stageKind": {
                          "type": "string",
                          "enum": [
                            "open",
                            "won",
                            "lost"
                          ]
                        },
                        "defaultProbabilityBps": {
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 10000
                        }
                      },
                      "required": [
                        "name",
                        "stageKind"
                      ],
                      "additionalProperties": false
                    },
                    "minItems": 2,
                    "maxItems": 50
                  }
                },
                "required": [
                  "name",
                  "stages"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "record": {
                      "type": "object",
                      "additionalProperties": {}
                    },
                    "mutation": {
                      "type": "object",
                      "properties": {
                        "mutationId": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "created",
                            "updated",
                            "matched",
                            "archived",
                            "merged",
                            "reverted",
                            "noop"
                          ],
                          "description": "What the write did. `noop` means it was accepted and changed nothing, because every value it carried already matched what was stored. IT IS NOT METERED: a noop does not count against your monthly change allowance, so a nightly sync that finds nothing new costs nothing. Neither does a write that only REDUCES what a workspace holds. `matched` means an upsert found an existing record on real identity evidence rather than creating a second one; `reverted` and `merged` are the undo and duplicate paths, and both are ordinary writes that count."
                        },
                        "targetId": {
                          "type": "string"
                        },
                        "record": {},
                        "changes": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "before": {},
                              "after": {}
                            },
                            "required": [
                              "field"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "held": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "kept": {},
                              "proposed": {},
                              "standing": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "incoming": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "actorId": {
                                "type": "string",
                                "minLength": 1
                              },
                              "assertedAt": {
                                "type": "string",
                                "minLength": 1
                              }
                            },
                            "required": [
                              "field",
                              "standing",
                              "incoming",
                              "actorId",
                              "assertedAt"
                            ],
                            "additionalProperties": false
                          },
                          "description": "Fields this write asked to change and did not, because the value standing in the record was asserted more strongly. THIS IS WHY A WRITE CAN RETURN 200 AND CHANGE NOTHING, and a caller that ignores it will believe it wrote something it did not. Precedence is confirmed > user_supplied > observed > imported > inferred, and a write carrying no `assertionKind` is weakest of all. Each entry reports the field, what the record still says, what you proposed, which claim won, and who made it. Send `overrideStanding` to write anyway, per write, when your claim really does supersede theirs."
                        },
                        "matchedBy": {
                          "type": "string",
                          "enum": [
                            "email",
                            "domain",
                            "external_id",
                            "idempotency_key",
                            "explicit_id"
                          ]
                        },
                        "reversible": {
                          "type": "boolean"
                        },
                        "replayed": {
                          "type": "boolean"
                        },
                        "dryRun": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "mutationId",
                        "status",
                        "reversible"
                      ],
                      "additionalProperties": false
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "mutation",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "A product quota is spent, or the subscription is not active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A conflict the caller can resolve: a stale expectedVersion, an idempotency key reused for different input, an ambiguous or duplicate identity, or a merge that no longer applies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The body, or a single record inside it, exceeds its bound.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "507": {
            "description": "The workspace is at its storage ceiling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/custom-fields": {
      "post": {
        "summary": "Define or update a typed custom field",
        "description": "Define or update a typed custom field on a company, contact, opportunity, interaction, or task. A field is addressed by its object type and key. The value type cannot change once values exist. Use interaction for call disposition, meeting type and next step: those are what activity reporting is made of, and a summary is prose rather than a field you can group by. Pass `computed` to make the field DERIVED instead of stored: it is then recalculated from stored fields on every read, nothing can write it, and it can never go stale behind its inputs. Two forms only. `{form:'binary', op:'multiply', left:{field:'salary_minor'}, right:{field:'placement_pct_bps'}, divideBy:10000}` computes a fee from two fields and a constant. `{form:'rollup', relationship:'opportunities', function:'sum', field:'amount_minor'}` totals over a declared relationship. A computed field must be a number, cannot be required or searchable, and cannot read another computed field. get_crm_schema lists the relationships and the inputs each type offers.",
        "tags": [
          "custom-fields"
        ],
        "operationId": "post_v1_custom_fields",
        "x-indraft-capability": "crm:configure",
        "x-indraft-scopes": [
          "crm:configure",
          "crm:admin"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "idempotencyKey": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 200,
                    "description": "Your own name for this write, so retrying it cannot do it twice. Send the same key again and you get the SAME result back rather than a second record, which is what makes a re-run safe after a timeout you never saw the answer to. Derive it from what the write is about, not from the clock: `nightly-sync-halden` retries correctly and a timestamp does not."
                  },
                  "expectedVersion": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "The version you read before deciding to write. If the record has moved since, the write is refused instead of overwriting whatever changed. Send it whenever you read, reasoned, and then wrote: without it the last writer wins and neither of you finds out."
                  },
                  "sourceId": {
                    "type": "string",
                    "description": "The recorded source this claim came from, if one exists. It attaches evidence to the write, so a person reading the field later can see where it came from rather than only who sent it."
                  },
                  "assertionKind": {
                    "type": "string",
                    "enum": [
                      "observed",
                      "inferred",
                      "imported",
                      "user_supplied"
                    ],
                    "description": "HOW YOU KNOW. This is the field the product is built around, so say what is true rather than what is strongest: `observed` you saw it stated directly, `imported` it came from a file or another system, `inferred` you worked it out, `user_supplied` a person told you in so many words. They rank, weakest first: inferred < imported < observed < user_supplied < confirmed. A weaker claim does not overwrite a stronger one; it is reported in `held[]` and the stored value stands, so an unattended re-run converges instead of eroding what somebody checked. `confirmed` is not accepted here: it means a person checked the value, and only a signed-in person can set it."
                  },
                  "attributionLabel": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120,
                    "description": "A short name for the work this write belongs to, shown beside the actor so one credential can distinguish separate jobs. It is recorded as CALLER-SUPPLIED and grants nothing: it changes no permission, no idempotency scope and no quota."
                  },
                  "dryRun": {
                    "type": "boolean",
                    "description": "Report what this write WOULD do and commit nothing. The response carries the same change list, held fields and refusals as the real call, so it is the way to check a risky write, or a whole import, before it lands. Nothing is metered."
                  },
                  "overrideStanding": {
                    "type": "boolean",
                    "description": "Apply this write even when the value standing in the record was asserted more strongly than this one. Absent means no, which is the safe answer for a re-run. WITHOUT IT, a write can be accepted and change nothing: precedence is confirmed > user_supplied > observed > imported > inferred, and a weaker claim leaves the standing value in place and reports the field in `held[]` rather than failing. That is the whole of why a write can return 200 and not take. WITH it, this write wins regardless of what it is overruling, INCLUDING a value a person confirmed, so an agent that sets it by default has switched the provenance mechanism off. Set it per write, when the caller knows its claim supersedes what is there."
                  },
                  "id": {
                    "type": "string"
                  },
                  "key": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 64,
                    "pattern": "^[a-z][a-z0-9_]*$"
                  },
                  "label": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "target": {
                    "type": "string",
                    "enum": [
                      "company",
                      "contact",
                      "opportunity",
                      "interaction",
                      "task"
                    ]
                  },
                  "valueType": {
                    "type": "string",
                    "enum": [
                      "text",
                      "number",
                      "boolean",
                      "timestamp",
                      "enum",
                      "json"
                    ]
                  },
                  "required": {
                    "type": "boolean"
                  },
                  "searchable": {
                    "type": "boolean"
                  },
                  "enumOptions": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 200
                    },
                    "maxItems": 100
                  },
                  "computed": {
                    "oneOf": [
                      {
                        "type": "object",
                        "properties": {
                          "form": {
                            "type": "string",
                            "enum": [
                              "binary"
                            ]
                          },
                          "op": {
                            "type": "string",
                            "enum": [
                              "add",
                              "subtract",
                              "multiply",
                              "divide"
                            ]
                          },
                          "left": {
                            "anyOf": [
                              {
                                "type": "object",
                                "properties": {
                                  "field": {
                                    "type": "string",
                                    "minLength": 1,
                                    "maxLength": 64,
                                    "pattern": "^[a-z][a-z0-9_]*$"
                                  }
                                },
                                "required": [
                                  "field"
                                ],
                                "additionalProperties": false
                              },
                              {
                                "type": "object",
                                "properties": {
                                  "constant": {
                                    "type": "integer",
                                    "minimum": -9007199254740991,
                                    "maximum": 9007199254740991
                                  }
                                },
                                "required": [
                                  "constant"
                                ],
                                "additionalProperties": false
                              }
                            ]
                          },
                          "right": {
                            "anyOf": [
                              {
                                "type": "object",
                                "properties": {
                                  "field": {
                                    "type": "string",
                                    "minLength": 1,
                                    "maxLength": 64,
                                    "pattern": "^[a-z][a-z0-9_]*$"
                                  }
                                },
                                "required": [
                                  "field"
                                ],
                                "additionalProperties": false
                              },
                              {
                                "type": "object",
                                "properties": {
                                  "constant": {
                                    "type": "integer",
                                    "minimum": -9007199254740991,
                                    "maximum": 9007199254740991
                                  }
                                },
                                "required": [
                                  "constant"
                                ],
                                "additionalProperties": false
                              }
                            ]
                          },
                          "divideBy": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          }
                        },
                        "required": [
                          "form",
                          "op",
                          "left",
                          "right"
                        ],
                        "additionalProperties": false
                      },
                      {
                        "type": "object",
                        "properties": {
                          "form": {
                            "type": "string",
                            "enum": [
                              "rollup"
                            ]
                          },
                          "relationship": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 64,
                            "pattern": "^[a-z][a-z0-9_]*$"
                          },
                          "function": {
                            "type": "string",
                            "enum": [
                              "sum",
                              "count",
                              "min",
                              "max"
                            ]
                          },
                          "field": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 64,
                            "pattern": "^[a-z][a-z0-9_]*$"
                          }
                        },
                        "required": [
                          "form",
                          "relationship",
                          "function"
                        ],
                        "additionalProperties": false
                      }
                    ],
                    "discriminator": {
                      "propertyName": "form"
                    }
                  }
                },
                "required": [
                  "key",
                  "label",
                  "target",
                  "valueType"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "record": {
                      "type": "object",
                      "additionalProperties": {}
                    },
                    "mutation": {
                      "type": "object",
                      "properties": {
                        "mutationId": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "created",
                            "updated",
                            "matched",
                            "archived",
                            "merged",
                            "reverted",
                            "noop"
                          ],
                          "description": "What the write did. `noop` means it was accepted and changed nothing, because every value it carried already matched what was stored. IT IS NOT METERED: a noop does not count against your monthly change allowance, so a nightly sync that finds nothing new costs nothing. Neither does a write that only REDUCES what a workspace holds. `matched` means an upsert found an existing record on real identity evidence rather than creating a second one; `reverted` and `merged` are the undo and duplicate paths, and both are ordinary writes that count."
                        },
                        "targetId": {
                          "type": "string"
                        },
                        "record": {},
                        "changes": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "before": {},
                              "after": {}
                            },
                            "required": [
                              "field"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "held": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "kept": {},
                              "proposed": {},
                              "standing": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "incoming": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "actorId": {
                                "type": "string",
                                "minLength": 1
                              },
                              "assertedAt": {
                                "type": "string",
                                "minLength": 1
                              }
                            },
                            "required": [
                              "field",
                              "standing",
                              "incoming",
                              "actorId",
                              "assertedAt"
                            ],
                            "additionalProperties": false
                          },
                          "description": "Fields this write asked to change and did not, because the value standing in the record was asserted more strongly. THIS IS WHY A WRITE CAN RETURN 200 AND CHANGE NOTHING, and a caller that ignores it will believe it wrote something it did not. Precedence is confirmed > user_supplied > observed > imported > inferred, and a write carrying no `assertionKind` is weakest of all. Each entry reports the field, what the record still says, what you proposed, which claim won, and who made it. Send `overrideStanding` to write anyway, per write, when your claim really does supersede theirs."
                        },
                        "matchedBy": {
                          "type": "string",
                          "enum": [
                            "email",
                            "domain",
                            "external_id",
                            "idempotency_key",
                            "explicit_id"
                          ]
                        },
                        "reversible": {
                          "type": "boolean"
                        },
                        "replayed": {
                          "type": "boolean"
                        },
                        "dryRun": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "mutationId",
                        "status",
                        "reversible"
                      ],
                      "additionalProperties": false
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "mutation",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "A product quota is spent, or the subscription is not active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A conflict the caller can resolve: a stale expectedVersion, an idempotency key reused for different input, an ambiguous or duplicate identity, or a merge that no longer applies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The body, or a single record inside it, exceeds its bound.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "507": {
            "description": "The workspace is at its storage ceiling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/exchange-rates": {
      "post": {
        "summary": "Assert an exchange rate, with its effective date and source",
        "description": "State an exchange rate this workspace stands behind, with the day it takes effect and where it came from. Indraft never fetches, infers, or interpolates a rate, so this is the ONLY way a total can cross currencies: without a stored rate an aggregate refuses rather than converting. The rate is recorded as an assertion like any other, with the actor who made it, and every converted total names it. Give the rate in millionths as an integer, so 1.0842 is 1084200: a decimal rate would be a float, and a float is how a rounding error reaches a pipeline total. Asserting the same pair for the same day again corrects the standing rate rather than adding a second one.",
        "tags": [
          "exchange-rates"
        ],
        "operationId": "post_v1_exchange_rates",
        "x-indraft-capability": "crm:configure",
        "x-indraft-scopes": [
          "crm:configure",
          "crm:admin"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "idempotencyKey": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 200,
                    "description": "Your own name for this write, so retrying it cannot do it twice. Send the same key again and you get the SAME result back rather than a second record, which is what makes a re-run safe after a timeout you never saw the answer to. Derive it from what the write is about, not from the clock: `nightly-sync-halden` retries correctly and a timestamp does not."
                  },
                  "expectedVersion": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "The version you read before deciding to write. If the record has moved since, the write is refused instead of overwriting whatever changed. Send it whenever you read, reasoned, and then wrote: without it the last writer wins and neither of you finds out."
                  },
                  "sourceId": {
                    "type": "string",
                    "description": "The recorded source this claim came from, if one exists. It attaches evidence to the write, so a person reading the field later can see where it came from rather than only who sent it."
                  },
                  "assertionKind": {
                    "type": "string",
                    "enum": [
                      "observed",
                      "inferred",
                      "imported",
                      "user_supplied"
                    ],
                    "description": "HOW YOU KNOW. This is the field the product is built around, so say what is true rather than what is strongest: `observed` you saw it stated directly, `imported` it came from a file or another system, `inferred` you worked it out, `user_supplied` a person told you in so many words. They rank, weakest first: inferred < imported < observed < user_supplied < confirmed. A weaker claim does not overwrite a stronger one; it is reported in `held[]` and the stored value stands, so an unattended re-run converges instead of eroding what somebody checked. `confirmed` is not accepted here: it means a person checked the value, and only a signed-in person can set it."
                  },
                  "attributionLabel": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120,
                    "description": "A short name for the work this write belongs to, shown beside the actor so one credential can distinguish separate jobs. It is recorded as CALLER-SUPPLIED and grants nothing: it changes no permission, no idempotency scope and no quota."
                  },
                  "dryRun": {
                    "type": "boolean",
                    "description": "Report what this write WOULD do and commit nothing. The response carries the same change list, held fields and refusals as the real call, so it is the way to check a risky write, or a whole import, before it lands. Nothing is metered."
                  },
                  "overrideStanding": {
                    "type": "boolean",
                    "description": "Apply this write even when the value standing in the record was asserted more strongly than this one. Absent means no, which is the safe answer for a re-run. WITHOUT IT, a write can be accepted and change nothing: precedence is confirmed > user_supplied > observed > imported > inferred, and a weaker claim leaves the standing value in place and reports the field in `held[]` rather than failing. That is the whole of why a write can return 200 and not take. WITH it, this write wins regardless of what it is overruling, INCLUDING a value a person confirmed, so an agent that sets it by default has switched the provenance mechanism off. Set it per write, when the caller knows its claim supersedes what is there."
                  },
                  "from": {
                    "type": "string",
                    "pattern": "^[A-Z]{3}$"
                  },
                  "to": {
                    "type": "string",
                    "pattern": "^[A-Z]{3}$"
                  },
                  "ratePpm": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "effectiveFrom": {
                    "type": "string",
                    "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                  },
                  "sourceLabel": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  }
                },
                "required": [
                  "from",
                  "to",
                  "ratePpm",
                  "effectiveFrom",
                  "sourceLabel"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "record": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "from": {
                          "type": "string"
                        },
                        "to": {
                          "type": "string"
                        },
                        "ratePpm": {
                          "type": "integer"
                        },
                        "effectiveFrom": {
                          "type": "string"
                        },
                        "sourceLabel": {
                          "type": "string"
                        },
                        "assertedByActorId": {
                          "type": "string"
                        },
                        "assertionKind": {
                          "type": "string"
                        },
                        "createdAt": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id",
                        "from",
                        "to",
                        "ratePpm",
                        "effectiveFrom",
                        "sourceLabel",
                        "assertedByActorId",
                        "assertionKind",
                        "createdAt"
                      ],
                      "additionalProperties": true
                    },
                    "mutation": {
                      "type": "object",
                      "properties": {
                        "mutationId": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "created",
                            "updated",
                            "matched",
                            "archived",
                            "merged",
                            "reverted",
                            "noop"
                          ],
                          "description": "What the write did. `noop` means it was accepted and changed nothing, because every value it carried already matched what was stored. IT IS NOT METERED: a noop does not count against your monthly change allowance, so a nightly sync that finds nothing new costs nothing. Neither does a write that only REDUCES what a workspace holds. `matched` means an upsert found an existing record on real identity evidence rather than creating a second one; `reverted` and `merged` are the undo and duplicate paths, and both are ordinary writes that count."
                        },
                        "targetId": {
                          "type": "string"
                        },
                        "record": {},
                        "changes": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "before": {},
                              "after": {}
                            },
                            "required": [
                              "field"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "held": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "kept": {},
                              "proposed": {},
                              "standing": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "incoming": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "actorId": {
                                "type": "string",
                                "minLength": 1
                              },
                              "assertedAt": {
                                "type": "string",
                                "minLength": 1
                              }
                            },
                            "required": [
                              "field",
                              "standing",
                              "incoming",
                              "actorId",
                              "assertedAt"
                            ],
                            "additionalProperties": false
                          },
                          "description": "Fields this write asked to change and did not, because the value standing in the record was asserted more strongly. THIS IS WHY A WRITE CAN RETURN 200 AND CHANGE NOTHING, and a caller that ignores it will believe it wrote something it did not. Precedence is confirmed > user_supplied > observed > imported > inferred, and a write carrying no `assertionKind` is weakest of all. Each entry reports the field, what the record still says, what you proposed, which claim won, and who made it. Send `overrideStanding` to write anyway, per write, when your claim really does supersede theirs."
                        },
                        "matchedBy": {
                          "type": "string",
                          "enum": [
                            "email",
                            "domain",
                            "external_id",
                            "idempotency_key",
                            "explicit_id"
                          ]
                        },
                        "reversible": {
                          "type": "boolean"
                        },
                        "replayed": {
                          "type": "boolean"
                        },
                        "dryRun": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "mutationId",
                        "status",
                        "reversible"
                      ],
                      "additionalProperties": false
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "record",
                    "mutation",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "A product quota is spent, or the subscription is not active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A conflict the caller can resolve: a stale expectedVersion, an idempotency key reused for different input, an ambiguous or duplicate identity, or a merge that no longer applies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The body, or a single record inside it, exceeds its bound.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "507": {
            "description": "The workspace is at its storage ceiling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "get": {
        "summary": "Every exchange rate this workspace has asserted",
        "description": "Every rate this workspace has asserted, with when it was asserted and by whom. Indraft never invents a rate: a converted total is refused until you supply one, because a number nobody chose is worse than no number.",
        "tags": [
          "exchange-rates"
        ],
        "operationId": "get_v1_exchange_rates",
        "x-indraft-capability": "crm:read",
        "x-indraft-scopes": [
          "crm:read",
          "crm:write",
          "crm:configure",
          "crm:admin",
          "crm:revert",
          "data:export"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "from": {
                            "type": "string"
                          },
                          "to": {
                            "type": "string"
                          },
                          "ratePpm": {
                            "type": "integer"
                          },
                          "effectiveFrom": {
                            "type": "string"
                          },
                          "sourceLabel": {
                            "type": "string"
                          },
                          "assertedByActorId": {
                            "type": "string"
                          },
                          "assertionKind": {
                            "type": "string"
                          },
                          "createdAt": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "from",
                          "to",
                          "ratePpm",
                          "effectiveFrom",
                          "sourceLabel",
                          "assertedByActorId",
                          "assertionKind",
                          "createdAt"
                        ],
                        "additionalProperties": true
                      }
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "items",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/companies:archive": {
      "post": {
        "summary": "Archive or restore up to 500 companies in one call",
        "description": "Up to 500 in one call, each independently applied. A failure on one row does not discard the rest, and the result reports every row's outcome.",
        "tags": [
          "companies"
        ],
        "operationId": "post_v1_companies_archive",
        "x-indraft-capability": "crm:write",
        "x-indraft-scopes": [
          "crm:write",
          "crm:admin"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "idempotencyKey": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 200,
                    "description": "Your own name for this write, so retrying it cannot do it twice. Send the same key again and you get the SAME result back rather than a second record, which is what makes a re-run safe after a timeout you never saw the answer to. Derive it from what the write is about, not from the clock: `nightly-sync-halden` retries correctly and a timestamp does not."
                  },
                  "expectedVersion": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "The version you read before deciding to write. If the record has moved since, the write is refused instead of overwriting whatever changed. Send it whenever you read, reasoned, and then wrote: without it the last writer wins and neither of you finds out."
                  },
                  "sourceId": {
                    "type": "string",
                    "description": "The recorded source this claim came from, if one exists. It attaches evidence to the write, so a person reading the field later can see where it came from rather than only who sent it."
                  },
                  "assertionKind": {
                    "type": "string",
                    "enum": [
                      "observed",
                      "inferred",
                      "imported",
                      "user_supplied"
                    ],
                    "description": "HOW YOU KNOW. This is the field the product is built around, so say what is true rather than what is strongest: `observed` you saw it stated directly, `imported` it came from a file or another system, `inferred` you worked it out, `user_supplied` a person told you in so many words. They rank, weakest first: inferred < imported < observed < user_supplied < confirmed. A weaker claim does not overwrite a stronger one; it is reported in `held[]` and the stored value stands, so an unattended re-run converges instead of eroding what somebody checked. `confirmed` is not accepted here: it means a person checked the value, and only a signed-in person can set it."
                  },
                  "attributionLabel": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120,
                    "description": "A short name for the work this write belongs to, shown beside the actor so one credential can distinguish separate jobs. It is recorded as CALLER-SUPPLIED and grants nothing: it changes no permission, no idempotency scope and no quota."
                  },
                  "dryRun": {
                    "type": "boolean",
                    "description": "Report what this write WOULD do and commit nothing. The response carries the same change list, held fields and refusals as the real call, so it is the way to check a risky write, or a whole import, before it lands. Nothing is metered."
                  },
                  "overrideStanding": {
                    "type": "boolean",
                    "description": "Apply this write even when the value standing in the record was asserted more strongly than this one. Absent means no, which is the safe answer for a re-run. WITHOUT IT, a write can be accepted and change nothing: precedence is confirmed > user_supplied > observed > imported > inferred, and a weaker claim leaves the standing value in place and reports the field in `held[]` rather than failing. That is the whole of why a write can return 200 and not take. WITH it, this write wins regardless of what it is overruling, INCLUDING a value a person confirmed, so an agent that sets it by default has switched the provenance mechanism off. Set it per write, when the caller knows its claim supersedes what is there."
                  },
                  "ids": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1
                    },
                    "minItems": 1,
                    "maxItems": 500
                  },
                  "restore": {
                    "type": "boolean"
                  }
                },
                "required": [
                  "ids"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "archived": {
                      "type": "integer"
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "ok": {
                            "type": "boolean"
                          },
                          "code": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "ok"
                        ],
                        "additionalProperties": true
                      }
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "archived",
                    "results",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "A product quota is spent, or the subscription is not active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A conflict the caller can resolve: a stale expectedVersion, an idempotency key reused for different input, an ambiguous or duplicate identity, or a merge that no longer applies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The body, or a single record inside it, exceeds its bound.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "507": {
            "description": "The workspace is at its storage ceiling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/contacts:archive": {
      "post": {
        "summary": "Archive or restore up to 500 contacts in one call",
        "description": "Up to 500 in one call, each independently applied. A failure on one row does not discard the rest, and the result reports every row's outcome.",
        "tags": [
          "contacts"
        ],
        "operationId": "post_v1_contacts_archive",
        "x-indraft-capability": "crm:write",
        "x-indraft-scopes": [
          "crm:write",
          "crm:admin"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "idempotencyKey": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 200,
                    "description": "Your own name for this write, so retrying it cannot do it twice. Send the same key again and you get the SAME result back rather than a second record, which is what makes a re-run safe after a timeout you never saw the answer to. Derive it from what the write is about, not from the clock: `nightly-sync-halden` retries correctly and a timestamp does not."
                  },
                  "expectedVersion": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "The version you read before deciding to write. If the record has moved since, the write is refused instead of overwriting whatever changed. Send it whenever you read, reasoned, and then wrote: without it the last writer wins and neither of you finds out."
                  },
                  "sourceId": {
                    "type": "string",
                    "description": "The recorded source this claim came from, if one exists. It attaches evidence to the write, so a person reading the field later can see where it came from rather than only who sent it."
                  },
                  "assertionKind": {
                    "type": "string",
                    "enum": [
                      "observed",
                      "inferred",
                      "imported",
                      "user_supplied"
                    ],
                    "description": "HOW YOU KNOW. This is the field the product is built around, so say what is true rather than what is strongest: `observed` you saw it stated directly, `imported` it came from a file or another system, `inferred` you worked it out, `user_supplied` a person told you in so many words. They rank, weakest first: inferred < imported < observed < user_supplied < confirmed. A weaker claim does not overwrite a stronger one; it is reported in `held[]` and the stored value stands, so an unattended re-run converges instead of eroding what somebody checked. `confirmed` is not accepted here: it means a person checked the value, and only a signed-in person can set it."
                  },
                  "attributionLabel": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120,
                    "description": "A short name for the work this write belongs to, shown beside the actor so one credential can distinguish separate jobs. It is recorded as CALLER-SUPPLIED and grants nothing: it changes no permission, no idempotency scope and no quota."
                  },
                  "dryRun": {
                    "type": "boolean",
                    "description": "Report what this write WOULD do and commit nothing. The response carries the same change list, held fields and refusals as the real call, so it is the way to check a risky write, or a whole import, before it lands. Nothing is metered."
                  },
                  "overrideStanding": {
                    "type": "boolean",
                    "description": "Apply this write even when the value standing in the record was asserted more strongly than this one. Absent means no, which is the safe answer for a re-run. WITHOUT IT, a write can be accepted and change nothing: precedence is confirmed > user_supplied > observed > imported > inferred, and a weaker claim leaves the standing value in place and reports the field in `held[]` rather than failing. That is the whole of why a write can return 200 and not take. WITH it, this write wins regardless of what it is overruling, INCLUDING a value a person confirmed, so an agent that sets it by default has switched the provenance mechanism off. Set it per write, when the caller knows its claim supersedes what is there."
                  },
                  "ids": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1
                    },
                    "minItems": 1,
                    "maxItems": 500
                  },
                  "restore": {
                    "type": "boolean"
                  }
                },
                "required": [
                  "ids"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "archived": {
                      "type": "integer"
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "ok": {
                            "type": "boolean"
                          },
                          "code": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "ok"
                        ],
                        "additionalProperties": true
                      }
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "archived",
                    "results",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "A product quota is spent, or the subscription is not active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A conflict the caller can resolve: a stale expectedVersion, an idempotency key reused for different input, an ambiguous or duplicate identity, or a merge that no longer applies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The body, or a single record inside it, exceeds its bound.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "507": {
            "description": "The workspace is at its storage ceiling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/unconfirmed": {
      "get": {
        "summary": "Values an agent asserted that no person has since confirmed",
        "description": "Values an agent asserted that no person has checked. Use it before you present a fact as settled, and to tell a person what is worth reviewing: every entry names the value, who asserted it, when, and how they came by it. You cannot confirm one. A confirmation means a person checked it, so only a person can make one, and that is the whole point of the queue. Narrow with objectType, or with assertionKinds to look at the weakest claims first.",
        "tags": [
          "provenance"
        ],
        "operationId": "get_v1_unconfirmed",
        "x-indraft-capability": "crm:read",
        "x-indraft-scopes": [
          "crm:read",
          "crm:write",
          "crm:configure",
          "crm:admin",
          "crm:revert",
          "data:export"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "description": "How many to return. The page bound is published in the schema call, and asking for more is refused rather than quietly truncated."
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "The opaque marker from the previous page. Store it and hand it back; do not parse it. A cursor is only ever emitted when another row really exists, so a page you were given is never empty."
            }
          },
          {
            "name": "objectType",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64,
              "pattern": "^[a-z][a-z0-9_]*$",
              "description": "What is being counted: a canonical type, or the key of a type this workspace defined."
            }
          },
          {
            "name": "assertionKinds",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 120,
              "description": "Which standings to include, comma separated. Confirmed values are what a person has checked, and are what an import cannot overwrite."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "objectType": {
                            "type": "string"
                          },
                          "objectId": {
                            "type": "string"
                          },
                          "field": {
                            "type": "string"
                          },
                          "value": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "integer"
                              },
                              {
                                "type": "boolean"
                              }
                            ]
                          },
                          "assertedAt": {
                            "type": "string"
                          },
                          "actorId": {
                            "type": "string"
                          },
                          "actorLabel": {
                            "type": "string"
                          },
                          "assertionKind": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "objectType",
                          "objectId",
                          "field",
                          "value",
                          "assertedAt",
                          "actorId",
                          "actorLabel",
                          "assertionKind"
                        ],
                        "additionalProperties": true
                      }
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "items",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/unconfirmed:confirm": {
      "post": {
        "summary": "Record that a person has checked a value and agrees with it",
        "description": "A confirmation means somebody checked it, so no token and no agent can make one whatever scopes it carries. The value it records outranks every later import, which is what stops a nightly sync quietly undoing a person's correction.",
        "tags": [
          "unconfirmed"
        ],
        "operationId": "post_v1_unconfirmed_confirm",
        "x-indraft-capability": "crm:write",
        "x-indraft-scopes": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "idempotencyKey": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 200,
                    "description": "Your own name for this write, so retrying it cannot do it twice. Send the same key again and you get the SAME result back rather than a second record, which is what makes a re-run safe after a timeout you never saw the answer to. Derive it from what the write is about, not from the clock: `nightly-sync-halden` retries correctly and a timestamp does not."
                  },
                  "expectedVersion": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "The version you read before deciding to write. If the record has moved since, the write is refused instead of overwriting whatever changed. Send it whenever you read, reasoned, and then wrote: without it the last writer wins and neither of you finds out."
                  },
                  "sourceId": {
                    "type": "string",
                    "description": "The recorded source this claim came from, if one exists. It attaches evidence to the write, so a person reading the field later can see where it came from rather than only who sent it."
                  },
                  "assertionKind": {
                    "type": "string",
                    "enum": [
                      "observed",
                      "inferred",
                      "imported",
                      "user_supplied"
                    ],
                    "description": "HOW YOU KNOW. This is the field the product is built around, so say what is true rather than what is strongest: `observed` you saw it stated directly, `imported` it came from a file or another system, `inferred` you worked it out, `user_supplied` a person told you in so many words. They rank, weakest first: inferred < imported < observed < user_supplied < confirmed. A weaker claim does not overwrite a stronger one; it is reported in `held[]` and the stored value stands, so an unattended re-run converges instead of eroding what somebody checked. `confirmed` is not accepted here: it means a person checked the value, and only a signed-in person can set it."
                  },
                  "attributionLabel": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120,
                    "description": "A short name for the work this write belongs to, shown beside the actor so one credential can distinguish separate jobs. It is recorded as CALLER-SUPPLIED and grants nothing: it changes no permission, no idempotency scope and no quota."
                  },
                  "dryRun": {
                    "type": "boolean",
                    "description": "Report what this write WOULD do and commit nothing. The response carries the same change list, held fields and refusals as the real call, so it is the way to check a risky write, or a whole import, before it lands. Nothing is metered."
                  },
                  "overrideStanding": {
                    "type": "boolean",
                    "description": "Apply this write even when the value standing in the record was asserted more strongly than this one. Absent means no, which is the safe answer for a re-run. WITHOUT IT, a write can be accepted and change nothing: precedence is confirmed > user_supplied > observed > imported > inferred, and a weaker claim leaves the standing value in place and reports the field in `held[]` rather than failing. That is the whole of why a write can return 200 and not take. WITH it, this write wins regardless of what it is overruling, INCLUDING a value a person confirmed, so an agent that sets it by default has switched the provenance mechanism off. Set it per write, when the caller knows its claim supersedes what is there."
                  },
                  "objectType": {
                    "type": "string",
                    "enum": [
                      "company",
                      "contact",
                      "opportunity",
                      "task"
                    ],
                    "description": "What is being counted: a canonical type, or the key of a type this workspace defined."
                  },
                  "id": {
                    "type": "string",
                    "minLength": 1
                  },
                  "field": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120,
                    "description": "The field to reduce. Refused when the function needs one and the field cannot carry it, rather than returning zero."
                  },
                  "value": {
                    "type": "string",
                    "maxLength": 4000
                  }
                },
                "required": [
                  "objectType",
                  "id",
                  "field",
                  "value"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "mutation": {
                      "type": "object",
                      "properties": {
                        "mutationId": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "created",
                            "updated",
                            "matched",
                            "archived",
                            "merged",
                            "reverted",
                            "noop"
                          ],
                          "description": "What the write did. `noop` means it was accepted and changed nothing, because every value it carried already matched what was stored. IT IS NOT METERED: a noop does not count against your monthly change allowance, so a nightly sync that finds nothing new costs nothing. Neither does a write that only REDUCES what a workspace holds. `matched` means an upsert found an existing record on real identity evidence rather than creating a second one; `reverted` and `merged` are the undo and duplicate paths, and both are ordinary writes that count."
                        },
                        "targetId": {
                          "type": "string"
                        },
                        "record": {},
                        "changes": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "before": {},
                              "after": {}
                            },
                            "required": [
                              "field"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "held": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "kept": {},
                              "proposed": {},
                              "standing": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "incoming": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "actorId": {
                                "type": "string",
                                "minLength": 1
                              },
                              "assertedAt": {
                                "type": "string",
                                "minLength": 1
                              }
                            },
                            "required": [
                              "field",
                              "standing",
                              "incoming",
                              "actorId",
                              "assertedAt"
                            ],
                            "additionalProperties": false
                          },
                          "description": "Fields this write asked to change and did not, because the value standing in the record was asserted more strongly. THIS IS WHY A WRITE CAN RETURN 200 AND CHANGE NOTHING, and a caller that ignores it will believe it wrote something it did not. Precedence is confirmed > user_supplied > observed > imported > inferred, and a write carrying no `assertionKind` is weakest of all. Each entry reports the field, what the record still says, what you proposed, which claim won, and who made it. Send `overrideStanding` to write anyway, per write, when your claim really does supersede theirs."
                        },
                        "matchedBy": {
                          "type": "string",
                          "enum": [
                            "email",
                            "domain",
                            "external_id",
                            "idempotency_key",
                            "explicit_id"
                          ]
                        },
                        "reversible": {
                          "type": "boolean"
                        },
                        "replayed": {
                          "type": "boolean"
                        },
                        "dryRun": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "mutationId",
                        "status",
                        "reversible"
                      ],
                      "additionalProperties": false
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "mutation",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "A product quota is spent, or the subscription is not active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A conflict the caller can resolve: a stale expectedVersion, an idempotency key reused for different input, an ambiguous or duplicate identity, or a merge that no longer applies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The body, or a single record inside it, exceeds its bound.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "507": {
            "description": "The workspace is at its storage ceiling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/stale": {
      "get": {
        "summary": "Records nobody has touched for a while, quietest first",
        "description": "Records nobody has touched for a while, quietest first, with how many days each has been quiet. Use this to find what has stopped being maintained: the change feed tells you what DID happen, and this tells you what did not. Returns a list and dates, never a score.",
        "tags": [
          "reporting"
        ],
        "operationId": "get_v1_stale",
        "x-indraft-capability": "crm:read",
        "x-indraft-scopes": [
          "crm:read",
          "crm:write",
          "crm:configure",
          "crm:admin",
          "crm:revert",
          "data:export"
        ],
        "parameters": [
          {
            "name": "quietForDays",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 3650,
              "description": "How long counts as quiet. A record nobody has ever touched is the quietest of all and is included, rather than being excluded by a join."
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "description": "How many to return. The page bound is published in the schema call, and asking for more is refused rather than quietly truncated."
            }
          },
          {
            "name": "objectType",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 48,
              "description": "What is being counted: a canonical type, or the key of a type this workspace defined."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "quietForDays": {
                      "type": "integer"
                    },
                    "counts": {
                      "type": "object",
                      "additionalProperties": {
                        "type": "integer"
                      }
                    },
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "objectType": {
                            "type": "string"
                          },
                          "id": {
                            "type": "string"
                          },
                          "label": {
                            "type": "string"
                          },
                          "updatedAt": {
                            "type": "string"
                          },
                          "quietDays": {
                            "type": "integer"
                          }
                        },
                        "required": [
                          "objectType",
                          "id",
                          "label",
                          "updatedAt",
                          "quietDays"
                        ],
                        "additionalProperties": true
                      }
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "quietForDays",
                    "counts",
                    "items",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/object-types": {
      "get": {
        "summary": "Every custom object type this workspace has defined",
        "description": "The custom object types this workspace has defined, with their fields and relationships. Canonical types (company, contact, opportunity, interaction, task) are not here: they are in get_crm_schema and mean the same thing in every workspace.",
        "tags": [
          "custom objects"
        ],
        "operationId": "get_v1_object_types",
        "x-indraft-capability": "crm:read",
        "x-indraft-scopes": [
          "crm:read",
          "crm:write",
          "crm:configure",
          "crm:admin",
          "crm:revert",
          "data:export"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "objectTypes": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "key": {
                            "type": "string"
                          },
                          "displayName": {
                            "type": "string"
                          },
                          "displayNamePlural": {
                            "type": "string"
                          },
                          "idPrefix": {
                            "type": "string"
                          },
                          "identity": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string"
                              },
                              "normalize": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "field",
                              "normalize"
                            ],
                            "additionalProperties": true
                          },
                          "pendingIdentity": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string"
                              },
                              "normalize": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "field",
                              "normalize"
                            ],
                            "additionalProperties": true
                          },
                          "fields": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "key": {
                                  "type": "string"
                                },
                                "label": {
                                  "type": "string"
                                },
                                "valueType": {
                                  "type": "string"
                                },
                                "required": {
                                  "type": "boolean"
                                },
                                "indexed": {
                                  "type": "boolean"
                                },
                                "enumOptions": {
                                  "type": "array",
                                  "items": {
                                    "type": "string"
                                  }
                                }
                              },
                              "required": [
                                "key",
                                "label",
                                "valueType"
                              ],
                              "additionalProperties": true
                            }
                          },
                          "relationships": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "name": {
                                  "type": "string"
                                },
                                "label": {
                                  "type": "string"
                                },
                                "target": {
                                  "type": "string"
                                },
                                "cardinality": {
                                  "type": "string"
                                }
                              },
                              "required": [
                                "name",
                                "label",
                                "target",
                                "cardinality"
                              ],
                              "additionalProperties": true
                            }
                          },
                          "archivedAt": {
                            "type": "string"
                          },
                          "pipelines": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "id": {
                                  "type": "string"
                                },
                                "name": {
                                  "type": "string"
                                },
                                "stages": {
                                  "type": "array",
                                  "items": {
                                    "type": "object",
                                    "properties": {
                                      "id": {
                                        "type": "string"
                                      },
                                      "name": {
                                        "type": "string"
                                      },
                                      "stageKind": {
                                        "type": "string",
                                        "enum": [
                                          "open",
                                          "won",
                                          "lost"
                                        ]
                                      },
                                      "position": {
                                        "type": "integer"
                                      }
                                    },
                                    "required": [
                                      "id",
                                      "name",
                                      "stageKind",
                                      "position"
                                    ],
                                    "additionalProperties": true
                                  }
                                }
                              },
                              "required": [
                                "id",
                                "name",
                                "stages"
                              ],
                              "additionalProperties": true
                            }
                          }
                        },
                        "required": [
                          "key",
                          "displayName",
                          "displayNamePlural",
                          "idPrefix",
                          "identity",
                          "pendingIdentity",
                          "fields",
                          "archivedAt"
                        ],
                        "additionalProperties": true
                      }
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "objectTypes",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Define a custom object type",
        "description": "Define a NEW object type this workspace needs and Indraft does not have: a Candidate, a Campaign, a Unit. To change a type that already exists, use alter_object_type. Typed fields and named relationships to existing records. The canonical types cannot be redefined this way, and a type you define carries the same history, attribution, and undo as everything else.",
        "tags": [
          "custom objects"
        ],
        "operationId": "post_v1_object_types",
        "x-indraft-capability": "crm:configure",
        "x-indraft-scopes": [
          "crm:configure",
          "crm:admin"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "idempotencyKey": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 200,
                    "description": "Your own name for this write, so retrying it cannot do it twice. Send the same key again and you get the SAME result back rather than a second record, which is what makes a re-run safe after a timeout you never saw the answer to. Derive it from what the write is about, not from the clock: `nightly-sync-halden` retries correctly and a timestamp does not."
                  },
                  "expectedVersion": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "The version you read before deciding to write. If the record has moved since, the write is refused instead of overwriting whatever changed. Send it whenever you read, reasoned, and then wrote: without it the last writer wins and neither of you finds out."
                  },
                  "sourceId": {
                    "type": "string",
                    "description": "The recorded source this claim came from, if one exists. It attaches evidence to the write, so a person reading the field later can see where it came from rather than only who sent it."
                  },
                  "assertionKind": {
                    "type": "string",
                    "enum": [
                      "observed",
                      "inferred",
                      "imported",
                      "user_supplied"
                    ],
                    "description": "HOW YOU KNOW. This is the field the product is built around, so say what is true rather than what is strongest: `observed` you saw it stated directly, `imported` it came from a file or another system, `inferred` you worked it out, `user_supplied` a person told you in so many words. They rank, weakest first: inferred < imported < observed < user_supplied < confirmed. A weaker claim does not overwrite a stronger one; it is reported in `held[]` and the stored value stands, so an unattended re-run converges instead of eroding what somebody checked. `confirmed` is not accepted here: it means a person checked the value, and only a signed-in person can set it."
                  },
                  "attributionLabel": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120,
                    "description": "A short name for the work this write belongs to, shown beside the actor so one credential can distinguish separate jobs. It is recorded as CALLER-SUPPLIED and grants nothing: it changes no permission, no idempotency scope and no quota."
                  },
                  "dryRun": {
                    "type": "boolean",
                    "description": "Report what this write WOULD do and commit nothing. The response carries the same change list, held fields and refusals as the real call, so it is the way to check a risky write, or a whole import, before it lands. Nothing is metered."
                  },
                  "overrideStanding": {
                    "type": "boolean",
                    "description": "Apply this write even when the value standing in the record was asserted more strongly than this one. Absent means no, which is the safe answer for a re-run. WITHOUT IT, a write can be accepted and change nothing: precedence is confirmed > user_supplied > observed > imported > inferred, and a weaker claim leaves the standing value in place and reports the field in `held[]` rather than failing. That is the whole of why a write can return 200 and not take. WITH it, this write wins regardless of what it is overruling, INCLUDING a value a person confirmed, so an agent that sets it by default has switched the provenance mechanism off. Set it per write, when the caller knows its claim supersedes what is there."
                  },
                  "key": {
                    "type": "string",
                    "pattern": "^[a-z][a-z0-9_]{0,47}$"
                  },
                  "displayName": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200,
                    "description": "What one record of this type is called, singular. A person reads this."
                  },
                  "displayNamePlural": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200,
                    "description": "The plural, for lists. Left out, a reasonable one is derived."
                  },
                  "idPrefix": {
                    "type": "string",
                    "pattern": "^[a-z][a-z0-9]{1,7}$"
                  },
                  "fields": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "key": {
                          "type": "string",
                          "pattern": "^[a-z][a-z0-9_]{0,47}$",
                          "description": "The name this field is addressed by, in every later read and write. Lower-case, starting with a letter. It is permanent: renaming a field is not offered, because every value already written is addressed by it."
                        },
                        "label": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 200,
                          "description": "What a person sees. Change this freely; it names nothing."
                        },
                        "valueType": {
                          "type": "string",
                          "enum": [
                            "text",
                            "number",
                            "boolean",
                            "timestamp",
                            "enum",
                            "json"
                          ],
                          "description": "What kind of value this holds. Permanent, and chosen for what the field IS rather than for what is convenient to send: a date stored as text cannot be sorted, filtered by range, or counted by month, and converting it later is not offered."
                        },
                        "required": {
                          "type": "boolean",
                          "description": "Whether a record without this value can exist. Applies to records written from now on; records already stored are not made invalid by it."
                        },
                        "indexed": {
                          "type": "boolean",
                          "description": "Set this on a field you will filter or sort by. Without it those still work and get slower as the type fills up. There is a published cap on how many fields one type may index, so spend it on the ones a person actually searches."
                        },
                        "enumOptions": {
                          "type": "array",
                          "items": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 200
                          },
                          "maxItems": 100,
                          "description": "The allowed values, required when valueType is enum and refused otherwise. A value outside this list is rejected rather than stored, so state every option you expect."
                        }
                      },
                      "required": [
                        "key",
                        "label",
                        "valueType"
                      ],
                      "additionalProperties": false
                    },
                    "minItems": 1,
                    "maxItems": 100
                  },
                  "relationships": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "name": {
                          "type": "string",
                          "pattern": "^[a-z][a-z0-9_]{0,47}$",
                          "description": "How this link is addressed when writing a record. Permanent, like a field key."
                        },
                        "label": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 200,
                          "description": "What a person sees for this link."
                        },
                        "target": {
                          "type": "string",
                          "pattern": "^[a-z][a-z0-9_]{0,47}$",
                          "description": "What it points at: a canonical type (company, contact, opportunity, task) or the key of another type this workspace defined. The target must already exist."
                        },
                        "cardinality": {
                          "type": "string",
                          "enum": [
                            "one",
                            "many"
                          ],
                          "description": "Whether one record may point at one of the target or at many. Pick from the record's side: an Application belongs to one Candidate and a Candidate has many Applications, so on Application this is one."
                        }
                      },
                      "required": [
                        "name",
                        "label",
                        "target",
                        "cardinality"
                      ],
                      "additionalProperties": false
                    },
                    "maxItems": 25
                  },
                  "identity": {
                    "type": "object",
                    "properties": {
                      "field": {
                        "type": "string",
                        "pattern": "^[a-z][a-z0-9_]{0,47}$",
                        "description": "The declared field whose value says two records are the same record. It must be a field of this type. Declare one only where the value really is unique per record: an upsert then matches on it instead of creating a second copy."
                      },
                      "normalize": {
                        "type": "string",
                        "enum": [
                          "exact",
                          "trimmed_casefold",
                          "email",
                          "domain",
                          "phone"
                        ],
                        "description": "How the value is compared. `exact` compares as stored; `trimmed_casefold` ignores surrounding space and letter case; `email`, `domain` and `phone` apply the same rules the canonical types use, so a Candidate keyed on email and a contact keyed on email agree about what one address is."
                      }
                    },
                    "required": [
                      "field",
                      "normalize"
                    ],
                    "additionalProperties": false
                  }
                },
                "required": [
                  "key",
                  "displayName",
                  "idPrefix",
                  "fields"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "objectType": {
                      "type": "object",
                      "properties": {
                        "key": {
                          "type": "string"
                        },
                        "displayName": {
                          "type": "string"
                        },
                        "displayNamePlural": {
                          "type": "string"
                        },
                        "idPrefix": {
                          "type": "string"
                        },
                        "identity": {
                          "type": "object",
                          "properties": {
                            "field": {
                              "type": "string"
                            },
                            "normalize": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "field",
                            "normalize"
                          ],
                          "additionalProperties": true
                        },
                        "pendingIdentity": {
                          "type": "object",
                          "properties": {
                            "field": {
                              "type": "string"
                            },
                            "normalize": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "field",
                            "normalize"
                          ],
                          "additionalProperties": true
                        },
                        "fields": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "key": {
                                "type": "string"
                              },
                              "label": {
                                "type": "string"
                              },
                              "valueType": {
                                "type": "string"
                              },
                              "required": {
                                "type": "boolean"
                              },
                              "indexed": {
                                "type": "boolean"
                              },
                              "enumOptions": {
                                "type": "array",
                                "items": {
                                  "type": "string"
                                }
                              }
                            },
                            "required": [
                              "key",
                              "label",
                              "valueType"
                            ],
                            "additionalProperties": true
                          }
                        },
                        "relationships": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "name": {
                                "type": "string"
                              },
                              "label": {
                                "type": "string"
                              },
                              "target": {
                                "type": "string"
                              },
                              "cardinality": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "name",
                              "label",
                              "target",
                              "cardinality"
                            ],
                            "additionalProperties": true
                          }
                        },
                        "archivedAt": {
                          "type": "string"
                        },
                        "pipelines": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string"
                              },
                              "name": {
                                "type": "string"
                              },
                              "stages": {
                                "type": "array",
                                "items": {
                                  "type": "object",
                                  "properties": {
                                    "id": {
                                      "type": "string"
                                    },
                                    "name": {
                                      "type": "string"
                                    },
                                    "stageKind": {
                                      "type": "string",
                                      "enum": [
                                        "open",
                                        "won",
                                        "lost"
                                      ]
                                    },
                                    "position": {
                                      "type": "integer"
                                    }
                                  },
                                  "required": [
                                    "id",
                                    "name",
                                    "stageKind",
                                    "position"
                                  ],
                                  "additionalProperties": true
                                }
                              }
                            },
                            "required": [
                              "id",
                              "name",
                              "stages"
                            ],
                            "additionalProperties": true
                          }
                        }
                      },
                      "required": [
                        "key",
                        "displayName",
                        "displayNamePlural",
                        "idPrefix",
                        "identity",
                        "pendingIdentity",
                        "fields",
                        "archivedAt"
                      ],
                      "additionalProperties": true
                    },
                    "mutation": {
                      "type": "object",
                      "properties": {
                        "mutationId": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "created",
                            "updated",
                            "matched",
                            "archived",
                            "merged",
                            "reverted",
                            "noop"
                          ],
                          "description": "What the write did. `noop` means it was accepted and changed nothing, because every value it carried already matched what was stored. IT IS NOT METERED: a noop does not count against your monthly change allowance, so a nightly sync that finds nothing new costs nothing. Neither does a write that only REDUCES what a workspace holds. `matched` means an upsert found an existing record on real identity evidence rather than creating a second one; `reverted` and `merged` are the undo and duplicate paths, and both are ordinary writes that count."
                        },
                        "targetId": {
                          "type": "string"
                        },
                        "record": {},
                        "changes": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "before": {},
                              "after": {}
                            },
                            "required": [
                              "field"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "held": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "kept": {},
                              "proposed": {},
                              "standing": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "incoming": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "actorId": {
                                "type": "string",
                                "minLength": 1
                              },
                              "assertedAt": {
                                "type": "string",
                                "minLength": 1
                              }
                            },
                            "required": [
                              "field",
                              "standing",
                              "incoming",
                              "actorId",
                              "assertedAt"
                            ],
                            "additionalProperties": false
                          },
                          "description": "Fields this write asked to change and did not, because the value standing in the record was asserted more strongly. THIS IS WHY A WRITE CAN RETURN 200 AND CHANGE NOTHING, and a caller that ignores it will believe it wrote something it did not. Precedence is confirmed > user_supplied > observed > imported > inferred, and a write carrying no `assertionKind` is weakest of all. Each entry reports the field, what the record still says, what you proposed, which claim won, and who made it. Send `overrideStanding` to write anyway, per write, when your claim really does supersede theirs."
                        },
                        "matchedBy": {
                          "type": "string",
                          "enum": [
                            "email",
                            "domain",
                            "external_id",
                            "idempotency_key",
                            "explicit_id"
                          ]
                        },
                        "reversible": {
                          "type": "boolean"
                        },
                        "replayed": {
                          "type": "boolean"
                        },
                        "dryRun": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "mutationId",
                        "status",
                        "reversible"
                      ],
                      "additionalProperties": false
                    },
                    "identityBackfill": {
                      "type": "object",
                      "properties": {
                        "normalized": {
                          "type": "integer"
                        },
                        "remaining": {
                          "type": "integer"
                        }
                      },
                      "required": [
                        "normalized",
                        "remaining"
                      ],
                      "additionalProperties": true
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "objectType",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "A product quota is spent, or the subscription is not active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A conflict the caller can resolve: a stale expectedVersion, an idempotency key reused for different input, an ambiguous or duplicate identity, or a merge that no longer applies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The body, or a single record inside it, exceeds its bound.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "507": {
            "description": "The workspace is at its storage ceiling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/object-types/{type}": {
      "patch": {
        "summary": "Add a field to a custom type, or archive and restore it",
        "description": "Change a type this workspace has ALREADY defined; use configure_object_type to create one. Add a field, declare which field is its identity so duplicates are refused rather than created, or archive and restore it. Declaring an identity over records that already share a value is refused and names them, so nothing is merged by surprise.",
        "tags": [
          "custom objects"
        ],
        "operationId": "patch_v1_object_types__type_",
        "x-indraft-capability": "crm:configure",
        "x-indraft-scopes": [
          "crm:configure",
          "crm:admin"
        ],
        "parameters": [
          {
            "name": "type",
            "in": "path",
            "required": true,
            "description": "The key of a type this workspace defined, as given when the type was created. Canonical types are not addressed this way.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "idempotencyKey": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 200,
                    "description": "Your own name for this write, so retrying it cannot do it twice. Send the same key again and you get the SAME result back rather than a second record, which is what makes a re-run safe after a timeout you never saw the answer to. Derive it from what the write is about, not from the clock: `nightly-sync-halden` retries correctly and a timestamp does not."
                  },
                  "expectedVersion": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "The version you read before deciding to write. If the record has moved since, the write is refused instead of overwriting whatever changed. Send it whenever you read, reasoned, and then wrote: without it the last writer wins and neither of you finds out."
                  },
                  "sourceId": {
                    "type": "string",
                    "description": "The recorded source this claim came from, if one exists. It attaches evidence to the write, so a person reading the field later can see where it came from rather than only who sent it."
                  },
                  "assertionKind": {
                    "type": "string",
                    "enum": [
                      "observed",
                      "inferred",
                      "imported",
                      "user_supplied"
                    ],
                    "description": "HOW YOU KNOW. This is the field the product is built around, so say what is true rather than what is strongest: `observed` you saw it stated directly, `imported` it came from a file or another system, `inferred` you worked it out, `user_supplied` a person told you in so many words. They rank, weakest first: inferred < imported < observed < user_supplied < confirmed. A weaker claim does not overwrite a stronger one; it is reported in `held[]` and the stored value stands, so an unattended re-run converges instead of eroding what somebody checked. `confirmed` is not accepted here: it means a person checked the value, and only a signed-in person can set it."
                  },
                  "attributionLabel": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120,
                    "description": "A short name for the work this write belongs to, shown beside the actor so one credential can distinguish separate jobs. It is recorded as CALLER-SUPPLIED and grants nothing: it changes no permission, no idempotency scope and no quota."
                  },
                  "dryRun": {
                    "type": "boolean",
                    "description": "Report what this write WOULD do and commit nothing. The response carries the same change list, held fields and refusals as the real call, so it is the way to check a risky write, or a whole import, before it lands. Nothing is metered."
                  },
                  "overrideStanding": {
                    "type": "boolean",
                    "description": "Apply this write even when the value standing in the record was asserted more strongly than this one. Absent means no, which is the safe answer for a re-run. WITHOUT IT, a write can be accepted and change nothing: precedence is confirmed > user_supplied > observed > imported > inferred, and a weaker claim leaves the standing value in place and reports the field in `held[]` rather than failing. That is the whole of why a write can return 200 and not take. WITH it, this write wins regardless of what it is overruling, INCLUDING a value a person confirmed, so an agent that sets it by default has switched the provenance mechanism off. Set it per write, when the caller knows its claim supersedes what is there."
                  },
                  "addField": {
                    "type": "object",
                    "properties": {
                      "key": {
                        "type": "string",
                        "pattern": "^[a-z][a-z0-9_]{0,47}$",
                        "description": "The name this field is addressed by, in every later read and write. Lower-case, starting with a letter. It is permanent: renaming a field is not offered, because every value already written is addressed by it."
                      },
                      "label": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 200,
                        "description": "What a person sees. Change this freely; it names nothing."
                      },
                      "valueType": {
                        "type": "string",
                        "enum": [
                          "text",
                          "number",
                          "boolean",
                          "timestamp",
                          "enum",
                          "json"
                        ],
                        "description": "What kind of value this holds. Permanent, and chosen for what the field IS rather than for what is convenient to send: a date stored as text cannot be sorted, filtered by range, or counted by month, and converting it later is not offered."
                      },
                      "required": {
                        "type": "boolean",
                        "description": "Whether a record without this value can exist. Applies to records written from now on; records already stored are not made invalid by it."
                      },
                      "indexed": {
                        "type": "boolean",
                        "description": "Set this on a field you will filter or sort by. Without it those still work and get slower as the type fills up. There is a published cap on how many fields one type may index, so spend it on the ones a person actually searches."
                      },
                      "enumOptions": {
                        "type": "array",
                        "items": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 200
                        },
                        "maxItems": 100,
                        "description": "The allowed values, required when valueType is enum and refused otherwise. A value outside this list is rejected rather than stored, so state every option you expect."
                      }
                    },
                    "required": [
                      "key",
                      "label",
                      "valueType"
                    ],
                    "additionalProperties": false
                  },
                  "archived": {
                    "type": "boolean"
                  },
                  "identity": {
                    "type": "object",
                    "properties": {
                      "field": {
                        "type": "string",
                        "pattern": "^[a-z][a-z0-9_]{0,47}$",
                        "description": "The declared field whose value says two records are the same record. It must be a field of this type. Declare one only where the value really is unique per record: an upsert then matches on it instead of creating a second copy."
                      },
                      "normalize": {
                        "type": "string",
                        "enum": [
                          "exact",
                          "trimmed_casefold",
                          "email",
                          "domain",
                          "phone"
                        ],
                        "description": "How the value is compared. `exact` compares as stored; `trimmed_casefold` ignores surrounding space and letter case; `email`, `domain` and `phone` apply the same rules the canonical types use, so a Candidate keyed on email and a contact keyed on email agree about what one address is."
                      }
                    },
                    "required": [
                      "field",
                      "normalize"
                    ],
                    "additionalProperties": false
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "objectType": {
                      "type": "object",
                      "properties": {
                        "key": {
                          "type": "string"
                        },
                        "displayName": {
                          "type": "string"
                        },
                        "displayNamePlural": {
                          "type": "string"
                        },
                        "idPrefix": {
                          "type": "string"
                        },
                        "identity": {
                          "type": "object",
                          "properties": {
                            "field": {
                              "type": "string"
                            },
                            "normalize": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "field",
                            "normalize"
                          ],
                          "additionalProperties": true
                        },
                        "pendingIdentity": {
                          "type": "object",
                          "properties": {
                            "field": {
                              "type": "string"
                            },
                            "normalize": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "field",
                            "normalize"
                          ],
                          "additionalProperties": true
                        },
                        "fields": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "key": {
                                "type": "string"
                              },
                              "label": {
                                "type": "string"
                              },
                              "valueType": {
                                "type": "string"
                              },
                              "required": {
                                "type": "boolean"
                              },
                              "indexed": {
                                "type": "boolean"
                              },
                              "enumOptions": {
                                "type": "array",
                                "items": {
                                  "type": "string"
                                }
                              }
                            },
                            "required": [
                              "key",
                              "label",
                              "valueType"
                            ],
                            "additionalProperties": true
                          }
                        },
                        "relationships": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "name": {
                                "type": "string"
                              },
                              "label": {
                                "type": "string"
                              },
                              "target": {
                                "type": "string"
                              },
                              "cardinality": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "name",
                              "label",
                              "target",
                              "cardinality"
                            ],
                            "additionalProperties": true
                          }
                        },
                        "archivedAt": {
                          "type": "string"
                        },
                        "pipelines": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string"
                              },
                              "name": {
                                "type": "string"
                              },
                              "stages": {
                                "type": "array",
                                "items": {
                                  "type": "object",
                                  "properties": {
                                    "id": {
                                      "type": "string"
                                    },
                                    "name": {
                                      "type": "string"
                                    },
                                    "stageKind": {
                                      "type": "string",
                                      "enum": [
                                        "open",
                                        "won",
                                        "lost"
                                      ]
                                    },
                                    "position": {
                                      "type": "integer"
                                    }
                                  },
                                  "required": [
                                    "id",
                                    "name",
                                    "stageKind",
                                    "position"
                                  ],
                                  "additionalProperties": true
                                }
                              }
                            },
                            "required": [
                              "id",
                              "name",
                              "stages"
                            ],
                            "additionalProperties": true
                          }
                        }
                      },
                      "required": [
                        "key",
                        "displayName",
                        "displayNamePlural",
                        "idPrefix",
                        "identity",
                        "pendingIdentity",
                        "fields",
                        "archivedAt"
                      ],
                      "additionalProperties": true
                    },
                    "mutation": {
                      "type": "object",
                      "properties": {
                        "mutationId": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "created",
                            "updated",
                            "matched",
                            "archived",
                            "merged",
                            "reverted",
                            "noop"
                          ],
                          "description": "What the write did. `noop` means it was accepted and changed nothing, because every value it carried already matched what was stored. IT IS NOT METERED: a noop does not count against your monthly change allowance, so a nightly sync that finds nothing new costs nothing. Neither does a write that only REDUCES what a workspace holds. `matched` means an upsert found an existing record on real identity evidence rather than creating a second one; `reverted` and `merged` are the undo and duplicate paths, and both are ordinary writes that count."
                        },
                        "targetId": {
                          "type": "string"
                        },
                        "record": {},
                        "changes": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "before": {},
                              "after": {}
                            },
                            "required": [
                              "field"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "held": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "kept": {},
                              "proposed": {},
                              "standing": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "incoming": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "actorId": {
                                "type": "string",
                                "minLength": 1
                              },
                              "assertedAt": {
                                "type": "string",
                                "minLength": 1
                              }
                            },
                            "required": [
                              "field",
                              "standing",
                              "incoming",
                              "actorId",
                              "assertedAt"
                            ],
                            "additionalProperties": false
                          },
                          "description": "Fields this write asked to change and did not, because the value standing in the record was asserted more strongly. THIS IS WHY A WRITE CAN RETURN 200 AND CHANGE NOTHING, and a caller that ignores it will believe it wrote something it did not. Precedence is confirmed > user_supplied > observed > imported > inferred, and a write carrying no `assertionKind` is weakest of all. Each entry reports the field, what the record still says, what you proposed, which claim won, and who made it. Send `overrideStanding` to write anyway, per write, when your claim really does supersede theirs."
                        },
                        "matchedBy": {
                          "type": "string",
                          "enum": [
                            "email",
                            "domain",
                            "external_id",
                            "idempotency_key",
                            "explicit_id"
                          ]
                        },
                        "reversible": {
                          "type": "boolean"
                        },
                        "replayed": {
                          "type": "boolean"
                        },
                        "dryRun": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "mutationId",
                        "status",
                        "reversible"
                      ],
                      "additionalProperties": false
                    },
                    "identityBackfill": {
                      "type": "object",
                      "properties": {
                        "normalized": {
                          "type": "integer"
                        },
                        "remaining": {
                          "type": "integer"
                        }
                      },
                      "required": [
                        "normalized",
                        "remaining"
                      ],
                      "additionalProperties": true
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "objectType",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "A product quota is spent, or the subscription is not active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such record, or it belongs to another workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A conflict the caller can resolve: a stale expectedVersion, an idempotency key reused for different input, an ambiguous or duplicate identity, or a merge that no longer applies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The body, or a single record inside it, exceeds its bound.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "507": {
            "description": "The workspace is at its storage ceiling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Permanently destroy an archived custom type, its table, and its records",
        "description": "Drops the table and everything in it. Only an archived type can be destroyed, which is the deliberate pause between deciding and losing, and the ledger rows about a destroyed type are exactly what a drop cannot preserve.",
        "tags": [
          "custom objects"
        ],
        "operationId": "delete_v1_object_types__type_",
        "x-indraft-capability": "workspace:delete",
        "x-indraft-scopes": [],
        "parameters": [
          {
            "name": "type",
            "in": "path",
            "required": true,
            "description": "The key of a type this workspace defined, as given when the type was created. Canonical types are not addressed this way.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "destroyed": {
                      "type": "object",
                      "properties": {
                        "key": {
                          "type": "string"
                        },
                        "rows": {
                          "type": "integer"
                        },
                        "tables": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        }
                      },
                      "required": [
                        "key",
                        "rows",
                        "tables"
                      ],
                      "additionalProperties": true
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "destroyed",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "A product quota is spent, or the subscription is not active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such record, or it belongs to another workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A conflict the caller can resolve: a stale expectedVersion, an idempotency key reused for different input, an ambiguous or duplicate identity, or a merge that no longer applies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "507": {
            "description": "The workspace is at its storage ceiling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/objects/{type}": {
      "get": {
        "summary": "Every record of one custom type, newest first",
        "description": "Records of one custom object type, newest first, with a cursor for the next page. The type must be one this workspace defined; ask get_crm_schema or list_object_types for the names. Filters and sorts exactly like the built-in lists, on the fields the type declared indexed.",
        "tags": [
          "custom objects"
        ],
        "operationId": "get_v1_objects__type_",
        "x-indraft-capability": "crm:read",
        "x-indraft-scopes": [
          "crm:read",
          "crm:write",
          "crm:configure",
          "crm:admin",
          "crm:revert",
          "data:export"
        ],
        "parameters": [
          {
            "name": "type",
            "in": "path",
            "required": true,
            "description": "The key of a type this workspace defined, as given when the type was created. Canonical types are not addressed this way.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "description": "How many to return. The page bound is published in the schema call, and asking for more is refused rather than quietly truncated."
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "The opaque marker from the previous page. Store it and hand it back; do not parse it. A cursor is only ever emitted when another row really exists, so a page you were given is never empty."
            }
          },
          {
            "name": "updatedSince",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 40,
              "description": "Only rows changed after this instant. The incremental read: without it a service syncing a large workspace has to walk all of it every time."
            }
          },
          {
            "name": "lastInteractionBefore",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 40,
              "description": "Only records whose most recent interaction is older than this, including those with none at all."
            }
          },
          {
            "name": "includeArchived",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "Include archived rows. Off by default, because a list is what you are working on and history is somewhere you go deliberately."
            }
          },
          {
            "name": "filter",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 560
                },
                {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 560
                  },
                  "maxItems": 8
                }
              ],
              "description": "Predicates, all of which must hold, written field:op:value. Only fields an index serves are accepted, and asking for one that is not names the ones that are."
            }
          },
          {
            "name": "or",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 560
                },
                {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 560
                  },
                  "maxItems": 4
                }
              ],
              "description": "Alternatives, ORed with each other and ANDed with filter. One level and never a tree: owned by me or owned by nobody is the question people ask, and anything deeper has a cost the caller cannot read off it."
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 65,
              "description": "A field to order by, with a leading minus for descending. Indexed fields only, for the same reason as filter."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "version": {
                            "type": "integer"
                          },
                          "createdAt": {
                            "type": "string"
                          },
                          "updatedAt": {
                            "type": "string"
                          },
                          "archivedAt": {
                            "type": "string"
                          },
                          "values": {
                            "type": "object",
                            "additionalProperties": {}
                          },
                          "links": {
                            "type": "object",
                            "additionalProperties": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              }
                            }
                          },
                          "lastActor": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string"
                              },
                              "kind": {
                                "type": "string",
                                "enum": [
                                  "human",
                                  "agent",
                                  "api_token",
                                  "system"
                                ]
                              },
                              "label": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "id",
                              "kind",
                              "label"
                            ],
                            "additionalProperties": true
                          },
                          "stage": {
                            "type": "object",
                            "properties": {
                              "pipelineId": {
                                "type": "string"
                              },
                              "stageId": {
                                "type": "string"
                              },
                              "status": {
                                "type": "string",
                                "enum": [
                                  "open",
                                  "won",
                                  "lost"
                                ]
                              }
                            },
                            "required": [
                              "pipelineId",
                              "stageId",
                              "status"
                            ],
                            "additionalProperties": true
                          }
                        },
                        "required": [
                          "id",
                          "version",
                          "createdAt",
                          "updatedAt",
                          "archivedAt",
                          "values",
                          "links"
                        ],
                        "additionalProperties": true
                      }
                    },
                    "nextCursor": {
                      "type": "string"
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "items",
                    "nextCursor",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such record, or it belongs to another workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Create a record of a custom type",
        "description": "Create or update one record of a custom object type. Supply only fields the type declares; an undeclared field is refused rather than ignored, so nothing you send goes missing silently.",
        "tags": [
          "custom objects"
        ],
        "operationId": "post_v1_objects__type_",
        "x-indraft-capability": "crm:write",
        "x-indraft-scopes": [
          "crm:write",
          "crm:admin"
        ],
        "parameters": [
          {
            "name": "type",
            "in": "path",
            "required": true,
            "description": "The key of a type this workspace defined, as given when the type was created. Canonical types are not addressed this way.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "idempotencyKey": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 200,
                    "description": "Your own name for this write, so retrying it cannot do it twice. Send the same key again and you get the SAME result back rather than a second record, which is what makes a re-run safe after a timeout you never saw the answer to. Derive it from what the write is about, not from the clock: `nightly-sync-halden` retries correctly and a timestamp does not."
                  },
                  "expectedVersion": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "The version you read before deciding to write. If the record has moved since, the write is refused instead of overwriting whatever changed. Send it whenever you read, reasoned, and then wrote: without it the last writer wins and neither of you finds out."
                  },
                  "sourceId": {
                    "type": "string",
                    "description": "The recorded source this claim came from, if one exists. It attaches evidence to the write, so a person reading the field later can see where it came from rather than only who sent it."
                  },
                  "assertionKind": {
                    "type": "string",
                    "enum": [
                      "observed",
                      "inferred",
                      "imported",
                      "user_supplied"
                    ],
                    "description": "HOW YOU KNOW. This is the field the product is built around, so say what is true rather than what is strongest: `observed` you saw it stated directly, `imported` it came from a file or another system, `inferred` you worked it out, `user_supplied` a person told you in so many words. They rank, weakest first: inferred < imported < observed < user_supplied < confirmed. A weaker claim does not overwrite a stronger one; it is reported in `held[]` and the stored value stands, so an unattended re-run converges instead of eroding what somebody checked. `confirmed` is not accepted here: it means a person checked the value, and only a signed-in person can set it."
                  },
                  "attributionLabel": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120,
                    "description": "A short name for the work this write belongs to, shown beside the actor so one credential can distinguish separate jobs. It is recorded as CALLER-SUPPLIED and grants nothing: it changes no permission, no idempotency scope and no quota."
                  },
                  "dryRun": {
                    "type": "boolean",
                    "description": "Report what this write WOULD do and commit nothing. The response carries the same change list, held fields and refusals as the real call, so it is the way to check a risky write, or a whole import, before it lands. Nothing is metered."
                  },
                  "overrideStanding": {
                    "type": "boolean",
                    "description": "Apply this write even when the value standing in the record was asserted more strongly than this one. Absent means no, which is the safe answer for a re-run. WITHOUT IT, a write can be accepted and change nothing: precedence is confirmed > user_supplied > observed > imported > inferred, and a weaker claim leaves the standing value in place and reports the field in `held[]` rather than failing. That is the whole of why a write can return 200 and not take. WITH it, this write wins regardless of what it is overruling, INCLUDING a value a person confirmed, so an agent that sets it by default has switched the provenance mechanism off. Set it per write, when the caller knows its claim supersedes what is there."
                  },
                  "values": {
                    "type": "object",
                    "additionalProperties": {}
                  },
                  "createDistinct": {
                    "type": "boolean"
                  }
                },
                "required": [
                  "values"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "record": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id"
                      ],
                      "additionalProperties": true
                    },
                    "mutation": {
                      "type": "object",
                      "properties": {
                        "mutationId": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "created",
                            "updated",
                            "matched",
                            "archived",
                            "merged",
                            "reverted",
                            "noop"
                          ],
                          "description": "What the write did. `noop` means it was accepted and changed nothing, because every value it carried already matched what was stored. IT IS NOT METERED: a noop does not count against your monthly change allowance, so a nightly sync that finds nothing new costs nothing. Neither does a write that only REDUCES what a workspace holds. `matched` means an upsert found an existing record on real identity evidence rather than creating a second one; `reverted` and `merged` are the undo and duplicate paths, and both are ordinary writes that count."
                        },
                        "targetId": {
                          "type": "string"
                        },
                        "record": {},
                        "changes": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "before": {},
                              "after": {}
                            },
                            "required": [
                              "field"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "held": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "kept": {},
                              "proposed": {},
                              "standing": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "incoming": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "actorId": {
                                "type": "string",
                                "minLength": 1
                              },
                              "assertedAt": {
                                "type": "string",
                                "minLength": 1
                              }
                            },
                            "required": [
                              "field",
                              "standing",
                              "incoming",
                              "actorId",
                              "assertedAt"
                            ],
                            "additionalProperties": false
                          },
                          "description": "Fields this write asked to change and did not, because the value standing in the record was asserted more strongly. THIS IS WHY A WRITE CAN RETURN 200 AND CHANGE NOTHING, and a caller that ignores it will believe it wrote something it did not. Precedence is confirmed > user_supplied > observed > imported > inferred, and a write carrying no `assertionKind` is weakest of all. Each entry reports the field, what the record still says, what you proposed, which claim won, and who made it. Send `overrideStanding` to write anyway, per write, when your claim really does supersede theirs."
                        },
                        "matchedBy": {
                          "type": "string",
                          "enum": [
                            "email",
                            "domain",
                            "external_id",
                            "idempotency_key",
                            "explicit_id"
                          ]
                        },
                        "reversible": {
                          "type": "boolean"
                        },
                        "replayed": {
                          "type": "boolean"
                        },
                        "dryRun": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "mutationId",
                        "status",
                        "reversible"
                      ],
                      "additionalProperties": false
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "record",
                    "mutation",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "A product quota is spent, or the subscription is not active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such record, or it belongs to another workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A conflict the caller can resolve: a stale expectedVersion, an idempotency key reused for different input, an ambiguous or duplicate identity, or a merge that no longer applies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The body, or a single record inside it, exceeds its bound.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "507": {
            "description": "The workspace is at its storage ceiling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/objects/{type}/{id}": {
      "get": {
        "summary": "Read one custom record",
        "description": "One record of a type this workspace defined. Values come back under the names you declared, and a single-valued relationship reads back under its own name rather than the column it became.",
        "tags": [
          "custom objects"
        ],
        "operationId": "get_v1_objects__type___id_",
        "x-indraft-capability": "crm:read",
        "x-indraft-scopes": [
          "crm:read",
          "crm:write",
          "crm:configure",
          "crm:admin",
          "crm:revert",
          "data:export"
        ],
        "parameters": [
          {
            "name": "type",
            "in": "path",
            "required": true,
            "description": "The key of a type this workspace defined, as given when the type was created. Canonical types are not addressed this way.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The :type id, as returned by the call that created or matched it.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "record": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "version": {
                          "type": "integer"
                        },
                        "createdAt": {
                          "type": "string"
                        },
                        "updatedAt": {
                          "type": "string"
                        },
                        "archivedAt": {
                          "type": "string"
                        },
                        "values": {
                          "type": "object",
                          "additionalProperties": {}
                        },
                        "links": {
                          "type": "object",
                          "additionalProperties": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          }
                        },
                        "lastActor": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string"
                            },
                            "kind": {
                              "type": "string",
                              "enum": [
                                "human",
                                "agent",
                                "api_token",
                                "system"
                              ]
                            },
                            "label": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "id",
                            "kind",
                            "label"
                          ],
                          "additionalProperties": true
                        },
                        "stage": {
                          "type": "object",
                          "properties": {
                            "pipelineId": {
                              "type": "string"
                            },
                            "stageId": {
                              "type": "string"
                            },
                            "status": {
                              "type": "string",
                              "enum": [
                                "open",
                                "won",
                                "lost"
                              ]
                            }
                          },
                          "required": [
                            "pipelineId",
                            "stageId",
                            "status"
                          ],
                          "additionalProperties": true
                        }
                      },
                      "required": [
                        "id",
                        "version",
                        "createdAt",
                        "updatedAt",
                        "archivedAt",
                        "values",
                        "links"
                      ],
                      "additionalProperties": true
                    },
                    "standing": {
                      "type": "object",
                      "additionalProperties": {
                        "type": "object",
                        "properties": {
                          "assertionKind": {
                            "type": "string",
                            "enum": [
                              "observed",
                              "inferred",
                              "imported",
                              "user_supplied",
                              "confirmed"
                            ]
                          },
                          "actorId": {
                            "type": "string"
                          },
                          "assertedAt": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "assertionKind",
                          "actorId",
                          "assertedAt"
                        ],
                        "additionalProperties": true
                      },
                      "description": "Per field: which kind of claim is standing on it, who asserted it, and when. This is the provenance the product is sold on, keyed by column name so it lines up with `changes`, `held[]` and the unconfirmed queue. `confirmed` means a person checked it and outranks everything an agent can assert; `inferred` is the weakest and is what an agent's own conclusion should carry. A write whose claim ranks below what is here is held rather than applied."
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "record",
                    "standing",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such record, or it belongs to another workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "summary": "Change a custom record's declared fields",
        "description": "Changes only the fields you send. A field the type does not declare is refused rather than ignored, because silently dropping a value on a type you designed yourself would mean your data went missing and nothing said so.",
        "tags": [
          "custom objects"
        ],
        "operationId": "patch_v1_objects__type___id_",
        "x-indraft-capability": "crm:write",
        "x-indraft-scopes": [
          "crm:write",
          "crm:admin"
        ],
        "parameters": [
          {
            "name": "type",
            "in": "path",
            "required": true,
            "description": "The key of a type this workspace defined, as given when the type was created. Canonical types are not addressed this way.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The :type id, as returned by the call that created or matched it.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "idempotencyKey": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 200,
                    "description": "Your own name for this write, so retrying it cannot do it twice. Send the same key again and you get the SAME result back rather than a second record, which is what makes a re-run safe after a timeout you never saw the answer to. Derive it from what the write is about, not from the clock: `nightly-sync-halden` retries correctly and a timestamp does not."
                  },
                  "expectedVersion": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "The version you read before deciding to write. If the record has moved since, the write is refused instead of overwriting whatever changed. Send it whenever you read, reasoned, and then wrote: without it the last writer wins and neither of you finds out."
                  },
                  "sourceId": {
                    "type": "string",
                    "description": "The recorded source this claim came from, if one exists. It attaches evidence to the write, so a person reading the field later can see where it came from rather than only who sent it."
                  },
                  "assertionKind": {
                    "type": "string",
                    "enum": [
                      "observed",
                      "inferred",
                      "imported",
                      "user_supplied"
                    ],
                    "description": "HOW YOU KNOW. This is the field the product is built around, so say what is true rather than what is strongest: `observed` you saw it stated directly, `imported` it came from a file or another system, `inferred` you worked it out, `user_supplied` a person told you in so many words. They rank, weakest first: inferred < imported < observed < user_supplied < confirmed. A weaker claim does not overwrite a stronger one; it is reported in `held[]` and the stored value stands, so an unattended re-run converges instead of eroding what somebody checked. `confirmed` is not accepted here: it means a person checked the value, and only a signed-in person can set it."
                  },
                  "attributionLabel": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120,
                    "description": "A short name for the work this write belongs to, shown beside the actor so one credential can distinguish separate jobs. It is recorded as CALLER-SUPPLIED and grants nothing: it changes no permission, no idempotency scope and no quota."
                  },
                  "dryRun": {
                    "type": "boolean",
                    "description": "Report what this write WOULD do and commit nothing. The response carries the same change list, held fields and refusals as the real call, so it is the way to check a risky write, or a whole import, before it lands. Nothing is metered."
                  },
                  "overrideStanding": {
                    "type": "boolean",
                    "description": "Apply this write even when the value standing in the record was asserted more strongly than this one. Absent means no, which is the safe answer for a re-run. WITHOUT IT, a write can be accepted and change nothing: precedence is confirmed > user_supplied > observed > imported > inferred, and a weaker claim leaves the standing value in place and reports the field in `held[]` rather than failing. That is the whole of why a write can return 200 and not take. WITH it, this write wins regardless of what it is overruling, INCLUDING a value a person confirmed, so an agent that sets it by default has switched the provenance mechanism off. Set it per write, when the caller knows its claim supersedes what is there."
                  },
                  "values": {
                    "type": "object",
                    "additionalProperties": {}
                  },
                  "createDistinct": {
                    "type": "boolean"
                  }
                },
                "required": [
                  "values"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "record": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id"
                      ],
                      "additionalProperties": true
                    },
                    "mutation": {
                      "type": "object",
                      "properties": {
                        "mutationId": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "created",
                            "updated",
                            "matched",
                            "archived",
                            "merged",
                            "reverted",
                            "noop"
                          ],
                          "description": "What the write did. `noop` means it was accepted and changed nothing, because every value it carried already matched what was stored. IT IS NOT METERED: a noop does not count against your monthly change allowance, so a nightly sync that finds nothing new costs nothing. Neither does a write that only REDUCES what a workspace holds. `matched` means an upsert found an existing record on real identity evidence rather than creating a second one; `reverted` and `merged` are the undo and duplicate paths, and both are ordinary writes that count."
                        },
                        "targetId": {
                          "type": "string"
                        },
                        "record": {},
                        "changes": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "before": {},
                              "after": {}
                            },
                            "required": [
                              "field"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "held": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "kept": {},
                              "proposed": {},
                              "standing": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "incoming": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "actorId": {
                                "type": "string",
                                "minLength": 1
                              },
                              "assertedAt": {
                                "type": "string",
                                "minLength": 1
                              }
                            },
                            "required": [
                              "field",
                              "standing",
                              "incoming",
                              "actorId",
                              "assertedAt"
                            ],
                            "additionalProperties": false
                          },
                          "description": "Fields this write asked to change and did not, because the value standing in the record was asserted more strongly. THIS IS WHY A WRITE CAN RETURN 200 AND CHANGE NOTHING, and a caller that ignores it will believe it wrote something it did not. Precedence is confirmed > user_supplied > observed > imported > inferred, and a write carrying no `assertionKind` is weakest of all. Each entry reports the field, what the record still says, what you proposed, which claim won, and who made it. Send `overrideStanding` to write anyway, per write, when your claim really does supersede theirs."
                        },
                        "matchedBy": {
                          "type": "string",
                          "enum": [
                            "email",
                            "domain",
                            "external_id",
                            "idempotency_key",
                            "explicit_id"
                          ]
                        },
                        "reversible": {
                          "type": "boolean"
                        },
                        "replayed": {
                          "type": "boolean"
                        },
                        "dryRun": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "mutationId",
                        "status",
                        "reversible"
                      ],
                      "additionalProperties": false
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "record",
                    "mutation",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "A product quota is spent, or the subscription is not active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such record, or it belongs to another workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A conflict the caller can resolve: a stale expectedVersion, an idempotency key reused for different input, an ambiguous or duplicate identity, or a merge that no longer applies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The body, or a single record inside it, exceeds its bound.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "507": {
            "description": "The workspace is at its storage ceiling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/objects/{type}/{id}/archive": {
      "post": {
        "summary": "Archive or restore one custom record",
        "description": "Archive one record of a type this workspace defined for itself, or restore it. For a company or a contact use archive_record instead. Archiving keeps the record readable and exportable and takes it out of lists; it is not a delete.",
        "tags": [
          "custom objects"
        ],
        "operationId": "post_v1_objects__type___id__archive",
        "x-indraft-capability": "crm:write",
        "x-indraft-scopes": [
          "crm:write",
          "crm:admin"
        ],
        "parameters": [
          {
            "name": "type",
            "in": "path",
            "required": true,
            "description": "The key of a type this workspace defined, as given when the type was created. Canonical types are not addressed this way.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The :type id, as returned by the call that created or matched it.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "idempotencyKey": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 200,
                    "description": "Your own name for this write, so retrying it cannot do it twice. Send the same key again and you get the SAME result back rather than a second record, which is what makes a re-run safe after a timeout you never saw the answer to. Derive it from what the write is about, not from the clock: `nightly-sync-halden` retries correctly and a timestamp does not."
                  },
                  "expectedVersion": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "The version you read before deciding to write. If the record has moved since, the write is refused instead of overwriting whatever changed. Send it whenever you read, reasoned, and then wrote: without it the last writer wins and neither of you finds out."
                  },
                  "sourceId": {
                    "type": "string",
                    "description": "The recorded source this claim came from, if one exists. It attaches evidence to the write, so a person reading the field later can see where it came from rather than only who sent it."
                  },
                  "assertionKind": {
                    "type": "string",
                    "enum": [
                      "observed",
                      "inferred",
                      "imported",
                      "user_supplied"
                    ],
                    "description": "HOW YOU KNOW. This is the field the product is built around, so say what is true rather than what is strongest: `observed` you saw it stated directly, `imported` it came from a file or another system, `inferred` you worked it out, `user_supplied` a person told you in so many words. They rank, weakest first: inferred < imported < observed < user_supplied < confirmed. A weaker claim does not overwrite a stronger one; it is reported in `held[]` and the stored value stands, so an unattended re-run converges instead of eroding what somebody checked. `confirmed` is not accepted here: it means a person checked the value, and only a signed-in person can set it."
                  },
                  "attributionLabel": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120,
                    "description": "A short name for the work this write belongs to, shown beside the actor so one credential can distinguish separate jobs. It is recorded as CALLER-SUPPLIED and grants nothing: it changes no permission, no idempotency scope and no quota."
                  },
                  "dryRun": {
                    "type": "boolean",
                    "description": "Report what this write WOULD do and commit nothing. The response carries the same change list, held fields and refusals as the real call, so it is the way to check a risky write, or a whole import, before it lands. Nothing is metered."
                  },
                  "overrideStanding": {
                    "type": "boolean",
                    "description": "Apply this write even when the value standing in the record was asserted more strongly than this one. Absent means no, which is the safe answer for a re-run. WITHOUT IT, a write can be accepted and change nothing: precedence is confirmed > user_supplied > observed > imported > inferred, and a weaker claim leaves the standing value in place and reports the field in `held[]` rather than failing. That is the whole of why a write can return 200 and not take. WITH it, this write wins regardless of what it is overruling, INCLUDING a value a person confirmed, so an agent that sets it by default has switched the provenance mechanism off. Set it per write, when the caller knows its claim supersedes what is there."
                  },
                  "restore": {
                    "type": "boolean"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "record": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id"
                      ],
                      "additionalProperties": true
                    },
                    "mutation": {
                      "type": "object",
                      "properties": {
                        "mutationId": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "created",
                            "updated",
                            "matched",
                            "archived",
                            "merged",
                            "reverted",
                            "noop"
                          ],
                          "description": "What the write did. `noop` means it was accepted and changed nothing, because every value it carried already matched what was stored. IT IS NOT METERED: a noop does not count against your monthly change allowance, so a nightly sync that finds nothing new costs nothing. Neither does a write that only REDUCES what a workspace holds. `matched` means an upsert found an existing record on real identity evidence rather than creating a second one; `reverted` and `merged` are the undo and duplicate paths, and both are ordinary writes that count."
                        },
                        "targetId": {
                          "type": "string"
                        },
                        "record": {},
                        "changes": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "before": {},
                              "after": {}
                            },
                            "required": [
                              "field"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "held": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "kept": {},
                              "proposed": {},
                              "standing": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "incoming": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "actorId": {
                                "type": "string",
                                "minLength": 1
                              },
                              "assertedAt": {
                                "type": "string",
                                "minLength": 1
                              }
                            },
                            "required": [
                              "field",
                              "standing",
                              "incoming",
                              "actorId",
                              "assertedAt"
                            ],
                            "additionalProperties": false
                          },
                          "description": "Fields this write asked to change and did not, because the value standing in the record was asserted more strongly. THIS IS WHY A WRITE CAN RETURN 200 AND CHANGE NOTHING, and a caller that ignores it will believe it wrote something it did not. Precedence is confirmed > user_supplied > observed > imported > inferred, and a write carrying no `assertionKind` is weakest of all. Each entry reports the field, what the record still says, what you proposed, which claim won, and who made it. Send `overrideStanding` to write anyway, per write, when your claim really does supersede theirs."
                        },
                        "matchedBy": {
                          "type": "string",
                          "enum": [
                            "email",
                            "domain",
                            "external_id",
                            "idempotency_key",
                            "explicit_id"
                          ]
                        },
                        "reversible": {
                          "type": "boolean"
                        },
                        "replayed": {
                          "type": "boolean"
                        },
                        "dryRun": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "mutationId",
                        "status",
                        "reversible"
                      ],
                      "additionalProperties": false
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "record",
                    "mutation",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "A product quota is spent, or the subscription is not active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such record, or it belongs to another workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A conflict the caller can resolve: a stale expectedVersion, an idempotency key reused for different input, an ambiguous or duplicate identity, or a merge that no longer applies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The body, or a single record inside it, exceeds its bound.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "507": {
            "description": "The workspace is at its storage ceiling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/objects/{type}/{id}/advance": {
      "post": {
        "summary": "Move one custom record to a stage of its type's pipeline",
        "description": "Move one record of a custom type to a stage of that type's pipeline. Status (open, won, lost) is derived from the stage, exactly as it is for an opportunity, so this is how a record of your own type is won or lost. The type needs a pipeline first: give it one with configure_pipeline naming the type. Filter list_object_records by _stage_id or _status to read a board.",
        "tags": [
          "custom objects"
        ],
        "operationId": "post_v1_objects__type___id__advance",
        "x-indraft-capability": "crm:write",
        "x-indraft-scopes": [
          "crm:write",
          "crm:admin"
        ],
        "parameters": [
          {
            "name": "type",
            "in": "path",
            "required": true,
            "description": "The key of a type this workspace defined, as given when the type was created. Canonical types are not addressed this way.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The :type id, as returned by the call that created or matched it.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "idempotencyKey": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 200,
                    "description": "Your own name for this write, so retrying it cannot do it twice. Send the same key again and you get the SAME result back rather than a second record, which is what makes a re-run safe after a timeout you never saw the answer to. Derive it from what the write is about, not from the clock: `nightly-sync-halden` retries correctly and a timestamp does not."
                  },
                  "expectedVersion": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "The version you read before deciding to write. If the record has moved since, the write is refused instead of overwriting whatever changed. Send it whenever you read, reasoned, and then wrote: without it the last writer wins and neither of you finds out."
                  },
                  "sourceId": {
                    "type": "string",
                    "description": "The recorded source this claim came from, if one exists. It attaches evidence to the write, so a person reading the field later can see where it came from rather than only who sent it."
                  },
                  "assertionKind": {
                    "type": "string",
                    "enum": [
                      "observed",
                      "inferred",
                      "imported",
                      "user_supplied"
                    ],
                    "description": "HOW YOU KNOW. This is the field the product is built around, so say what is true rather than what is strongest: `observed` you saw it stated directly, `imported` it came from a file or another system, `inferred` you worked it out, `user_supplied` a person told you in so many words. They rank, weakest first: inferred < imported < observed < user_supplied < confirmed. A weaker claim does not overwrite a stronger one; it is reported in `held[]` and the stored value stands, so an unattended re-run converges instead of eroding what somebody checked. `confirmed` is not accepted here: it means a person checked the value, and only a signed-in person can set it."
                  },
                  "attributionLabel": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120,
                    "description": "A short name for the work this write belongs to, shown beside the actor so one credential can distinguish separate jobs. It is recorded as CALLER-SUPPLIED and grants nothing: it changes no permission, no idempotency scope and no quota."
                  },
                  "dryRun": {
                    "type": "boolean",
                    "description": "Report what this write WOULD do and commit nothing. The response carries the same change list, held fields and refusals as the real call, so it is the way to check a risky write, or a whole import, before it lands. Nothing is metered."
                  },
                  "overrideStanding": {
                    "type": "boolean",
                    "description": "Apply this write even when the value standing in the record was asserted more strongly than this one. Absent means no, which is the safe answer for a re-run. WITHOUT IT, a write can be accepted and change nothing: precedence is confirmed > user_supplied > observed > imported > inferred, and a weaker claim leaves the standing value in place and reports the field in `held[]` rather than failing. That is the whole of why a write can return 200 and not take. WITH it, this write wins regardless of what it is overruling, INCLUDING a value a person confirmed, so an agent that sets it by default has switched the provenance mechanism off. Set it per write, when the caller knows its claim supersedes what is there."
                  },
                  "stageId": {
                    "type": "string",
                    "minLength": 1
                  }
                },
                "required": [
                  "stageId"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "record": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id"
                      ],
                      "additionalProperties": true
                    },
                    "mutation": {
                      "type": "object",
                      "properties": {
                        "mutationId": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "created",
                            "updated",
                            "matched",
                            "archived",
                            "merged",
                            "reverted",
                            "noop"
                          ],
                          "description": "What the write did. `noop` means it was accepted and changed nothing, because every value it carried already matched what was stored. IT IS NOT METERED: a noop does not count against your monthly change allowance, so a nightly sync that finds nothing new costs nothing. Neither does a write that only REDUCES what a workspace holds. `matched` means an upsert found an existing record on real identity evidence rather than creating a second one; `reverted` and `merged` are the undo and duplicate paths, and both are ordinary writes that count."
                        },
                        "targetId": {
                          "type": "string"
                        },
                        "record": {},
                        "changes": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "before": {},
                              "after": {}
                            },
                            "required": [
                              "field"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "held": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "kept": {},
                              "proposed": {},
                              "standing": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "incoming": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "actorId": {
                                "type": "string",
                                "minLength": 1
                              },
                              "assertedAt": {
                                "type": "string",
                                "minLength": 1
                              }
                            },
                            "required": [
                              "field",
                              "standing",
                              "incoming",
                              "actorId",
                              "assertedAt"
                            ],
                            "additionalProperties": false
                          },
                          "description": "Fields this write asked to change and did not, because the value standing in the record was asserted more strongly. THIS IS WHY A WRITE CAN RETURN 200 AND CHANGE NOTHING, and a caller that ignores it will believe it wrote something it did not. Precedence is confirmed > user_supplied > observed > imported > inferred, and a write carrying no `assertionKind` is weakest of all. Each entry reports the field, what the record still says, what you proposed, which claim won, and who made it. Send `overrideStanding` to write anyway, per write, when your claim really does supersede theirs."
                        },
                        "matchedBy": {
                          "type": "string",
                          "enum": [
                            "email",
                            "domain",
                            "external_id",
                            "idempotency_key",
                            "explicit_id"
                          ]
                        },
                        "reversible": {
                          "type": "boolean"
                        },
                        "replayed": {
                          "type": "boolean"
                        },
                        "dryRun": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "mutationId",
                        "status",
                        "reversible"
                      ],
                      "additionalProperties": false
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "record",
                    "mutation",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "A product quota is spent, or the subscription is not active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such record, or it belongs to another workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A conflict the caller can resolve: a stale expectedVersion, an idempotency key reused for different input, an ambiguous or duplicate identity, or a merge that no longer applies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The body, or a single record inside it, exceeds its bound.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "507": {
            "description": "The workspace is at its storage ceiling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/objects:merge": {
      "post": {
        "summary": "Merge a duplicate custom record into a target, naming both ids",
        "description": "Merge a duplicate record of a custom type into a target. References move to the target and the source is archived. You must name both ids: nothing here works out which records are the same, and a custom type has no natural key. Not undoable by revert_change; use unmerge.",
        "tags": [
          "custom objects"
        ],
        "operationId": "post_v1_objects_merge",
        "x-indraft-capability": "crm:write",
        "x-indraft-scopes": [
          "crm:write",
          "crm:admin"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "idempotencyKey": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 200,
                    "description": "Your own name for this write, so retrying it cannot do it twice. Send the same key again and you get the SAME result back rather than a second record, which is what makes a re-run safe after a timeout you never saw the answer to. Derive it from what the write is about, not from the clock: `nightly-sync-halden` retries correctly and a timestamp does not."
                  },
                  "expectedVersion": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "The version you read before deciding to write. If the record has moved since, the write is refused instead of overwriting whatever changed. Send it whenever you read, reasoned, and then wrote: without it the last writer wins and neither of you finds out."
                  },
                  "sourceId": {
                    "type": "string",
                    "minLength": 1
                  },
                  "assertionKind": {
                    "type": "string",
                    "enum": [
                      "observed",
                      "inferred",
                      "imported",
                      "user_supplied"
                    ],
                    "description": "HOW YOU KNOW. This is the field the product is built around, so say what is true rather than what is strongest: `observed` you saw it stated directly, `imported` it came from a file or another system, `inferred` you worked it out, `user_supplied` a person told you in so many words. They rank, weakest first: inferred < imported < observed < user_supplied < confirmed. A weaker claim does not overwrite a stronger one; it is reported in `held[]` and the stored value stands, so an unattended re-run converges instead of eroding what somebody checked. `confirmed` is not accepted here: it means a person checked the value, and only a signed-in person can set it."
                  },
                  "attributionLabel": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120,
                    "description": "A short name for the work this write belongs to, shown beside the actor so one credential can distinguish separate jobs. It is recorded as CALLER-SUPPLIED and grants nothing: it changes no permission, no idempotency scope and no quota."
                  },
                  "dryRun": {
                    "type": "boolean",
                    "description": "Report what this write WOULD do and commit nothing. The response carries the same change list, held fields and refusals as the real call, so it is the way to check a risky write, or a whole import, before it lands. Nothing is metered."
                  },
                  "overrideStanding": {
                    "type": "boolean",
                    "description": "Apply this write even when the value standing in the record was asserted more strongly than this one. Absent means no, which is the safe answer for a re-run. WITHOUT IT, a write can be accepted and change nothing: precedence is confirmed > user_supplied > observed > imported > inferred, and a weaker claim leaves the standing value in place and reports the field in `held[]` rather than failing. That is the whole of why a write can return 200 and not take. WITH it, this write wins regardless of what it is overruling, INCLUDING a value a person confirmed, so an agent that sets it by default has switched the provenance mechanism off. Set it per write, when the caller knows its claim supersedes what is there."
                  },
                  "targetId": {
                    "type": "string",
                    "minLength": 1
                  },
                  "objectType": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 48
                  }
                },
                "required": [
                  "sourceId",
                  "targetId",
                  "objectType"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "record": {
                      "type": "object",
                      "properties": {
                        "mergeId": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "mergeId"
                      ],
                      "additionalProperties": true
                    },
                    "mutation": {
                      "type": "object",
                      "properties": {
                        "mutationId": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "created",
                            "updated",
                            "matched",
                            "archived",
                            "merged",
                            "reverted",
                            "noop"
                          ],
                          "description": "What the write did. `noop` means it was accepted and changed nothing, because every value it carried already matched what was stored. IT IS NOT METERED: a noop does not count against your monthly change allowance, so a nightly sync that finds nothing new costs nothing. Neither does a write that only REDUCES what a workspace holds. `matched` means an upsert found an existing record on real identity evidence rather than creating a second one; `reverted` and `merged` are the undo and duplicate paths, and both are ordinary writes that count."
                        },
                        "targetId": {
                          "type": "string"
                        },
                        "record": {},
                        "changes": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "before": {},
                              "after": {}
                            },
                            "required": [
                              "field"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "held": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "kept": {},
                              "proposed": {},
                              "standing": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "incoming": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "actorId": {
                                "type": "string",
                                "minLength": 1
                              },
                              "assertedAt": {
                                "type": "string",
                                "minLength": 1
                              }
                            },
                            "required": [
                              "field",
                              "standing",
                              "incoming",
                              "actorId",
                              "assertedAt"
                            ],
                            "additionalProperties": false
                          },
                          "description": "Fields this write asked to change and did not, because the value standing in the record was asserted more strongly. THIS IS WHY A WRITE CAN RETURN 200 AND CHANGE NOTHING, and a caller that ignores it will believe it wrote something it did not. Precedence is confirmed > user_supplied > observed > imported > inferred, and a write carrying no `assertionKind` is weakest of all. Each entry reports the field, what the record still says, what you proposed, which claim won, and who made it. Send `overrideStanding` to write anyway, per write, when your claim really does supersede theirs."
                        },
                        "matchedBy": {
                          "type": "string",
                          "enum": [
                            "email",
                            "domain",
                            "external_id",
                            "idempotency_key",
                            "explicit_id"
                          ]
                        },
                        "reversible": {
                          "type": "boolean"
                        },
                        "replayed": {
                          "type": "boolean"
                        },
                        "dryRun": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "mutationId",
                        "status",
                        "reversible"
                      ],
                      "additionalProperties": false
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "mutation",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "A product quota is spent, or the subscription is not active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A conflict the caller can resolve: a stale expectedVersion, an idempotency key reused for different input, an ambiguous or duplicate identity, or a merge that no longer applies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The body, or a single record inside it, exceeds its bound.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "507": {
            "description": "The workspace is at its storage ceiling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/objects:archive": {
      "post": {
        "summary": "Archive or restore up to 500 custom records of one type in one call",
        "description": "Up to 500 records of one type in one call, each independently applied, with every row's outcome reported.",
        "tags": [
          "custom objects"
        ],
        "operationId": "post_v1_objects_archive",
        "x-indraft-capability": "crm:write",
        "x-indraft-scopes": [
          "crm:write",
          "crm:admin"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "idempotencyKey": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 200,
                    "description": "Your own name for this write, so retrying it cannot do it twice. Send the same key again and you get the SAME result back rather than a second record, which is what makes a re-run safe after a timeout you never saw the answer to. Derive it from what the write is about, not from the clock: `nightly-sync-halden` retries correctly and a timestamp does not."
                  },
                  "expectedVersion": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "The version you read before deciding to write. If the record has moved since, the write is refused instead of overwriting whatever changed. Send it whenever you read, reasoned, and then wrote: without it the last writer wins and neither of you finds out."
                  },
                  "sourceId": {
                    "type": "string",
                    "description": "The recorded source this claim came from, if one exists. It attaches evidence to the write, so a person reading the field later can see where it came from rather than only who sent it."
                  },
                  "assertionKind": {
                    "type": "string",
                    "enum": [
                      "observed",
                      "inferred",
                      "imported",
                      "user_supplied"
                    ],
                    "description": "HOW YOU KNOW. This is the field the product is built around, so say what is true rather than what is strongest: `observed` you saw it stated directly, `imported` it came from a file or another system, `inferred` you worked it out, `user_supplied` a person told you in so many words. They rank, weakest first: inferred < imported < observed < user_supplied < confirmed. A weaker claim does not overwrite a stronger one; it is reported in `held[]` and the stored value stands, so an unattended re-run converges instead of eroding what somebody checked. `confirmed` is not accepted here: it means a person checked the value, and only a signed-in person can set it."
                  },
                  "attributionLabel": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120,
                    "description": "A short name for the work this write belongs to, shown beside the actor so one credential can distinguish separate jobs. It is recorded as CALLER-SUPPLIED and grants nothing: it changes no permission, no idempotency scope and no quota."
                  },
                  "dryRun": {
                    "type": "boolean",
                    "description": "Report what this write WOULD do and commit nothing. The response carries the same change list, held fields and refusals as the real call, so it is the way to check a risky write, or a whole import, before it lands. Nothing is metered."
                  },
                  "overrideStanding": {
                    "type": "boolean",
                    "description": "Apply this write even when the value standing in the record was asserted more strongly than this one. Absent means no, which is the safe answer for a re-run. WITHOUT IT, a write can be accepted and change nothing: precedence is confirmed > user_supplied > observed > imported > inferred, and a weaker claim leaves the standing value in place and reports the field in `held[]` rather than failing. That is the whole of why a write can return 200 and not take. WITH it, this write wins regardless of what it is overruling, INCLUDING a value a person confirmed, so an agent that sets it by default has switched the provenance mechanism off. Set it per write, when the caller knows its claim supersedes what is there."
                  },
                  "ids": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1
                    },
                    "minItems": 1,
                    "maxItems": 500
                  },
                  "restore": {
                    "type": "boolean"
                  },
                  "objectType": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 48
                  }
                },
                "required": [
                  "ids",
                  "objectType"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "archived": {
                      "type": "integer"
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "ok": {
                            "type": "boolean"
                          },
                          "code": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "ok"
                        ],
                        "additionalProperties": true
                      }
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "archived",
                    "results",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "A product quota is spent, or the subscription is not active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A conflict the caller can resolve: a stale expectedVersion, an idempotency key reused for different input, an ambiguous or duplicate identity, or a merge that no longer applies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The body, or a single record inside it, exceeds its bound.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "507": {
            "description": "The workspace is at its storage ceiling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/workspace": {
      "patch": {
        "summary": "Change the workspace name, display timezone, or default currency",
        "description": "The display timezone decides how a date bucket is drawn in every report, and the default currency decides what a total is expressed in. Changing either changes what past numbers look like, not what they were.",
        "tags": [
          "admin"
        ],
        "operationId": "patch_v1_workspace",
        "x-indraft-capability": "crm:configure",
        "x-indraft-scopes": [
          "crm:configure",
          "crm:admin"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 80
                  },
                  "displayTimezone": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 60
                  },
                  "defaultCurrency": {
                    "type": "string",
                    "pattern": "^[A-Z]{3}$"
                  },
                  "idempotencyKey": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "fiscalYearStartMonth": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 12
                  }
                },
                "required": [
                  "name",
                  "displayTimezone",
                  "defaultCurrency"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "workspace": {
                      "type": "object",
                      "properties": {
                        "name": {
                          "type": "string"
                        },
                        "displayTimezone": {
                          "type": "string"
                        },
                        "defaultCurrency": {
                          "type": "string"
                        },
                        "fiscalYearStartMonth": {
                          "type": "integer"
                        },
                        "standingOverridePolicy": {
                          "type": "string",
                          "enum": [
                            "allowed",
                            "confirmed_protected",
                            "refused"
                          ]
                        }
                      },
                      "required": [
                        "name",
                        "displayTimezone",
                        "defaultCurrency",
                        "fiscalYearStartMonth",
                        "standingOverridePolicy"
                      ],
                      "additionalProperties": true
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "workspace",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "A product quota is spent, or the subscription is not active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A conflict the caller can resolve: a stale expectedVersion, an idempotency key reused for different input, an ambiguous or duplicate identity, or a merge that no longer applies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The body, or a single record inside it, exceeds its bound.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "507": {
            "description": "The workspace is at its storage ceiling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/workspace/standing-override-policy": {
      "patch": {
        "summary": "Set what this workspace permits overrideStanding to do",
        "description": "`allowed` is the default and today's behaviour. `confirmed_protected` lets a write override anything except a value a person confirmed, which is what most workspaces mean. `refused` means a write carrying the flag is refused outright rather than quietly downgraded. Reserved to a person: a credential cannot change it, including one with every scope, because a control an agent can switch off is not a control.",
        "tags": [
          "admin"
        ],
        "operationId": "patch_v1_workspace_standing_override_policy",
        "x-indraft-capability": "members:manage",
        "x-indraft-scopes": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "policy": {
                    "type": "string",
                    "enum": [
                      "allowed",
                      "confirmed_protected",
                      "refused"
                    ]
                  }
                },
                "required": [
                  "policy"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "workspace": {
                      "type": "object",
                      "properties": {
                        "name": {
                          "type": "string"
                        },
                        "displayTimezone": {
                          "type": "string"
                        },
                        "defaultCurrency": {
                          "type": "string"
                        },
                        "fiscalYearStartMonth": {
                          "type": "integer"
                        },
                        "standingOverridePolicy": {
                          "type": "string",
                          "enum": [
                            "allowed",
                            "confirmed_protected",
                            "refused"
                          ]
                        }
                      },
                      "required": [
                        "name",
                        "displayTimezone",
                        "defaultCurrency",
                        "fiscalYearStartMonth",
                        "standingOverridePolicy"
                      ],
                      "additionalProperties": true
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "workspace",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "A product quota is spent, or the subscription is not active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A conflict the caller can resolve: a stale expectedVersion, an idempotency key reused for different input, an ambiguous or duplicate identity, or a merge that no longer applies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The body, or a single record inside it, exceeds its bound.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "507": {
            "description": "The workspace is at its storage ceiling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/workspace/deletion": {
      "post": {
        "summary": "Schedule this workspace for destruction, cancellable for seven days",
        "description": "Schedules destruction rather than performing it, and the seven days are the point: an accidental deletion that ran immediately is recoverable by nobody, including us, and the person most likely to delete the wrong workspace is the one working through a support ticket.",
        "tags": [
          "admin"
        ],
        "operationId": "post_v1_workspace_deletion",
        "x-indraft-capability": "workspace:delete",
        "x-indraft-scopes": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {},
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "scheduled": {
                      "type": "string",
                      "enum": [
                        true
                      ]
                    },
                    "deleteAfter": {
                      "type": "string"
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "scheduled",
                    "deleteAfter",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "A product quota is spent, or the subscription is not active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A conflict the caller can resolve: a stale expectedVersion, an idempotency key reused for different input, an ambiguous or duplicate identity, or a merge that no longer applies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The body, or a single record inside it, exceeds its bound.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "507": {
            "description": "The workspace is at its storage ceiling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Cancel a scheduled destruction",
        "description": "Cancels a scheduled destruction. Available for the whole window and refused after it, because after it there is nothing left to cancel.",
        "tags": [
          "admin"
        ],
        "operationId": "delete_v1_workspace_deletion",
        "x-indraft-capability": "workspace:delete",
        "x-indraft-scopes": [],
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "cancelled": {
                      "type": "string",
                      "enum": [
                        true
                      ]
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "cancelled",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "A product quota is spent, or the subscription is not active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A conflict the caller can resolve: a stale expectedVersion, an idempotency key reused for different input, an ambiguous or duplicate identity, or a merge that no longer applies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "507": {
            "description": "The workspace is at its storage ceiling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/workspaces": {
      "get": {
        "summary": "List the workspaces this credential can reach",
        "description": "Every workspace this credential can reach. A credential is scoped to one workspace unless it was provisioned to manage several, which is how an agency runs eleven client workspaces without any of them seeing another.",
        "tags": [
          "admin"
        ],
        "operationId": "get_v1_workspaces",
        "x-indraft-capability": "workspaces:provision",
        "x-indraft-scopes": [
          "workspaces:provision"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "workspaces": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "created_at": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "name",
                          "created_at"
                        ],
                        "additionalProperties": true
                      }
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "workspaces",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Create a workspace and return a credential scoped to it",
        "description": "Creates a workspace and returns a credential scoped to it and nothing else. Intended for provisioning one per customer under a parent account, which is why the returned credential cannot reach the workspace that created it.",
        "tags": [
          "admin"
        ],
        "operationId": "post_v1_workspaces",
        "x-indraft-capability": "workspaces:provision",
        "x-indraft-scopes": [
          "workspaces:provision"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 80
                  },
                  "displayTimezone": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 60
                  },
                  "defaultCurrency": {
                    "type": "string",
                    "pattern": "^[A-Z]{3}$"
                  },
                  "idempotencyKey": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  }
                },
                "required": [
                  "name",
                  "displayTimezone",
                  "defaultCurrency"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "workspace": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "name": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id",
                        "name"
                      ],
                      "additionalProperties": true
                    },
                    "credential": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "prefix": {
                          "type": "string"
                        },
                        "token": {
                          "type": "string"
                        },
                        "scopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        }
                      },
                      "required": [
                        "id",
                        "prefix",
                        "token",
                        "scopes"
                      ],
                      "additionalProperties": true
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "workspace",
                    "credential",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "A product quota is spent, or the subscription is not active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A conflict the caller can resolve: a stale expectedVersion, an idempotency key reused for different input, an ambiguous or duplicate identity, or a merge that no longer applies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The body, or a single record inside it, exceeds its bound.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "507": {
            "description": "The workspace is at its storage ceiling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhooks": {
      "get": {
        "summary": "List registered webhook endpoints",
        "description": "Registered endpoints and the events each is subscribed to. Signing secrets are not included: they are shown once, at registration, and rolled rather than recovered.",
        "tags": [
          "webhooks"
        ],
        "operationId": "get_v1_webhooks",
        "x-indraft-capability": "crm:configure",
        "x-indraft-scopes": [
          "crm:configure",
          "crm:admin"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "endpoints": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "url": {
                            "type": "string"
                          },
                          "events": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "description": {
                            "type": "string"
                          },
                          "createdAt": {
                            "type": "string"
                          },
                          "disabledAt": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "url",
                          "events",
                          "description",
                          "createdAt",
                          "disabledAt"
                        ],
                        "additionalProperties": true
                      }
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "endpoints",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Register a webhook endpoint, returning its signing secret once",
        "description": "The signing secret is in this response and nowhere else. Verify a delivery by recomputing the signature over the timestamp and the raw body. An address that is not https, or one on a private, loopback or cloud-metadata range, is refused here rather than at delivery time.",
        "tags": [
          "webhooks"
        ],
        "operationId": "post_v1_webhooks",
        "x-indraft-capability": "crm:configure",
        "x-indraft-scopes": [
          "crm:configure",
          "crm:admin"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "maxLength": 2000
                  },
                  "events": {
                    "type": "array",
                    "items": {
                      "anyOf": [
                        {
                          "type": "string",
                          "enum": [
                            "advance_opportunity",
                            "configure_watch",
                            "advance_custom_record",
                            "archive",
                            "restore",
                            "archive_custom_record",
                            "cancel_task",
                            "update_task",
                            "complete_task",
                            "configure_custom_field",
                            "configure_exchange_rate",
                            "configure_object_type",
                            "configure_pipeline",
                            "configure_workspace",
                            "set_standing_override_policy",
                            "confirm",
                            "create_opportunity",
                            "create_task",
                            "erase_subject",
                            "link_contact_company",
                            "merge_companies",
                            "merge_contacts",
                            "merge_object_records",
                            "record_interaction",
                            "revert_change",
                            "unmerge",
                            "update_opportunity",
                            "upsert_company",
                            "upsert_contact",
                            "upsert_custom_record"
                          ]
                        },
                        {
                          "type": "string",
                          "enum": [
                            "watch_fired"
                          ]
                        }
                      ]
                    },
                    "maxItems": 50
                  },
                  "description": {
                    "type": "string",
                    "maxLength": 200
                  }
                },
                "required": [
                  "url"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "endpoint": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "url": {
                          "type": "string"
                        },
                        "events": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "description": {
                          "type": "string"
                        },
                        "createdAt": {
                          "type": "string"
                        },
                        "disabledAt": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id",
                        "url",
                        "events",
                        "description",
                        "createdAt",
                        "disabledAt"
                      ],
                      "additionalProperties": true
                    },
                    "secret": {
                      "type": "string"
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "endpoint",
                    "secret",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "A product quota is spent, or the subscription is not active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A conflict the caller can resolve: a stale expectedVersion, an idempotency key reused for different input, an ambiguous or duplicate identity, or a merge that no longer applies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The body, or a single record inside it, exceeds its bound.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "507": {
            "description": "The workspace is at its storage ceiling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/watches": {
      "get": {
        "summary": "Every saved question this workspace asks on a clock",
        "description": "Every question this workspace asks itself on a clock, with what each last counted and when it last had something to say. A watch reports only when its count is above its threshold AND has changed, so one that has not fired recently is usually one whose answer has not moved.",
        "tags": [
          "watches"
        ],
        "operationId": "get_v1_watches",
        "x-indraft-capability": "crm:read",
        "x-indraft-scopes": [
          "crm:read",
          "crm:write",
          "crm:configure",
          "crm:admin",
          "crm:revert",
          "data:export"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "watches": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "objectType": {
                            "type": "string"
                          },
                          "filter": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "additionalProperties": {}
                            }
                          },
                          "threshold": {
                            "type": "integer"
                          },
                          "everyHours": {
                            "type": "integer"
                          },
                          "lastCount": {
                            "type": "integer"
                          },
                          "lastCheckedAt": {
                            "type": "string"
                          },
                          "lastFiredAt": {
                            "type": "string"
                          },
                          "disabledAt": {
                            "type": "string"
                          },
                          "createdAt": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "name",
                          "objectType",
                          "filter",
                          "threshold",
                          "everyHours",
                          "lastCount",
                          "lastCheckedAt",
                          "lastFiredAt",
                          "disabledAt",
                          "createdAt"
                        ],
                        "additionalProperties": true
                      }
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "watches",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Save a question, a threshold, and how often to ask it",
        "description": "Save a question to be asked on a clock, and told to whoever subscribes when the answer moves. Use this for anything the operator says to check nightly, weekly or monthly: it is how something gets done when nobody is in the conversation. The filter is the same grammar every list tool takes, so anything you can ask for you can watch. Best for what did NOT happen, which no event can report: a deposit that never advanced a stage, a service date that passed, an account nobody touched.",
        "tags": [
          "watches"
        ],
        "operationId": "post_v1_watches",
        "x-indraft-capability": "crm:configure",
        "x-indraft-scopes": [
          "crm:configure",
          "crm:admin"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "idempotencyKey": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 200,
                    "description": "Your own name for this write, so retrying it cannot do it twice. Send the same key again and you get the SAME result back rather than a second record, which is what makes a re-run safe after a timeout you never saw the answer to. Derive it from what the write is about, not from the clock: `nightly-sync-halden` retries correctly and a timestamp does not."
                  },
                  "expectedVersion": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "The version you read before deciding to write. If the record has moved since, the write is refused instead of overwriting whatever changed. Send it whenever you read, reasoned, and then wrote: without it the last writer wins and neither of you finds out."
                  },
                  "sourceId": {
                    "type": "string",
                    "description": "The recorded source this claim came from, if one exists. It attaches evidence to the write, so a person reading the field later can see where it came from rather than only who sent it."
                  },
                  "assertionKind": {
                    "type": "string",
                    "enum": [
                      "observed",
                      "inferred",
                      "imported",
                      "user_supplied"
                    ],
                    "description": "HOW YOU KNOW. This is the field the product is built around, so say what is true rather than what is strongest: `observed` you saw it stated directly, `imported` it came from a file or another system, `inferred` you worked it out, `user_supplied` a person told you in so many words. They rank, weakest first: inferred < imported < observed < user_supplied < confirmed. A weaker claim does not overwrite a stronger one; it is reported in `held[]` and the stored value stands, so an unattended re-run converges instead of eroding what somebody checked. `confirmed` is not accepted here: it means a person checked the value, and only a signed-in person can set it."
                  },
                  "attributionLabel": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120,
                    "description": "A short name for the work this write belongs to, shown beside the actor so one credential can distinguish separate jobs. It is recorded as CALLER-SUPPLIED and grants nothing: it changes no permission, no idempotency scope and no quota."
                  },
                  "dryRun": {
                    "type": "boolean",
                    "description": "Report what this write WOULD do and commit nothing. The response carries the same change list, held fields and refusals as the real call, so it is the way to check a risky write, or a whole import, before it lands. Nothing is metered."
                  },
                  "overrideStanding": {
                    "type": "boolean",
                    "description": "Apply this write even when the value standing in the record was asserted more strongly than this one. Absent means no, which is the safe answer for a re-run. WITHOUT IT, a write can be accepted and change nothing: precedence is confirmed > user_supplied > observed > imported > inferred, and a weaker claim leaves the standing value in place and reports the field in `held[]` rather than failing. That is the whole of why a write can return 200 and not take. WITH it, this write wins regardless of what it is overruling, INCLUDING a value a person confirmed, so an agent that sets it by default has switched the provenance mechanism off. Set it per write, when the caller knows its claim supersedes what is there."
                  },
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "objectType": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 64,
                    "description": "What is being counted: a canonical type, or the key of a type this workspace defined."
                  },
                  "filter": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 560
                    },
                    "minItems": 1,
                    "maxItems": 8,
                    "description": "Predicates, all of which must hold, written field:op:value. Only fields an index serves are accepted, and asking for one that is not names the ones that are."
                  },
                  "threshold": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 1000000
                  },
                  "everyHours": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 720
                  }
                },
                "required": [
                  "name",
                  "objectType",
                  "filter",
                  "everyHours"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "watch": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "name": {
                          "type": "string"
                        },
                        "objectType": {
                          "type": "string"
                        },
                        "filter": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "additionalProperties": {}
                          }
                        },
                        "threshold": {
                          "type": "integer"
                        },
                        "everyHours": {
                          "type": "integer"
                        },
                        "lastCount": {
                          "type": "integer"
                        },
                        "lastCheckedAt": {
                          "type": "string"
                        },
                        "lastFiredAt": {
                          "type": "string"
                        },
                        "disabledAt": {
                          "type": "string"
                        },
                        "createdAt": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id",
                        "name",
                        "objectType",
                        "filter",
                        "threshold",
                        "everyHours",
                        "lastCount",
                        "lastCheckedAt",
                        "lastFiredAt",
                        "disabledAt",
                        "createdAt"
                      ],
                      "additionalProperties": true
                    },
                    "mutation": {
                      "type": "object",
                      "properties": {
                        "mutationId": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "created",
                            "updated",
                            "matched",
                            "archived",
                            "merged",
                            "reverted",
                            "noop"
                          ],
                          "description": "What the write did. `noop` means it was accepted and changed nothing, because every value it carried already matched what was stored. IT IS NOT METERED: a noop does not count against your monthly change allowance, so a nightly sync that finds nothing new costs nothing. Neither does a write that only REDUCES what a workspace holds. `matched` means an upsert found an existing record on real identity evidence rather than creating a second one; `reverted` and `merged` are the undo and duplicate paths, and both are ordinary writes that count."
                        },
                        "targetId": {
                          "type": "string"
                        },
                        "record": {},
                        "changes": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "before": {},
                              "after": {}
                            },
                            "required": [
                              "field"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "held": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "kept": {},
                              "proposed": {},
                              "standing": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "incoming": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "actorId": {
                                "type": "string",
                                "minLength": 1
                              },
                              "assertedAt": {
                                "type": "string",
                                "minLength": 1
                              }
                            },
                            "required": [
                              "field",
                              "standing",
                              "incoming",
                              "actorId",
                              "assertedAt"
                            ],
                            "additionalProperties": false
                          },
                          "description": "Fields this write asked to change and did not, because the value standing in the record was asserted more strongly. THIS IS WHY A WRITE CAN RETURN 200 AND CHANGE NOTHING, and a caller that ignores it will believe it wrote something it did not. Precedence is confirmed > user_supplied > observed > imported > inferred, and a write carrying no `assertionKind` is weakest of all. Each entry reports the field, what the record still says, what you proposed, which claim won, and who made it. Send `overrideStanding` to write anyway, per write, when your claim really does supersede theirs."
                        },
                        "matchedBy": {
                          "type": "string",
                          "enum": [
                            "email",
                            "domain",
                            "external_id",
                            "idempotency_key",
                            "explicit_id"
                          ]
                        },
                        "reversible": {
                          "type": "boolean"
                        },
                        "replayed": {
                          "type": "boolean"
                        },
                        "dryRun": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "mutationId",
                        "status",
                        "reversible"
                      ],
                      "additionalProperties": false
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "watch",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "A product quota is spent, or the subscription is not active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A conflict the caller can resolve: a stale expectedVersion, an idempotency key reused for different input, an ambiguous or duplicate identity, or a merge that no longer applies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The body, or a single record inside it, exceeds its bound.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "507": {
            "description": "The workspace is at its storage ceiling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/watches/{id}": {
      "delete": {
        "summary": "Stop asking",
        "description": "Stop asking a saved question. The watch keeps its history and simply goes quiet; nothing it already reported is removed.",
        "tags": [
          "watches"
        ],
        "operationId": "delete_v1_watches__id_",
        "x-indraft-capability": "crm:configure",
        "x-indraft-scopes": [
          "crm:configure",
          "crm:admin"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The watche id, as returned by the call that created or matched it.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "idempotencyKey": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 200,
                    "description": "Your own name for this write, so retrying it cannot do it twice. Send the same key again and you get the SAME result back rather than a second record, which is what makes a re-run safe after a timeout you never saw the answer to. Derive it from what the write is about, not from the clock: `nightly-sync-halden` retries correctly and a timestamp does not."
                  },
                  "expectedVersion": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "The version you read before deciding to write. If the record has moved since, the write is refused instead of overwriting whatever changed. Send it whenever you read, reasoned, and then wrote: without it the last writer wins and neither of you finds out."
                  },
                  "sourceId": {
                    "type": "string",
                    "description": "The recorded source this claim came from, if one exists. It attaches evidence to the write, so a person reading the field later can see where it came from rather than only who sent it."
                  },
                  "assertionKind": {
                    "type": "string",
                    "enum": [
                      "observed",
                      "inferred",
                      "imported",
                      "user_supplied"
                    ],
                    "description": "HOW YOU KNOW. This is the field the product is built around, so say what is true rather than what is strongest: `observed` you saw it stated directly, `imported` it came from a file or another system, `inferred` you worked it out, `user_supplied` a person told you in so many words. They rank, weakest first: inferred < imported < observed < user_supplied < confirmed. A weaker claim does not overwrite a stronger one; it is reported in `held[]` and the stored value stands, so an unattended re-run converges instead of eroding what somebody checked. `confirmed` is not accepted here: it means a person checked the value, and only a signed-in person can set it."
                  },
                  "attributionLabel": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120,
                    "description": "A short name for the work this write belongs to, shown beside the actor so one credential can distinguish separate jobs. It is recorded as CALLER-SUPPLIED and grants nothing: it changes no permission, no idempotency scope and no quota."
                  },
                  "dryRun": {
                    "type": "boolean",
                    "description": "Report what this write WOULD do and commit nothing. The response carries the same change list, held fields and refusals as the real call, so it is the way to check a risky write, or a whole import, before it lands. Nothing is metered."
                  },
                  "overrideStanding": {
                    "type": "boolean",
                    "description": "Apply this write even when the value standing in the record was asserted more strongly than this one. Absent means no, which is the safe answer for a re-run. WITHOUT IT, a write can be accepted and change nothing: precedence is confirmed > user_supplied > observed > imported > inferred, and a weaker claim leaves the standing value in place and reports the field in `held[]` rather than failing. That is the whole of why a write can return 200 and not take. WITH it, this write wins regardless of what it is overruling, INCLUDING a value a person confirmed, so an agent that sets it by default has switched the provenance mechanism off. Set it per write, when the caller knows its claim supersedes what is there."
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "stopped": {
                      "type": "boolean"
                    },
                    "mutation": {
                      "type": "object",
                      "properties": {
                        "mutationId": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "created",
                            "updated",
                            "matched",
                            "archived",
                            "merged",
                            "reverted",
                            "noop"
                          ],
                          "description": "What the write did. `noop` means it was accepted and changed nothing, because every value it carried already matched what was stored. IT IS NOT METERED: a noop does not count against your monthly change allowance, so a nightly sync that finds nothing new costs nothing. Neither does a write that only REDUCES what a workspace holds. `matched` means an upsert found an existing record on real identity evidence rather than creating a second one; `reverted` and `merged` are the undo and duplicate paths, and both are ordinary writes that count."
                        },
                        "targetId": {
                          "type": "string"
                        },
                        "record": {},
                        "changes": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "before": {},
                              "after": {}
                            },
                            "required": [
                              "field"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "held": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 128
                              },
                              "kept": {},
                              "proposed": {},
                              "standing": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "incoming": {
                                "type": "string",
                                "enum": [
                                  "observed",
                                  "inferred",
                                  "imported",
                                  "user_supplied",
                                  "confirmed"
                                ]
                              },
                              "actorId": {
                                "type": "string",
                                "minLength": 1
                              },
                              "assertedAt": {
                                "type": "string",
                                "minLength": 1
                              }
                            },
                            "required": [
                              "field",
                              "standing",
                              "incoming",
                              "actorId",
                              "assertedAt"
                            ],
                            "additionalProperties": false
                          },
                          "description": "Fields this write asked to change and did not, because the value standing in the record was asserted more strongly. THIS IS WHY A WRITE CAN RETURN 200 AND CHANGE NOTHING, and a caller that ignores it will believe it wrote something it did not. Precedence is confirmed > user_supplied > observed > imported > inferred, and a write carrying no `assertionKind` is weakest of all. Each entry reports the field, what the record still says, what you proposed, which claim won, and who made it. Send `overrideStanding` to write anyway, per write, when your claim really does supersede theirs."
                        },
                        "matchedBy": {
                          "type": "string",
                          "enum": [
                            "email",
                            "domain",
                            "external_id",
                            "idempotency_key",
                            "explicit_id"
                          ]
                        },
                        "reversible": {
                          "type": "boolean"
                        },
                        "replayed": {
                          "type": "boolean"
                        },
                        "dryRun": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "mutationId",
                        "status",
                        "reversible"
                      ],
                      "additionalProperties": false
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "stopped",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "A product quota is spent, or the subscription is not active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such record, or it belongs to another workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A conflict the caller can resolve: a stale expectedVersion, an idempotency key reused for different input, an ambiguous or duplicate identity, or a merge that no longer applies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The body, or a single record inside it, exceeds its bound.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "507": {
            "description": "The workspace is at its storage ceiling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhooks/{id}": {
      "delete": {
        "summary": "Disable a webhook endpoint",
        "description": "Disables the endpoint and keeps its delivery history, so a failure you are still investigating does not disappear when you stop the bleeding.",
        "tags": [
          "webhooks"
        ],
        "operationId": "delete_v1_webhooks__id_",
        "x-indraft-capability": "crm:configure",
        "x-indraft-scopes": [
          "crm:configure",
          "crm:admin"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The webhook id, as returned by the call that created or matched it.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "disabled": {
                      "type": "boolean"
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "disabled",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "A product quota is spent, or the subscription is not active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such record, or it belongs to another workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A conflict the caller can resolve: a stale expectedVersion, an idempotency key reused for different input, an ambiguous or duplicate identity, or a merge that no longer applies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "507": {
            "description": "The workspace is at its storage ceiling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhooks/deliveries": {
      "get": {
        "summary": "Recent delivery attempts and their outcomes",
        "description": "Every attempt, its response status, how many attempts have been made and when the next one is due. This is the first place to look when a workflow stopped running, and usually the last.",
        "tags": [
          "webhooks"
        ],
        "operationId": "get_v1_webhooks_deliveries",
        "x-indraft-capability": "crm:read",
        "x-indraft-scopes": [
          "crm:read",
          "crm:write",
          "crm:configure",
          "crm:admin",
          "crm:revert",
          "data:export"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "deliveries": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "eventId": {
                            "type": "string"
                          },
                          "endpointId": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "pending",
                              "delivered",
                              "failed",
                              "exhausted"
                            ]
                          },
                          "attempts": {
                            "type": "integer"
                          },
                          "nextAttemptAt": {
                            "type": "string"
                          },
                          "responseStatus": {
                            "type": "integer"
                          },
                          "error": {
                            "type": "string"
                          },
                          "deliveredAt": {
                            "type": "string"
                          },
                          "createdAt": {
                            "type": "string"
                          },
                          "updatedAt": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "eventId",
                          "endpointId",
                          "status",
                          "attempts",
                          "nextAttemptAt",
                          "responseStatus",
                          "error",
                          "deliveredAt",
                          "createdAt",
                          "updatedAt"
                        ],
                        "additionalProperties": true
                      }
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "deliveries",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhooks/events/{id}/replay": {
      "post": {
        "summary": "Queue an event for delivery again",
        "description": "Queues one event to a subscribed endpoint again. Per endpoint, so replaying to a workflow you have just fixed does not re-deliver to the three that were fine.",
        "tags": [
          "webhooks"
        ],
        "operationId": "post_v1_webhooks_events__id__replay",
        "x-indraft-capability": "crm:configure",
        "x-indraft-scopes": [
          "crm:configure",
          "crm:admin"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The event id, as returned by the call that created or matched it.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "queued": {
                      "type": "integer"
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "queued",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "A product quota is spent, or the subscription is not active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such record, or it belongs to another workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A conflict the caller can resolve: a stale expectedVersion, an idempotency key reused for different input, an ambiguous or duplicate identity, or a merge that no longer applies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "507": {
            "description": "The workspace is at its storage ceiling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/export": {
      "get": {
        "summary": "Export every record, custom object type, and the change ledger, as one JSON file",
        "description": "Every record, every type you defined, and the ledger, in one documented file. Needs a credential explicitly created to export whose creator is an owner, so it is not something a token left in a configuration file can do quietly. Above 100 MB it refuses rather than returning part of your workspace.",
        "tags": [
          "export"
        ],
        "operationId": "get_v1_export",
        "x-indraft-capability": "data:export",
        "x-indraft-scopes": [
          "data:export"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "format": {
                      "type": "string",
                      "enum": [
                        "indraft.workspace-export"
                      ]
                    },
                    "version": {
                      "type": "string",
                      "enum": [
                        1
                      ]
                    },
                    "exportedAt": {
                      "type": "string"
                    },
                    "workspaceId": {
                      "type": "string"
                    },
                    "tables": {
                      "type": "object",
                      "additionalProperties": {
                        "type": "array",
                        "items": {
                          "type": "object",
                          "additionalProperties": {}
                        }
                      }
                    },
                    "counts": {
                      "type": "object",
                      "additionalProperties": {
                        "type": "integer"
                      }
                    }
                  },
                  "required": [
                    "format",
                    "version",
                    "exportedAt",
                    "workspaceId",
                    "tables",
                    "counts"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/export.zip": {
      "get": {
        "summary": "Export the whole workspace as an archive of CSV files and one JSON document",
        "description": "The same contents as the JSON export, as one spreadsheet per table plus a written explanation of how the files join up. It opens in Excel, Numbers, Sheets and LibreOffice with no conversion.",
        "tags": [
          "export"
        ],
        "operationId": "get_v1_export_zip",
        "x-indraft-capability": "data:export",
        "x-indraft-scopes": [
          "data:export"
        ],
        "responses": {
          "200": {
            "description": "A ZIP holding README.txt, manifest.json, workspace.json and one CSV per table. Streamed, so the first bytes arrive before the last table has been read.",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/zip": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/bulk": {
      "post": {
        "summary": "Apply a bounded batch of operations",
        "description": "Apply up to 100 operations in one call, so a first population session is not one call per record. Each item is independently idempotent; one failure does not discard the rest, and the result reports each item's outcome.",
        "tags": [
          "bulk"
        ],
        "operationId": "post_v1_bulk",
        "x-indraft-capability": "crm:write",
        "x-indraft-scopes": [
          "crm:write",
          "crm:admin"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "idempotencyKey": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 200,
                    "description": "Your own name for this write, so retrying it cannot do it twice. Send the same key again and you get the SAME result back rather than a second record, which is what makes a re-run safe after a timeout you never saw the answer to. Derive it from what the write is about, not from the clock: `nightly-sync-halden` retries correctly and a timestamp does not."
                  },
                  "expectedVersion": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "The version you read before deciding to write. If the record has moved since, the write is refused instead of overwriting whatever changed. Send it whenever you read, reasoned, and then wrote: without it the last writer wins and neither of you finds out."
                  },
                  "sourceId": {
                    "type": "string",
                    "description": "The recorded source this claim came from, if one exists. It attaches evidence to the write, so a person reading the field later can see where it came from rather than only who sent it."
                  },
                  "assertionKind": {
                    "type": "string",
                    "enum": [
                      "observed",
                      "inferred",
                      "imported",
                      "user_supplied"
                    ],
                    "description": "HOW YOU KNOW. This is the field the product is built around, so say what is true rather than what is strongest: `observed` you saw it stated directly, `imported` it came from a file or another system, `inferred` you worked it out, `user_supplied` a person told you in so many words. They rank, weakest first: inferred < imported < observed < user_supplied < confirmed. A weaker claim does not overwrite a stronger one; it is reported in `held[]` and the stored value stands, so an unattended re-run converges instead of eroding what somebody checked. `confirmed` is not accepted here: it means a person checked the value, and only a signed-in person can set it."
                  },
                  "attributionLabel": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120,
                    "description": "A short name for the work this write belongs to, shown beside the actor so one credential can distinguish separate jobs. It is recorded as CALLER-SUPPLIED and grants nothing: it changes no permission, no idempotency scope and no quota."
                  },
                  "dryRun": {
                    "type": "boolean",
                    "description": "Report what this write WOULD do and commit nothing. The response carries the same change list, held fields and refusals as the real call, so it is the way to check a risky write, or a whole import, before it lands. Nothing is metered."
                  },
                  "overrideStanding": {
                    "type": "boolean",
                    "description": "Apply this write even when the value standing in the record was asserted more strongly than this one. Absent means no, which is the safe answer for a re-run. WITHOUT IT, a write can be accepted and change nothing: precedence is confirmed > user_supplied > observed > imported > inferred, and a weaker claim leaves the standing value in place and reports the field in `held[]` rather than failing. That is the whole of why a write can return 200 and not take. WITH it, this write wins regardless of what it is overruling, INCLUDING a value a person confirmed, so an agent that sets it by default has switched the provenance mechanism off. Set it per write, when the caller knows its claim supersedes what is there."
                  },
                  "operations": {
                    "type": "array",
                    "items": {
                      "oneOf": [
                        {
                          "type": "object",
                          "properties": {
                            "operation": {
                              "type": "string",
                              "enum": [
                                "upsert_company"
                              ]
                            },
                            "body": {
                              "type": "object",
                              "properties": {
                                "idempotencyKey": {
                                  "type": "string",
                                  "minLength": 8,
                                  "maxLength": 200,
                                  "description": "Your own name for this write, so retrying it cannot do it twice. Send the same key again and you get the SAME result back rather than a second record, which is what makes a re-run safe after a timeout you never saw the answer to. Derive it from what the write is about, not from the clock: `nightly-sync-halden` retries correctly and a timestamp does not."
                                },
                                "expectedVersion": {
                                  "type": "integer",
                                  "minimum": 0,
                                  "description": "The version you read before deciding to write. If the record has moved since, the write is refused instead of overwriting whatever changed. Send it whenever you read, reasoned, and then wrote: without it the last writer wins and neither of you finds out."
                                },
                                "sourceId": {
                                  "type": "string",
                                  "description": "The recorded source this claim came from, if one exists. It attaches evidence to the write, so a person reading the field later can see where it came from rather than only who sent it."
                                },
                                "assertionKind": {
                                  "type": "string",
                                  "enum": [
                                    "observed",
                                    "inferred",
                                    "imported",
                                    "user_supplied"
                                  ],
                                  "description": "HOW YOU KNOW. This is the field the product is built around, so say what is true rather than what is strongest: `observed` you saw it stated directly, `imported` it came from a file or another system, `inferred` you worked it out, `user_supplied` a person told you in so many words. They rank, weakest first: inferred < imported < observed < user_supplied < confirmed. A weaker claim does not overwrite a stronger one; it is reported in `held[]` and the stored value stands, so an unattended re-run converges instead of eroding what somebody checked. `confirmed` is not accepted here: it means a person checked the value, and only a signed-in person can set it."
                                },
                                "attributionLabel": {
                                  "type": "string",
                                  "minLength": 1,
                                  "maxLength": 120,
                                  "description": "A short name for the work this write belongs to, shown beside the actor so one credential can distinguish separate jobs. It is recorded as CALLER-SUPPLIED and grants nothing: it changes no permission, no idempotency scope and no quota."
                                },
                                "dryRun": {
                                  "type": "boolean",
                                  "description": "Report what this write WOULD do and commit nothing. The response carries the same change list, held fields and refusals as the real call, so it is the way to check a risky write, or a whole import, before it lands. Nothing is metered."
                                },
                                "overrideStanding": {
                                  "type": "boolean",
                                  "description": "Apply this write even when the value standing in the record was asserted more strongly than this one. Absent means no, which is the safe answer for a re-run. WITHOUT IT, a write can be accepted and change nothing: precedence is confirmed > user_supplied > observed > imported > inferred, and a weaker claim leaves the standing value in place and reports the field in `held[]` rather than failing. That is the whole of why a write can return 200 and not take. WITH it, this write wins regardless of what it is overruling, INCLUDING a value a person confirmed, so an agent that sets it by default has switched the provenance mechanism off. Set it per write, when the caller knows its claim supersedes what is there."
                                },
                                "id": {
                                  "type": "string",
                                  "description": "Update this exact company. Without it the call matches on identity evidence, in order: an external identity, then the normalised domain. Send the id when you already know which record you mean, which is the only way to be certain."
                                },
                                "name": {
                                  "type": "string",
                                  "minLength": 1,
                                  "maxLength": 300,
                                  "description": "The company's name. It is NOT identity: two companies may share a name, so a name alone never matches an existing record and creates a second one."
                                },
                                "domain": {
                                  "type": "string",
                                  "maxLength": 200,
                                  "description": "The company's own domain, which IS identity: it is normalised and matched on, so sending it is what stops a nightly sync creating the same company twice. Send the domain, not a URL."
                                },
                                "website": {
                                  "type": "string",
                                  "maxLength": 500,
                                  "description": "The full URL a person would open. Not matched on; `domain` is."
                                },
                                "industry": {
                                  "type": "string",
                                  "maxLength": 200,
                                  "description": "What the company does, in words."
                                },
                                "lifecycle": {
                                  "type": "object",
                                  "properties": {
                                    "category": {
                                      "type": "string",
                                      "enum": [
                                        "lead",
                                        "prospect",
                                        "customer",
                                        "former_customer",
                                        "partner",
                                        "other"
                                      ],
                                      "description": "Where this stands with you, from a fixed list so it can be counted and filtered across the workspace."
                                    },
                                    "label": {
                                      "type": "string",
                                      "minLength": 1,
                                      "maxLength": 200,
                                      "description": "Your own word for it, shown to people. The category is what the product reasons with; this is what your team calls it."
                                    }
                                  },
                                  "required": [
                                    "category"
                                  ],
                                  "additionalProperties": false,
                                  "description": "Where this company stands with you: the stage, and your own label for it."
                                },
                                "ownerActorId": {
                                  "type": "string",
                                  "minLength": 1,
                                  "description": "Who owns this record: a member, or an agent. Null unassigns. Ownership is filterable, so it is how a person finds their own accounts."
                                },
                                "customFields": {
                                  "type": "object",
                                  "additionalProperties": {
                                    "anyOf": [
                                      {
                                        "type": "string",
                                        "maxLength": 2000
                                      },
                                      {
                                        "type": "integer"
                                      },
                                      {
                                        "type": "boolean"
                                      },
                                      {
                                        "type": "null"
                                      }
                                    ]
                                  },
                                  "description": "Values for fields this workspace defined, keyed by the field's key. Read the schema first: a key that is not declared is REFUSED, with the available keys in the error, rather than stored where nobody will find it. Send null to clear one."
                                },
                                "tags": {
                                  "type": "array",
                                  "items": {
                                    "type": "string",
                                    "minLength": 1,
                                    "maxLength": 60
                                  },
                                  "maxItems": 50,
                                  "description": "Labels, with no hierarchy and no meaning beyond membership. This REPLACES the tags on the record rather than adding to them, so send the full set you want."
                                },
                                "externalProvider": {
                                  "type": "string",
                                  "minLength": 1,
                                  "maxLength": 120,
                                  "description": "Which system issued `externalId`, for example `salesforce` or `stripe`. Required with it: two systems each numbering their records from one is the normal case, so an id without its issuer is not an identity and is refused."
                                },
                                "externalId": {
                                  "type": "string",
                                  "minLength": 1,
                                  "maxLength": 200,
                                  "description": "This record's id in that other system. Matched on BEFORE domain or email, so an integration can sync without remembering our ids."
                                },
                                "createDistinct": {
                                  "type": "boolean",
                                  "description": "Create a new record even though the evidence matches an existing one. For the case where you know two look alike and really are different. Absent means match, which is the safe answer for a re-run."
                                }
                              },
                              "required": [
                                "name"
                              ],
                              "additionalProperties": false
                            }
                          },
                          "required": [
                            "operation",
                            "body"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "object",
                          "properties": {
                            "operation": {
                              "type": "string",
                              "enum": [
                                "upsert_contact"
                              ]
                            },
                            "body": {
                              "type": "object",
                              "properties": {
                                "idempotencyKey": {
                                  "type": "string",
                                  "minLength": 8,
                                  "maxLength": 200,
                                  "description": "Your own name for this write, so retrying it cannot do it twice. Send the same key again and you get the SAME result back rather than a second record, which is what makes a re-run safe after a timeout you never saw the answer to. Derive it from what the write is about, not from the clock: `nightly-sync-halden` retries correctly and a timestamp does not."
                                },
                                "expectedVersion": {
                                  "type": "integer",
                                  "minimum": 0,
                                  "description": "The version you read before deciding to write. If the record has moved since, the write is refused instead of overwriting whatever changed. Send it whenever you read, reasoned, and then wrote: without it the last writer wins and neither of you finds out."
                                },
                                "sourceId": {
                                  "type": "string",
                                  "description": "The recorded source this claim came from, if one exists. It attaches evidence to the write, so a person reading the field later can see where it came from rather than only who sent it."
                                },
                                "assertionKind": {
                                  "type": "string",
                                  "enum": [
                                    "observed",
                                    "inferred",
                                    "imported",
                                    "user_supplied"
                                  ],
                                  "description": "HOW YOU KNOW. This is the field the product is built around, so say what is true rather than what is strongest: `observed` you saw it stated directly, `imported` it came from a file or another system, `inferred` you worked it out, `user_supplied` a person told you in so many words. They rank, weakest first: inferred < imported < observed < user_supplied < confirmed. A weaker claim does not overwrite a stronger one; it is reported in `held[]` and the stored value stands, so an unattended re-run converges instead of eroding what somebody checked. `confirmed` is not accepted here: it means a person checked the value, and only a signed-in person can set it."
                                },
                                "attributionLabel": {
                                  "type": "string",
                                  "minLength": 1,
                                  "maxLength": 120,
                                  "description": "A short name for the work this write belongs to, shown beside the actor so one credential can distinguish separate jobs. It is recorded as CALLER-SUPPLIED and grants nothing: it changes no permission, no idempotency scope and no quota."
                                },
                                "dryRun": {
                                  "type": "boolean",
                                  "description": "Report what this write WOULD do and commit nothing. The response carries the same change list, held fields and refusals as the real call, so it is the way to check a risky write, or a whole import, before it lands. Nothing is metered."
                                },
                                "overrideStanding": {
                                  "type": "boolean",
                                  "description": "Apply this write even when the value standing in the record was asserted more strongly than this one. Absent means no, which is the safe answer for a re-run. WITHOUT IT, a write can be accepted and change nothing: precedence is confirmed > user_supplied > observed > imported > inferred, and a weaker claim leaves the standing value in place and reports the field in `held[]` rather than failing. That is the whole of why a write can return 200 and not take. WITH it, this write wins regardless of what it is overruling, INCLUDING a value a person confirmed, so an agent that sets it by default has switched the provenance mechanism off. Set it per write, when the caller knows its claim supersedes what is there."
                                },
                                "id": {
                                  "type": "string"
                                },
                                "displayName": {
                                  "type": "string",
                                  "minLength": 1,
                                  "maxLength": 300
                                },
                                "email": {
                                  "type": "string",
                                  "maxLength": 200
                                },
                                "phone": {
                                  "type": "string",
                                  "maxLength": 60
                                },
                                "title": {
                                  "type": "string",
                                  "maxLength": 200
                                },
                                "lifecycle": {
                                  "type": "object",
                                  "properties": {
                                    "category": {
                                      "type": "string",
                                      "enum": [
                                        "lead",
                                        "prospect",
                                        "customer",
                                        "former_customer",
                                        "partner",
                                        "other"
                                      ],
                                      "description": "Where this stands with you, from a fixed list so it can be counted and filtered across the workspace."
                                    },
                                    "label": {
                                      "type": "string",
                                      "minLength": 1,
                                      "maxLength": 200,
                                      "description": "Your own word for it, shown to people. The category is what the product reasons with; this is what your team calls it."
                                    }
                                  },
                                  "required": [
                                    "category"
                                  ],
                                  "additionalProperties": false
                                },
                                "companyId": {
                                  "type": "string"
                                },
                                "companyRole": {
                                  "type": "string",
                                  "enum": [
                                    "employee",
                                    "founder",
                                    "executive",
                                    "advisor",
                                    "other"
                                  ]
                                },
                                "ownerActorId": {
                                  "type": "string",
                                  "minLength": 1
                                },
                                "customFields": {
                                  "type": "object",
                                  "additionalProperties": {
                                    "anyOf": [
                                      {
                                        "type": "string",
                                        "maxLength": 2000
                                      },
                                      {
                                        "type": "integer"
                                      },
                                      {
                                        "type": "boolean"
                                      },
                                      {
                                        "type": "null"
                                      }
                                    ]
                                  },
                                  "description": "Values for fields this workspace defined, keyed by the field's key. Read the schema first: a key that is not declared is REFUSED, with the available keys in the error, rather than stored where nobody will find it. Send null to clear one."
                                },
                                "tags": {
                                  "type": "array",
                                  "items": {
                                    "type": "string",
                                    "minLength": 1,
                                    "maxLength": 60
                                  },
                                  "maxItems": 50
                                },
                                "externalProvider": {
                                  "type": "string",
                                  "minLength": 1,
                                  "maxLength": 120,
                                  "description": "Which system issued `externalId`, for example `salesforce` or `stripe`. Required with it: two systems each numbering their records from one is the normal case, so an id without its issuer is not an identity and is refused."
                                },
                                "externalId": {
                                  "type": "string",
                                  "minLength": 1,
                                  "maxLength": 200,
                                  "description": "This record's id in that other system. Matched on BEFORE domain or email, so an integration can sync without remembering our ids."
                                },
                                "createDistinct": {
                                  "type": "boolean",
                                  "description": "Create a new record even though the evidence matches an existing one. For the case where you know two look alike and really are different. Absent means match, which is the safe answer for a re-run."
                                }
                              },
                              "required": [
                                "displayName"
                              ],
                              "additionalProperties": false
                            }
                          },
                          "required": [
                            "operation",
                            "body"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "object",
                          "properties": {
                            "operation": {
                              "type": "string",
                              "enum": [
                                "create_opportunity"
                              ]
                            },
                            "body": {
                              "type": "object",
                              "properties": {
                                "idempotencyKey": {
                                  "type": "string",
                                  "minLength": 8,
                                  "maxLength": 200,
                                  "description": "Your own name for this write, so retrying it cannot do it twice. Send the same key again and you get the SAME result back rather than a second record, which is what makes a re-run safe after a timeout you never saw the answer to. Derive it from what the write is about, not from the clock: `nightly-sync-halden` retries correctly and a timestamp does not."
                                },
                                "expectedVersion": {
                                  "type": "integer",
                                  "minimum": 0,
                                  "description": "The version you read before deciding to write. If the record has moved since, the write is refused instead of overwriting whatever changed. Send it whenever you read, reasoned, and then wrote: without it the last writer wins and neither of you finds out."
                                },
                                "sourceId": {
                                  "type": "string",
                                  "description": "The recorded source this claim came from, if one exists. It attaches evidence to the write, so a person reading the field later can see where it came from rather than only who sent it."
                                },
                                "assertionKind": {
                                  "type": "string",
                                  "enum": [
                                    "observed",
                                    "inferred",
                                    "imported",
                                    "user_supplied"
                                  ],
                                  "description": "HOW YOU KNOW. This is the field the product is built around, so say what is true rather than what is strongest: `observed` you saw it stated directly, `imported` it came from a file or another system, `inferred` you worked it out, `user_supplied` a person told you in so many words. They rank, weakest first: inferred < imported < observed < user_supplied < confirmed. A weaker claim does not overwrite a stronger one; it is reported in `held[]` and the stored value stands, so an unattended re-run converges instead of eroding what somebody checked. `confirmed` is not accepted here: it means a person checked the value, and only a signed-in person can set it."
                                },
                                "attributionLabel": {
                                  "type": "string",
                                  "minLength": 1,
                                  "maxLength": 120,
                                  "description": "A short name for the work this write belongs to, shown beside the actor so one credential can distinguish separate jobs. It is recorded as CALLER-SUPPLIED and grants nothing: it changes no permission, no idempotency scope and no quota."
                                },
                                "dryRun": {
                                  "type": "boolean",
                                  "description": "Report what this write WOULD do and commit nothing. The response carries the same change list, held fields and refusals as the real call, so it is the way to check a risky write, or a whole import, before it lands. Nothing is metered."
                                },
                                "overrideStanding": {
                                  "type": "boolean",
                                  "description": "Apply this write even when the value standing in the record was asserted more strongly than this one. Absent means no, which is the safe answer for a re-run. WITHOUT IT, a write can be accepted and change nothing: precedence is confirmed > user_supplied > observed > imported > inferred, and a weaker claim leaves the standing value in place and reports the field in `held[]` rather than failing. That is the whole of why a write can return 200 and not take. WITH it, this write wins regardless of what it is overruling, INCLUDING a value a person confirmed, so an agent that sets it by default has switched the provenance mechanism off. Set it per write, when the caller knows its claim supersedes what is there."
                                },
                                "name": {
                                  "type": "string",
                                  "minLength": 1,
                                  "maxLength": 300
                                },
                                "stageId": {
                                  "type": "string",
                                  "description": "Only records in this stage. Stage ids come from the schema call, which lists every pipeline and its stages in order."
                                },
                                "companyId": {
                                  "type": "string"
                                },
                                "amountMinor": {
                                  "type": "integer",
                                  "minimum": -9007199254740991,
                                  "maximum": 9007199254740991
                                },
                                "currency": {
                                  "type": "string",
                                  "pattern": "^[A-Z]{3}$"
                                },
                                "expectedCloseDate": {
                                  "type": "string"
                                },
                                "ownerActorId": {
                                  "type": "string",
                                  "minLength": 1
                                },
                                "probabilityBps": {
                                  "type": "integer",
                                  "minimum": 0,
                                  "maximum": 10000
                                },
                                "customFields": {
                                  "type": "object",
                                  "additionalProperties": {
                                    "anyOf": [
                                      {
                                        "type": "string",
                                        "maxLength": 2000
                                      },
                                      {
                                        "type": "integer"
                                      },
                                      {
                                        "type": "boolean"
                                      },
                                      {
                                        "type": "null"
                                      }
                                    ]
                                  },
                                  "description": "Values for fields this workspace defined, keyed by the field's key. Read the schema first: a key that is not declared is REFUSED, with the available keys in the error, rather than stored where nobody will find it. Send null to clear one."
                                }
                              },
                              "required": [
                                "name"
                              ],
                              "additionalProperties": false
                            }
                          },
                          "required": [
                            "operation",
                            "body"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "object",
                          "properties": {
                            "operation": {
                              "type": "string",
                              "enum": [
                                "advance_opportunity"
                              ]
                            },
                            "body": {
                              "type": "object",
                              "properties": {
                                "idempotencyKey": {
                                  "type": "string",
                                  "minLength": 8,
                                  "maxLength": 200,
                                  "description": "Your own name for this write, so retrying it cannot do it twice. Send the same key again and you get the SAME result back rather than a second record, which is what makes a re-run safe after a timeout you never saw the answer to. Derive it from what the write is about, not from the clock: `nightly-sync-halden` retries correctly and a timestamp does not."
                                },
                                "expectedVersion": {
                                  "type": "integer",
                                  "minimum": 0,
                                  "description": "The version you read before deciding to write. If the record has moved since, the write is refused instead of overwriting whatever changed. Send it whenever you read, reasoned, and then wrote: without it the last writer wins and neither of you finds out."
                                },
                                "sourceId": {
                                  "type": "string",
                                  "description": "The recorded source this claim came from, if one exists. It attaches evidence to the write, so a person reading the field later can see where it came from rather than only who sent it."
                                },
                                "assertionKind": {
                                  "type": "string",
                                  "enum": [
                                    "observed",
                                    "inferred",
                                    "imported",
                                    "user_supplied"
                                  ],
                                  "description": "HOW YOU KNOW. This is the field the product is built around, so say what is true rather than what is strongest: `observed` you saw it stated directly, `imported` it came from a file or another system, `inferred` you worked it out, `user_supplied` a person told you in so many words. They rank, weakest first: inferred < imported < observed < user_supplied < confirmed. A weaker claim does not overwrite a stronger one; it is reported in `held[]` and the stored value stands, so an unattended re-run converges instead of eroding what somebody checked. `confirmed` is not accepted here: it means a person checked the value, and only a signed-in person can set it."
                                },
                                "attributionLabel": {
                                  "type": "string",
                                  "minLength": 1,
                                  "maxLength": 120,
                                  "description": "A short name for the work this write belongs to, shown beside the actor so one credential can distinguish separate jobs. It is recorded as CALLER-SUPPLIED and grants nothing: it changes no permission, no idempotency scope and no quota."
                                },
                                "dryRun": {
                                  "type": "boolean",
                                  "description": "Report what this write WOULD do and commit nothing. The response carries the same change list, held fields and refusals as the real call, so it is the way to check a risky write, or a whole import, before it lands. Nothing is metered."
                                },
                                "overrideStanding": {
                                  "type": "boolean",
                                  "description": "Apply this write even when the value standing in the record was asserted more strongly than this one. Absent means no, which is the safe answer for a re-run. WITHOUT IT, a write can be accepted and change nothing: precedence is confirmed > user_supplied > observed > imported > inferred, and a weaker claim leaves the standing value in place and reports the field in `held[]` rather than failing. That is the whole of why a write can return 200 and not take. WITH it, this write wins regardless of what it is overruling, INCLUDING a value a person confirmed, so an agent that sets it by default has switched the provenance mechanism off. Set it per write, when the caller knows its claim supersedes what is there."
                                },
                                "stageId": {
                                  "type": "string",
                                  "minLength": 1
                                },
                                "opportunityId": {
                                  "type": "string",
                                  "minLength": 1
                                }
                              },
                              "required": [
                                "stageId",
                                "opportunityId"
                              ],
                              "additionalProperties": false
                            }
                          },
                          "required": [
                            "operation",
                            "body"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "object",
                          "properties": {
                            "operation": {
                              "type": "string",
                              "enum": [
                                "record_interaction"
                              ]
                            },
                            "body": {
                              "type": "object",
                              "properties": {
                                "idempotencyKey": {
                                  "type": "string",
                                  "minLength": 8,
                                  "maxLength": 200,
                                  "description": "Your own name for this write, so retrying it cannot do it twice. Send the same key again and you get the SAME result back rather than a second record, which is what makes a re-run safe after a timeout you never saw the answer to. Derive it from what the write is about, not from the clock: `nightly-sync-halden` retries correctly and a timestamp does not."
                                },
                                "expectedVersion": {
                                  "type": "integer",
                                  "minimum": 0,
                                  "description": "The version you read before deciding to write. If the record has moved since, the write is refused instead of overwriting whatever changed. Send it whenever you read, reasoned, and then wrote: without it the last writer wins and neither of you finds out."
                                },
                                "sourceId": {
                                  "type": "string",
                                  "description": "The recorded source this claim came from, if one exists. It attaches evidence to the write, so a person reading the field later can see where it came from rather than only who sent it."
                                },
                                "assertionKind": {
                                  "type": "string",
                                  "enum": [
                                    "observed",
                                    "inferred",
                                    "imported",
                                    "user_supplied"
                                  ],
                                  "description": "HOW YOU KNOW. This is the field the product is built around, so say what is true rather than what is strongest: `observed` you saw it stated directly, `imported` it came from a file or another system, `inferred` you worked it out, `user_supplied` a person told you in so many words. They rank, weakest first: inferred < imported < observed < user_supplied < confirmed. A weaker claim does not overwrite a stronger one; it is reported in `held[]` and the stored value stands, so an unattended re-run converges instead of eroding what somebody checked. `confirmed` is not accepted here: it means a person checked the value, and only a signed-in person can set it."
                                },
                                "attributionLabel": {
                                  "type": "string",
                                  "minLength": 1,
                                  "maxLength": 120,
                                  "description": "A short name for the work this write belongs to, shown beside the actor so one credential can distinguish separate jobs. It is recorded as CALLER-SUPPLIED and grants nothing: it changes no permission, no idempotency scope and no quota."
                                },
                                "dryRun": {
                                  "type": "boolean",
                                  "description": "Report what this write WOULD do and commit nothing. The response carries the same change list, held fields and refusals as the real call, so it is the way to check a risky write, or a whole import, before it lands. Nothing is metered."
                                },
                                "overrideStanding": {
                                  "type": "boolean",
                                  "description": "Apply this write even when the value standing in the record was asserted more strongly than this one. Absent means no, which is the safe answer for a re-run. WITHOUT IT, a write can be accepted and change nothing: precedence is confirmed > user_supplied > observed > imported > inferred, and a weaker claim leaves the standing value in place and reports the field in `held[]` rather than failing. That is the whole of why a write can return 200 and not take. WITH it, this write wins regardless of what it is overruling, INCLUDING a value a person confirmed, so an agent that sets it by default has switched the provenance mechanism off. Set it per write, when the caller knows its claim supersedes what is there."
                                },
                                "interactionType": {
                                  "type": "string",
                                  "enum": [
                                    "email",
                                    "call",
                                    "meeting",
                                    "message",
                                    "note"
                                  ]
                                },
                                "direction": {
                                  "type": "string",
                                  "enum": [
                                    "inbound",
                                    "outbound",
                                    "internal"
                                  ]
                                },
                                "subject": {
                                  "type": "string",
                                  "maxLength": 200
                                },
                                "summary": {
                                  "type": "string",
                                  "minLength": 1,
                                  "maxLength": 4000
                                },
                                "occurredAt": {
                                  "type": "string"
                                },
                                "provider": {
                                  "type": "string",
                                  "maxLength": 200
                                },
                                "externalId": {
                                  "type": "string",
                                  "maxLength": 200
                                },
                                "evidenceText": {
                                  "type": "string",
                                  "maxLength": 2000
                                },
                                "customFields": {
                                  "type": "object",
                                  "additionalProperties": {
                                    "anyOf": [
                                      {
                                        "type": "string",
                                        "maxLength": 2000
                                      },
                                      {
                                        "type": "integer"
                                      },
                                      {
                                        "type": "boolean"
                                      },
                                      {
                                        "type": "null"
                                      }
                                    ]
                                  },
                                  "description": "Values for fields this workspace defined, keyed by the field's key. Read the schema first: a key that is not declared is REFUSED, with the available keys in the error, rather than stored where nobody will find it. Send null to clear one."
                                },
                                "companyIds": {
                                  "type": "array",
                                  "items": {
                                    "type": "string"
                                  },
                                  "maxItems": 100
                                },
                                "contactIds": {
                                  "type": "array",
                                  "items": {
                                    "type": "string"
                                  },
                                  "maxItems": 100
                                },
                                "opportunityIds": {
                                  "type": "array",
                                  "items": {
                                    "type": "string"
                                  },
                                  "maxItems": 100
                                }
                              },
                              "required": [
                                "interactionType",
                                "summary",
                                "occurredAt"
                              ],
                              "additionalProperties": false
                            }
                          },
                          "required": [
                            "operation",
                            "body"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "object",
                          "properties": {
                            "operation": {
                              "type": "string",
                              "enum": [
                                "create_task"
                              ]
                            },
                            "body": {
                              "type": "object",
                              "properties": {
                                "idempotencyKey": {
                                  "type": "string",
                                  "minLength": 8,
                                  "maxLength": 200,
                                  "description": "Your own name for this write, so retrying it cannot do it twice. Send the same key again and you get the SAME result back rather than a second record, which is what makes a re-run safe after a timeout you never saw the answer to. Derive it from what the write is about, not from the clock: `nightly-sync-halden` retries correctly and a timestamp does not."
                                },
                                "expectedVersion": {
                                  "type": "integer",
                                  "minimum": 0,
                                  "description": "The version you read before deciding to write. If the record has moved since, the write is refused instead of overwriting whatever changed. Send it whenever you read, reasoned, and then wrote: without it the last writer wins and neither of you finds out."
                                },
                                "sourceId": {
                                  "type": "string",
                                  "description": "The recorded source this claim came from, if one exists. It attaches evidence to the write, so a person reading the field later can see where it came from rather than only who sent it."
                                },
                                "assertionKind": {
                                  "type": "string",
                                  "enum": [
                                    "observed",
                                    "inferred",
                                    "imported",
                                    "user_supplied"
                                  ],
                                  "description": "HOW YOU KNOW. This is the field the product is built around, so say what is true rather than what is strongest: `observed` you saw it stated directly, `imported` it came from a file or another system, `inferred` you worked it out, `user_supplied` a person told you in so many words. They rank, weakest first: inferred < imported < observed < user_supplied < confirmed. A weaker claim does not overwrite a stronger one; it is reported in `held[]` and the stored value stands, so an unattended re-run converges instead of eroding what somebody checked. `confirmed` is not accepted here: it means a person checked the value, and only a signed-in person can set it."
                                },
                                "attributionLabel": {
                                  "type": "string",
                                  "minLength": 1,
                                  "maxLength": 120,
                                  "description": "A short name for the work this write belongs to, shown beside the actor so one credential can distinguish separate jobs. It is recorded as CALLER-SUPPLIED and grants nothing: it changes no permission, no idempotency scope and no quota."
                                },
                                "dryRun": {
                                  "type": "boolean",
                                  "description": "Report what this write WOULD do and commit nothing. The response carries the same change list, held fields and refusals as the real call, so it is the way to check a risky write, or a whole import, before it lands. Nothing is metered."
                                },
                                "overrideStanding": {
                                  "type": "boolean",
                                  "description": "Apply this write even when the value standing in the record was asserted more strongly than this one. Absent means no, which is the safe answer for a re-run. WITHOUT IT, a write can be accepted and change nothing: precedence is confirmed > user_supplied > observed > imported > inferred, and a weaker claim leaves the standing value in place and reports the field in `held[]` rather than failing. That is the whole of why a write can return 200 and not take. WITH it, this write wins regardless of what it is overruling, INCLUDING a value a person confirmed, so an agent that sets it by default has switched the provenance mechanism off. Set it per write, when the caller knows its claim supersedes what is there."
                                },
                                "title": {
                                  "type": "string",
                                  "minLength": 1,
                                  "maxLength": 300
                                },
                                "dueAt": {
                                  "type": "string"
                                },
                                "assigneeActorId": {
                                  "type": "string",
                                  "description": "Only tasks assigned to this actor. The actor id comes back on every change and in the schema call for the caller themselves."
                                },
                                "priority": {
                                  "type": "string",
                                  "enum": [
                                    "low",
                                    "normal",
                                    "high"
                                  ]
                                },
                                "companyIds": {
                                  "type": "array",
                                  "items": {
                                    "type": "string"
                                  },
                                  "maxItems": 100
                                },
                                "contactIds": {
                                  "type": "array",
                                  "items": {
                                    "type": "string"
                                  },
                                  "maxItems": 100
                                },
                                "opportunityIds": {
                                  "type": "array",
                                  "items": {
                                    "type": "string"
                                  },
                                  "maxItems": 100
                                },
                                "customFields": {
                                  "type": "object",
                                  "additionalProperties": {
                                    "anyOf": [
                                      {
                                        "type": "string",
                                        "maxLength": 2000
                                      },
                                      {
                                        "type": "integer"
                                      },
                                      {
                                        "type": "boolean"
                                      },
                                      {
                                        "type": "null"
                                      }
                                    ]
                                  },
                                  "description": "Values for fields this workspace defined, keyed by the field's key. Read the schema first: a key that is not declared is REFUSED, with the available keys in the error, rather than stored where nobody will find it. Send null to clear one."
                                }
                              },
                              "required": [
                                "title"
                              ],
                              "additionalProperties": false
                            }
                          },
                          "required": [
                            "operation",
                            "body"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "object",
                          "properties": {
                            "operation": {
                              "type": "string",
                              "enum": [
                                "upsert_object_record"
                              ]
                            },
                            "body": {
                              "type": "object",
                              "properties": {
                                "idempotencyKey": {
                                  "type": "string",
                                  "minLength": 8,
                                  "maxLength": 200,
                                  "description": "Your own name for this write, so retrying it cannot do it twice. Send the same key again and you get the SAME result back rather than a second record, which is what makes a re-run safe after a timeout you never saw the answer to. Derive it from what the write is about, not from the clock: `nightly-sync-halden` retries correctly and a timestamp does not."
                                },
                                "expectedVersion": {
                                  "type": "integer",
                                  "minimum": 0,
                                  "description": "The version you read before deciding to write. If the record has moved since, the write is refused instead of overwriting whatever changed. Send it whenever you read, reasoned, and then wrote: without it the last writer wins and neither of you finds out."
                                },
                                "sourceId": {
                                  "type": "string",
                                  "description": "The recorded source this claim came from, if one exists. It attaches evidence to the write, so a person reading the field later can see where it came from rather than only who sent it."
                                },
                                "assertionKind": {
                                  "type": "string",
                                  "enum": [
                                    "observed",
                                    "inferred",
                                    "imported",
                                    "user_supplied"
                                  ],
                                  "description": "HOW YOU KNOW. This is the field the product is built around, so say what is true rather than what is strongest: `observed` you saw it stated directly, `imported` it came from a file or another system, `inferred` you worked it out, `user_supplied` a person told you in so many words. They rank, weakest first: inferred < imported < observed < user_supplied < confirmed. A weaker claim does not overwrite a stronger one; it is reported in `held[]` and the stored value stands, so an unattended re-run converges instead of eroding what somebody checked. `confirmed` is not accepted here: it means a person checked the value, and only a signed-in person can set it."
                                },
                                "attributionLabel": {
                                  "type": "string",
                                  "minLength": 1,
                                  "maxLength": 120,
                                  "description": "A short name for the work this write belongs to, shown beside the actor so one credential can distinguish separate jobs. It is recorded as CALLER-SUPPLIED and grants nothing: it changes no permission, no idempotency scope and no quota."
                                },
                                "dryRun": {
                                  "type": "boolean",
                                  "description": "Report what this write WOULD do and commit nothing. The response carries the same change list, held fields and refusals as the real call, so it is the way to check a risky write, or a whole import, before it lands. Nothing is metered."
                                },
                                "overrideStanding": {
                                  "type": "boolean",
                                  "description": "Apply this write even when the value standing in the record was asserted more strongly than this one. Absent means no, which is the safe answer for a re-run. WITHOUT IT, a write can be accepted and change nothing: precedence is confirmed > user_supplied > observed > imported > inferred, and a weaker claim leaves the standing value in place and reports the field in `held[]` rather than failing. That is the whole of why a write can return 200 and not take. WITH it, this write wins regardless of what it is overruling, INCLUDING a value a person confirmed, so an agent that sets it by default has switched the provenance mechanism off. Set it per write, when the caller knows its claim supersedes what is there."
                                },
                                "values": {
                                  "type": "object",
                                  "additionalProperties": {}
                                },
                                "createDistinct": {
                                  "type": "boolean"
                                },
                                "objectType": {
                                  "type": "string",
                                  "minLength": 1,
                                  "maxLength": 64,
                                  "description": "What is being counted: a canonical type, or the key of a type this workspace defined."
                                },
                                "recordId": {
                                  "type": "string",
                                  "minLength": 1
                                }
                              },
                              "required": [
                                "values",
                                "objectType"
                              ],
                              "additionalProperties": false
                            }
                          },
                          "required": [
                            "operation",
                            "body"
                          ],
                          "additionalProperties": false
                        }
                      ],
                      "discriminator": {
                        "propertyName": "operation"
                      }
                    },
                    "minItems": 1,
                    "maxItems": 100
                  }
                },
                "required": [
                  "operations"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "results": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "index": {
                            "type": "integer"
                          },
                          "operation": {
                            "type": "string"
                          },
                          "ok": {
                            "type": "boolean"
                          },
                          "result": {
                            "type": "object",
                            "properties": {
                              "mutationId": {
                                "type": "string"
                              },
                              "status": {
                                "type": "string",
                                "enum": [
                                  "created",
                                  "updated",
                                  "matched",
                                  "archived",
                                  "merged",
                                  "reverted",
                                  "noop"
                                ],
                                "description": "What the write did. `noop` means it was accepted and changed nothing, because every value it carried already matched what was stored. IT IS NOT METERED: a noop does not count against your monthly change allowance, so a nightly sync that finds nothing new costs nothing. Neither does a write that only REDUCES what a workspace holds. `matched` means an upsert found an existing record on real identity evidence rather than creating a second one; `reverted` and `merged` are the undo and duplicate paths, and both are ordinary writes that count."
                              },
                              "targetId": {
                                "type": "string"
                              },
                              "record": {},
                              "changes": {
                                "type": "array",
                                "items": {
                                  "type": "object",
                                  "properties": {
                                    "field": {
                                      "type": "string",
                                      "minLength": 1,
                                      "maxLength": 128
                                    },
                                    "before": {},
                                    "after": {}
                                  },
                                  "required": [
                                    "field"
                                  ],
                                  "additionalProperties": false
                                }
                              },
                              "held": {
                                "type": "array",
                                "items": {
                                  "type": "object",
                                  "properties": {
                                    "field": {
                                      "type": "string",
                                      "minLength": 1,
                                      "maxLength": 128
                                    },
                                    "kept": {},
                                    "proposed": {},
                                    "standing": {
                                      "type": "string",
                                      "enum": [
                                        "observed",
                                        "inferred",
                                        "imported",
                                        "user_supplied",
                                        "confirmed"
                                      ]
                                    },
                                    "incoming": {
                                      "type": "string",
                                      "enum": [
                                        "observed",
                                        "inferred",
                                        "imported",
                                        "user_supplied",
                                        "confirmed"
                                      ]
                                    },
                                    "actorId": {
                                      "type": "string",
                                      "minLength": 1
                                    },
                                    "assertedAt": {
                                      "type": "string",
                                      "minLength": 1
                                    }
                                  },
                                  "required": [
                                    "field",
                                    "standing",
                                    "incoming",
                                    "actorId",
                                    "assertedAt"
                                  ],
                                  "additionalProperties": false
                                },
                                "description": "Fields this write asked to change and did not, because the value standing in the record was asserted more strongly. THIS IS WHY A WRITE CAN RETURN 200 AND CHANGE NOTHING, and a caller that ignores it will believe it wrote something it did not. Precedence is confirmed > user_supplied > observed > imported > inferred, and a write carrying no `assertionKind` is weakest of all. Each entry reports the field, what the record still says, what you proposed, which claim won, and who made it. Send `overrideStanding` to write anyway, per write, when your claim really does supersede theirs."
                              },
                              "matchedBy": {
                                "type": "string",
                                "enum": [
                                  "email",
                                  "domain",
                                  "external_id",
                                  "idempotency_key",
                                  "explicit_id"
                                ]
                              },
                              "reversible": {
                                "type": "boolean"
                              },
                              "replayed": {
                                "type": "boolean"
                              },
                              "dryRun": {
                                "type": "boolean"
                              }
                            },
                            "required": [
                              "mutationId",
                              "status",
                              "reversible"
                            ],
                            "additionalProperties": false
                          },
                          "error": {
                            "type": "object",
                            "properties": {
                              "code": {
                                "type": "string",
                                "enum": [
                                  "unauthorized",
                                  "forbidden_scope",
                                  "standing_override_refused",
                                  "workspace_not_found",
                                  "validation_error",
                                  "record_not_found",
                                  "ambiguous_identity",
                                  "duplicate_identity",
                                  "stale_version",
                                  "invalid_stage_transition",
                                  "idempotency_conflict",
                                  "not_reversible",
                                  "merge_conflict",
                                  "rate_limited",
                                  "quota_exceeded",
                                  "payload_too_large",
                                  "workspace_capacity",
                                  "payment_required",
                                  "billing_state_stale",
                                  "operation_in_flight",
                                  "internal_error"
                                ]
                              },
                              "message": {
                                "type": "string"
                              },
                              "recoveryHint": {
                                "type": "string"
                              },
                              "detail": {
                                "type": "object",
                                "additionalProperties": {}
                              }
                            },
                            "required": [
                              "code",
                              "message",
                              "recoveryHint",
                              "detail"
                            ],
                            "additionalProperties": true
                          }
                        },
                        "required": [
                          "index",
                          "operation",
                          "ok"
                        ],
                        "additionalProperties": true
                      }
                    },
                    "succeeded": {
                      "type": "integer"
                    },
                    "failed": {
                      "type": "integer"
                    },
                    "requestId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "results",
                    "succeeded",
                    "failed",
                    "requestId"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "A product quota is spent, or the subscription is not active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A conflict the caller can resolve: a stale expectedVersion, an idempotency key reused for different input, an ambiguous or duplicate identity, or a merge that no longer applies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The body, or a single record inside it, exceeds its bound.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "507": {
            "description": "The workspace is at its storage ceiling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/billing/usage": {
      "get": {
        "summary": "Plan, subscription status, and usage against every quota",
        "description": "Plan, subscription state, and usage against every quota, served from the control plane rather than the workspace. That separation is deliberate: billing state has to be readable when a workspace is at its storage ceiling, and checking whether you are over budget must not consume the budget.",
        "tags": [
          "billing"
        ],
        "operationId": "get_billing_usage",
        "x-indraft-capability": "crm:read",
        "x-indraft-scopes": [
          "crm:read",
          "crm:write",
          "crm:configure",
          "crm:admin",
          "crm:revert",
          "data:export"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "plan": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string"
                    },
                    "metrics": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "metric": {
                            "type": "string"
                          },
                          "used": {
                            "type": "integer"
                          },
                          "limit": {
                            "type": "integer"
                          }
                        },
                        "required": [
                          "metric",
                          "used",
                          "limit"
                        ],
                        "additionalProperties": true
                      }
                    },
                    "activity": {
                      "type": "object",
                      "properties": {
                        "interactions": {
                          "type": "integer"
                        },
                        "tasks": {
                          "type": "integer"
                        }
                      },
                      "required": [
                        "interactions",
                        "tasks"
                      ],
                      "additionalProperties": true
                    },
                    "capacity": {
                      "type": "object",
                      "properties": {
                        "bytes": {
                          "type": "integer"
                        },
                        "ceilingBytes": {
                          "type": "integer"
                        },
                        "fractionUsed": {
                          "type": "integer"
                        },
                        "warning": {
                          "type": "string",
                          "enum": [
                            "none",
                            "approaching",
                            "critical"
                          ]
                        },
                        "operatorAlert": {
                          "type": "boolean"
                        },
                        "projection": {
                          "type": "object",
                          "properties": {
                            "observedDays": {
                              "type": "integer"
                            },
                            "bytesPerDay": {
                              "type": "integer"
                            },
                            "monthsToCeiling": {
                              "type": "integer"
                            },
                            "reachesCeilingAt": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "observedDays",
                            "bytesPerDay",
                            "monthsToCeiling",
                            "reachesCeilingAt"
                          ],
                          "additionalProperties": true
                        },
                        "indexedRecords": {
                          "type": "integer"
                        }
                      },
                      "required": [
                        "bytes",
                        "ceilingBytes",
                        "fractionUsed",
                        "warning",
                        "operatorAlert",
                        "projection"
                      ],
                      "additionalProperties": true
                    },
                    "overage": {
                      "type": "object",
                      "properties": {
                        "pooled": {
                          "type": "object",
                          "properties": {
                            "records": {
                              "type": "integer"
                            },
                            "changes": {
                              "type": "integer"
                            }
                          },
                          "required": [
                            "records",
                            "changes"
                          ],
                          "additionalProperties": true
                        },
                        "lines": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "metric": {
                                "type": "string",
                                "enum": [
                                  "records",
                                  "changes"
                                ]
                              },
                              "over": {
                                "type": "integer"
                              },
                              "blocks": {
                                "type": "integer"
                              },
                              "blockSize": {
                                "type": "integer"
                              },
                              "perBlockMinor": {
                                "type": "integer"
                              },
                              "amountMinor": {
                                "type": "integer"
                              }
                            },
                            "required": [
                              "metric",
                              "over",
                              "blocks",
                              "blockSize",
                              "perBlockMinor",
                              "amountMinor"
                            ],
                            "additionalProperties": true
                          }
                        },
                        "seatsMinor": {
                          "type": "integer"
                        },
                        "totalMinor": {
                          "type": "integer"
                        },
                        "cappedTo": {
                          "type": "string"
                        },
                        "savedMinor": {
                          "type": "integer"
                        }
                      },
                      "required": [
                        "pooled",
                        "lines",
                        "seatsMinor",
                        "totalMinor",
                        "cappedTo",
                        "savedMinor"
                      ],
                      "additionalProperties": true
                    }
                  },
                  "required": [
                    "plan",
                    "status",
                    "metrics"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/billing/checkout": {
      "post": {
        "summary": "Start a Stripe Checkout session for a plan",
        "description": "Starts a Stripe Checkout session and returns the URL to send the customer to. No card details reach Indraft at any point, and no CRM record reaches Stripe.",
        "tags": [
          "billing"
        ],
        "operationId": "post_billing_checkout",
        "x-indraft-capability": "billing:manage",
        "x-indraft-scopes": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "plan": {
                    "type": "string",
                    "enum": [
                      "solo",
                      "team",
                      "scale",
                      "business"
                    ]
                  },
                  "interval": {
                    "type": "string",
                    "enum": [
                      "month",
                      "year"
                    ]
                  }
                },
                "required": [
                  "plan"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "url": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "url"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "A product quota is spent, or the subscription is not active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A conflict the caller can resolve: a stale expectedVersion, an idempotency key reused for different input, an ambiguous or duplicate identity, or a merge that no longer applies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The body, or a single record inside it, exceeds its bound.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "507": {
            "description": "The workspace is at its storage ceiling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/billing/portal": {
      "post": {
        "summary": "Open the Stripe Customer Portal",
        "description": "Opens the Stripe Customer Portal, where a customer changes their card, reads invoices, or cancels. Cancelling there is the whole path: there is no retention flow to get through.",
        "tags": [
          "billing"
        ],
        "operationId": "post_billing_portal",
        "x-indraft-capability": "billing:manage",
        "x-indraft-scopes": [],
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "url": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "url"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "A product quota is spent, or the subscription is not active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A conflict the caller can resolve: a stale expectedVersion, an idempotency key reused for different input, an ambiguous or duplicate identity, or a merge that no longer applies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "507": {
            "description": "The workspace is at its storage ceiling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/mcp/connections": {
      "get": {
        "summary": "List agent connections and their state",
        "description": "Every agent connection, who authorized it, the scopes it holds and when it was last used, so the question of who has access and whether they are using it is answerable at any time.",
        "tags": [
          "connections"
        ],
        "operationId": "get_mcp_connections",
        "x-indraft-capability": "crm:read",
        "x-indraft-scopes": [
          "crm:read",
          "crm:write",
          "crm:configure",
          "crm:admin",
          "crm:revert",
          "data:export"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "connections": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "workspaceId": {
                            "type": "string"
                          },
                          "workosUserId": {
                            "type": "string"
                          },
                          "clientId": {
                            "type": "string"
                          },
                          "scopes": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "revokedAt": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "workspaceId",
                          "workosUserId",
                          "clientId",
                          "scopes",
                          "revokedAt"
                        ],
                        "additionalProperties": true
                      }
                    }
                  },
                  "required": [
                    "connections"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/mcp/connections/{id}": {
      "delete": {
        "summary": "Revoke one agent connection, effective immediately",
        "description": "Revokes one connection, effective on that connection's very next request. Not at the end of a session and not on a cache expiry.",
        "tags": [
          "connections"
        ],
        "operationId": "delete_mcp_connections__id_",
        "x-indraft-capability": "members:manage",
        "x-indraft-scopes": [],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The connection id, as returned by the call that created or matched it.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "revoked": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "revoked"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "A product quota is spent, or the subscription is not active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such record, or it belongs to another workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A conflict the caller can resolve: a stale expectedVersion, an idempotency key reused for different input, an ambiguous or duplicate identity, or a merge that no longer applies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "507": {
            "description": "The workspace is at its storage ceiling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/tokens": {
      "get": {
        "summary": "List API tokens and their state, never their secrets",
        "description": "Every token, its label, the scopes it asked for, who created it and when it was last used. Secrets are stored as hashes and are never returned, here or anywhere.",
        "tags": [
          "admin"
        ],
        "operationId": "get_v1_tokens",
        "x-indraft-capability": "credentials:manage",
        "x-indraft-scopes": [],
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tokens": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "prefix": {
                            "type": "string"
                          },
                          "scopes": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "label": {
                            "type": "string"
                          },
                          "lastUsedAt": {
                            "type": "string"
                          },
                          "revokedAt": {
                            "type": "string"
                          },
                          "createdAt": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "prefix",
                          "scopes",
                          "label",
                          "lastUsedAt",
                          "revokedAt",
                          "createdAt"
                        ],
                        "additionalProperties": true
                      }
                    }
                  },
                  "required": [
                    "tokens"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Create an API token, returning its secret exactly once",
        "description": "The secret is in this response and nowhere else. Naming a scope is a request rather than a grant: a token holds the intersection of its scopes and the live role of the member who created it, read at request time, so demoting that person weakens every token they made in the same moment.",
        "tags": [
          "admin"
        ],
        "operationId": "post_v1_tokens",
        "x-indraft-capability": "credentials:manage",
        "x-indraft-scopes": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "label": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120
                  },
                  "scopes": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "crm:read",
                        "crm:write",
                        "crm:configure",
                        "crm:admin",
                        "data:export",
                        "workspaces:provision",
                        "crm:revert"
                      ]
                    },
                    "minItems": 1,
                    "maxItems": 7
                  }
                },
                "required": [
                  "label",
                  "scopes"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "prefix": {
                      "type": "string"
                    },
                    "token": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "prefix",
                    "token"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "A product quota is spent, or the subscription is not active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A conflict the caller can resolve: a stale expectedVersion, an idempotency key reused for different input, an ambiguous or duplicate identity, or a merge that no longer applies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The body, or a single record inside it, exceeds its bound.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request does not satisfy the schema on this page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "507": {
            "description": "The workspace is at its storage ceiling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/tokens/{id}": {
      "delete": {
        "summary": "Revoke one API token, effective on its next request",
        "description": "Revokes one token, effective on its next request. The token's history stays, because who did what does not stop being true when a credential is retired.",
        "tags": [
          "admin"
        ],
        "operationId": "delete_v1_tokens__id_",
        "x-indraft-capability": "credentials:manage",
        "x-indraft-scopes": [],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The token id, as returned by the call that created or matched it.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "revoked": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "revoked"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "No credential, or one that has been revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "A product quota is spent, or the subscription is not active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Authenticated, and this capability is not held.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such record, or it belongs to another workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A conflict the caller can resolve: a stale expectedVersion, an idempotency key reused for different input, an ambiguous or duplicate identity, or a merge that no longer applies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Infrastructure protection tripped. This is not a product quota.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "ratelimit-limit": {
                "description": "Requests permitted in the window closest to refusing this caller.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-remaining": {
                "description": "Requests left in that window. Zero means the next request is refused.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-reset": {
                "description": "Seconds until that window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "ratelimit-policy": {
                "description": "Every window in force, not only the one reported above.",
                "schema": {
                  "type": "string"
                }
              },
              "retry-after": {
                "description": "Seconds to wait before retrying. The request itself was fine.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "A defect on our side. The hint says so, and carries an incident id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "507": {
            "description": "The workspace is at its storage ceiling.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "webhooks": {
    "mutation": {
      "post": {
        "summary": "Something changed in a workspace you subscribed to",
        "description": "Delivered at least once, so deduplicate on the payload's `id`, which is the mutation id and is stable across retries. Verify `x-indraft-signature` before trusting the body: it is `t=<unix seconds>,v1=<hex>` where the hex is an HMAC-SHA256 of `<t>.<raw body>` under your endpoint's signing secret, which is shown once when the endpoint is registered. The timestamp is inside the signed material, so a captured delivery cannot be replayed later with a fresh one. Compare in constant time, and reject a timestamp far from your own clock. Respond 2xx to acknowledge; anything else is retried with backoff.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "operation": {
                    "type": "string",
                    "enum": [
                      "advance_opportunity",
                      "configure_watch",
                      "advance_custom_record",
                      "archive",
                      "restore",
                      "archive_custom_record",
                      "cancel_task",
                      "update_task",
                      "complete_task",
                      "configure_custom_field",
                      "configure_exchange_rate",
                      "configure_object_type",
                      "configure_pipeline",
                      "configure_workspace",
                      "set_standing_override_policy",
                      "confirm",
                      "create_opportunity",
                      "create_task",
                      "erase_subject",
                      "link_contact_company",
                      "merge_companies",
                      "merge_contacts",
                      "merge_object_records",
                      "record_interaction",
                      "revert_change",
                      "unmerge",
                      "update_opportunity",
                      "upsert_company",
                      "upsert_contact",
                      "upsert_custom_record"
                    ]
                  },
                  "outcome": {
                    "type": "string",
                    "enum": [
                      "created",
                      "updated",
                      "matched",
                      "archived",
                      "merged",
                      "reverted",
                      "noop"
                    ],
                    "description": "What the write did. `noop` means it was accepted and changed nothing, because every value it carried already matched what was stored. IT IS NOT METERED: a noop does not count against your monthly change allowance, so a nightly sync that finds nothing new costs nothing. Neither does a write that only REDUCES what a workspace holds. `matched` means an upsert found an existing record on real identity evidence rather than creating a second one; `reverted` and `merged` are the undo and duplicate paths, and both are ordinary writes that count."
                  },
                  "targetType": {
                    "type": "string"
                  },
                  "targetId": {
                    "type": "string"
                  },
                  "actorId": {
                    "type": "string"
                  },
                  "accessPath": {
                    "type": "string",
                    "enum": [
                      "rest",
                      "mcp",
                      "app",
                      "system"
                    ]
                  },
                  "attributionLabel": {
                    "type": "string"
                  },
                  "assertionKind": {
                    "type": "string",
                    "enum": [
                      "observed",
                      "inferred",
                      "imported",
                      "user_supplied"
                    ]
                  },
                  "occurredAt": {
                    "type": "string"
                  },
                  "changes": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "objectType": {
                          "type": "string"
                        },
                        "objectId": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "before": {},
                        "after": {}
                      },
                      "required": [
                        "objectType",
                        "objectId",
                        "field"
                      ],
                      "additionalProperties": true
                    }
                  }
                },
                "required": [
                  "id",
                  "operation",
                  "outcome",
                  "targetType",
                  "targetId",
                  "actorId",
                  "accessPath",
                  "attributionLabel",
                  "assertionKind",
                  "occurredAt",
                  "changes"
                ],
                "additionalProperties": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Acknowledged. Anything outside 2xx is retried."
          }
        }
      }
    }
  }
}
