{ "openapi": "3.1.0", "info": { "title": "Latitude API", "version": "1.0.0", "description": "The Latitude public API. Authenticate using an API key via the `Authorization: Bearer` header." }, "servers": [ { "url": "https://api.latitude.so", "description": "Production" } ], "components": { "securitySchemes": { "ApiKeyAuth": { "type": "http", "scheme": "bearer", "description": "Organization-scoped API key" } }, "schemas": { "HealthResponse": { "type": "object", "properties": { "service": { "type": "string", "enum": [ "api" ] }, "status": { "type": "string", "enum": [ "ok" ] } }, "required": [ "service", "status" ] }, "OAuthProtectedResourceMetadata": { "type": "object", "properties": { "resource": { "type": "string" }, "authorization_servers": { "type": "array", "items": { "type": "string" } } }, "required": [ "resource", "authorization_servers" ] }, "Project": { "type": "object", "properties": { "id": { "type": "string", "description": "Stable project identifier (CUID2)." }, "organizationId": { "type": "string", "description": "Organization that owns this project." }, "name": { "type": "string", "description": "Human-readable name." }, "slug": { "type": "string", "description": "URL-safe slug derived from `name`. Regenerated when the name changes in a way that affects the slug form." }, "settings": { "$ref": "#/components/schemas/ProjectSettings" }, "firstTraceAt": { "type": [ "string", "null" ], "description": "ISO-8601 timestamp of the first ingested trace. `null` until the first trace lands." }, "deletedAt": { "type": [ "string", "null" ], "description": "ISO-8601 timestamp at which the project was deleted. `null` while the project is active." }, "lastEditedAt": { "type": "string", "description": "ISO-8601 timestamp of the most recent name/settings edit." }, "createdAt": { "type": "string", "description": "ISO-8601 timestamp of creation." }, "updatedAt": { "type": "string", "description": "ISO-8601 timestamp of the last metadata change." } }, "required": [ "id", "organizationId", "name", "slug", "settings", "firstTraceAt", "deletedAt", "lastEditedAt", "createdAt", "updatedAt" ] }, "ProjectSettings": { "type": [ "object", "null" ], "properties": { "keepMonitoring": { "type": "boolean", "description": "When `true`, the evaluation linked to an issue keeps running after the issue is resolved. When `false`, resolving the issue stops the evaluation. Defaults to `true` when omitted." }, "alertNotifications": { "$ref": "#/components/schemas/AlertNotificationsSetting" } }, "description": "Per-project settings overrides. `null` means inherit from the organization." }, "AlertNotificationsSetting": { "type": "object", "properties": { "issue.new": { "type": "boolean", "description": "Send a notification when a new issue is discovered. Defaults to `true` when omitted." }, "issue.regressed": { "type": "boolean", "description": "Send a notification when a previously-resolved issue regresses. Defaults to `true` when omitted." }, "issue.escalating": { "type": "boolean", "description": "Send a notification when an active issue is escalating in volume or severity. Defaults to `true` when omitted." }, "escalationSensitivity": { "type": "integer", "minimum": 1, "maximum": 6, "description": "Sensitivity of the escalation detector, 1 (most sensitive, more notifications) to 6 (least sensitive, fewer notifications). Defaults to a balanced value when omitted." } }, "description": "Per-alert-kind in-app notification toggles plus escalation-detector tuning. Omit to keep current values." }, "Error": { "type": "object", "properties": { "error": { "type": "string" } }, "required": [ "error" ] }, "CreateProjectBody": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1, "description": "Human-readable name for the project. Must be unique within the organization." } }, "required": [ "name" ] }, "PaginatedProjects": { "type": "object", "properties": { "items": { "type": "array", "items": { "$ref": "#/components/schemas/Project" }, "description": "Page of items, in the requested sort order." }, "nextCursor": { "type": [ "string", "null" ], "description": "Opaque cursor for fetching the next page. `null` when there are no more pages. Pass it back in `cursor` to continue." }, "hasMore": { "type": "boolean", "description": "`true` when there is at least one more page after this one." } }, "required": [ "items", "nextCursor", "hasMore" ] }, "UpdateProjectBody": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1, "description": "New human-readable name. Triggers slug regeneration when the change affects the slug form (cosmetic edits like capitalization keep the URL stable)." }, "settings": { "allOf": [ { "$ref": "#/components/schemas/ProjectSettings" }, { "description": "Replace the project's settings overrides. Omit to leave settings untouched. To clear overrides entirely, edit via the web UI." } ] }, "flaggers": { "type": "object", "properties": { "frustration": { "type": "boolean" }, "nsfw": { "type": "boolean" }, "refusal": { "type": "boolean" }, "laziness": { "type": "boolean" }, "jailbreaking": { "type": "boolean" }, "forgetting": { "type": "boolean" }, "trashing": { "type": "boolean" }, "tool-call-errors": { "type": "boolean" }, "output-schema-validation": { "type": "boolean" }, "empty-response": { "type": "boolean" } }, "description": "Enable or disable specific flaggers for the project. Keys are flagger slugs; values are the new `enabled` state. Omitted slugs are left untouched." } } }, "ScoreResponse": { "anyOf": [ { "$ref": "#/components/schemas/CustomScoreResponse" }, { "$ref": "#/components/schemas/EvaluationScoreResponse" } ] }, "CustomScoreResponse": { "type": "object", "properties": { "id": { "type": "string", "minLength": 24, "maxLength": 24, "description": "Stable score identifier." }, "organizationId": { "type": "string", "minLength": 24, "maxLength": 24, "description": "Organization that owns this score." }, "projectId": { "type": "string", "minLength": 24, "maxLength": 24, "description": "Project this score lives in." }, "sessionId": { "type": [ "string", "null" ], "maxLength": 128, "description": "Session id lifted from the trace, when set. `null` when the trace has no session." }, "traceId": { "type": [ "string", "null" ], "minLength": 32, "maxLength": 32, "description": "Identifier of the scored trace." }, "spanId": { "type": [ "string", "null" ], "minLength": 16, "maxLength": 16, "description": "Span the score pins to. Defaults to the trace's last LLM-completion span." }, "simulationId": { "type": [ "string", "null" ], "minLength": 24, "maxLength": 24, "description": "Simulation reference, if any." }, "issueId": { "type": [ "string", "null" ], "minLength": 24, "maxLength": 24, "description": "Issue this score contributes to, if any." }, "value": { "type": "number", "minimum": 0, "maximum": 1, "description": "Normalized score value in [0, 1]." }, "passed": { "type": "boolean", "description": "Whether the score marks the output as passing." }, "feedback": { "type": "string", "description": "Free-text feedback explaining the score." }, "error": { "type": [ "string", "null" ], "minLength": 1, "description": "Generation error text, when score generation itself errored. `null` for successful scores." }, "errored": { "type": "boolean", "description": "`true` when the score could not be generated successfully." }, "duration": { "type": "integer", "minimum": 0, "description": "Score generation duration in nanoseconds." }, "tokens": { "type": "integer", "minimum": 0, "description": "LLM tokens consumed generating the score." }, "cost": { "type": "integer", "minimum": 0, "description": "Score cost in microcents (1/1,000,000 of a USD)." }, "draftedAt": { "type": [ "string", "null" ], "format": "date-time", "description": "ISO-8601 timestamp while the score is awaiting human confirmation. `null` for published / system scores." }, "annotatorId": { "type": [ "string", "null" ], "minLength": 24, "maxLength": 24, "description": "User who authored the score, if any." }, "createdAt": { "type": "string", "format": "date-time", "description": "ISO-8601 timestamp at which the score was created." }, "updatedAt": { "type": "string", "format": "date-time", "description": "ISO-8601 timestamp of the last metadata update." }, "source": { "type": "string", "enum": [ "custom" ], "description": "Discriminator. `\"custom\"` denotes a user-supplied score." }, "sourceId": { "type": "string", "minLength": 1, "maxLength": 128, "description": "User-supplied tag identifying the score's origin (echoed from the request)." }, "metadata": { "type": "object", "additionalProperties": {}, "description": "Arbitrary user-supplied metadata persisted alongside the score." } }, "required": [ "id", "organizationId", "projectId", "sessionId", "traceId", "spanId", "simulationId", "issueId", "value", "passed", "feedback", "error", "errored", "duration", "tokens", "cost", "draftedAt", "annotatorId", "createdAt", "updatedAt", "source", "sourceId", "metadata" ] }, "EvaluationScoreResponse": { "type": "object", "properties": { "id": { "type": "string", "minLength": 24, "maxLength": 24, "description": "Stable score identifier." }, "organizationId": { "type": "string", "minLength": 24, "maxLength": 24, "description": "Organization that owns this score." }, "projectId": { "type": "string", "minLength": 24, "maxLength": 24, "description": "Project this score lives in." }, "sessionId": { "type": [ "string", "null" ], "maxLength": 128, "description": "Session id lifted from the trace, when set. `null` when the trace has no session." }, "traceId": { "type": [ "string", "null" ], "minLength": 32, "maxLength": 32, "description": "Identifier of the scored trace." }, "spanId": { "type": [ "string", "null" ], "minLength": 16, "maxLength": 16, "description": "Span the score pins to. Defaults to the trace's last LLM-completion span." }, "simulationId": { "type": [ "string", "null" ], "minLength": 24, "maxLength": 24, "description": "Simulation reference, if any." }, "issueId": { "type": [ "string", "null" ], "minLength": 24, "maxLength": 24, "description": "Issue this score contributes to, if any." }, "value": { "type": "number", "minimum": 0, "maximum": 1, "description": "Normalized score value in [0, 1]." }, "passed": { "type": "boolean", "description": "Whether the score marks the output as passing." }, "feedback": { "type": "string", "description": "Free-text feedback explaining the score." }, "error": { "type": [ "string", "null" ], "minLength": 1, "description": "Generation error text, when score generation itself errored. `null` for successful scores." }, "errored": { "type": "boolean", "description": "`true` when the score could not be generated successfully." }, "duration": { "type": "integer", "minimum": 0, "description": "Score generation duration in nanoseconds." }, "tokens": { "type": "integer", "minimum": 0, "description": "LLM tokens consumed generating the score." }, "cost": { "type": "integer", "minimum": 0, "description": "Score cost in microcents (1/1,000,000 of a USD)." }, "draftedAt": { "type": [ "string", "null" ], "format": "date-time", "description": "ISO-8601 timestamp while the score is awaiting human confirmation. `null` for published / system scores." }, "annotatorId": { "type": [ "string", "null" ], "minLength": 24, "maxLength": 24, "description": "User who authored the score, if any." }, "createdAt": { "type": "string", "format": "date-time", "description": "ISO-8601 timestamp at which the score was created." }, "updatedAt": { "type": "string", "format": "date-time", "description": "ISO-8601 timestamp of the last metadata update." }, "source": { "type": "string", "enum": [ "evaluation" ], "description": "Discriminator. `\"evaluation\"` denotes a platform-generated evaluation score." }, "sourceId": { "type": "string", "minLength": 24, "maxLength": 24, "description": "CUID of the evaluation that produced this score." }, "metadata": { "$ref": "#/components/schemas/EvaluationScoreMetadata" } }, "required": [ "id", "organizationId", "projectId", "sessionId", "traceId", "spanId", "simulationId", "issueId", "value", "passed", "feedback", "error", "errored", "duration", "tokens", "cost", "draftedAt", "annotatorId", "createdAt", "updatedAt", "source", "sourceId", "metadata" ] }, "EvaluationScoreMetadata": { "type": "object", "properties": { "evaluationHash": { "type": "string", "description": "Hash of the evaluation script that produced this score; lets the platform track which version generated it." } }, "required": [ "evaluationHash" ], "description": "Evaluation-specific metadata." }, "CreateScoreBody": { "anyOf": [ { "$ref": "#/components/schemas/CreateCustomScoreBody" }, { "$ref": "#/components/schemas/CreateEvaluationScoreBody" } ] }, "CreateCustomScoreBody": { "type": "object", "properties": { "simulationId": { "type": [ "string", "null" ], "minLength": 24, "maxLength": 24, "default": null, "description": "Simulation this score is tied to, if any. `null` (default) when not part of a simulation." }, "value": { "type": "number", "minimum": 0, "maximum": 1, "description": "Normalized score value in [0, 1]. Higher = better." }, "passed": { "type": "boolean", "description": "Whether the scored output passes the evaluator's bar." }, "feedback": { "type": "string", "description": "Free-text feedback explaining the score." }, "error": { "type": [ "string", "null" ], "minLength": 1, "default": null, "description": "Generation error text, when score generation itself failed. `null` (default) for successful scores." }, "duration": { "type": "integer", "minimum": 0, "default": 0, "description": "Score generation duration in nanoseconds. `0` for externally-computed scores." }, "tokens": { "type": "integer", "minimum": 0, "default": 0, "description": "LLM tokens consumed generating the score, if any. `0` for externally-computed scores." }, "cost": { "type": "integer", "minimum": 0, "default": 0, "description": "Score cost in microcents (1/1,000,000 of a USD). `0` for externally-computed scores." }, "trace": { "$ref": "#/components/schemas/TraceRef" }, "sourceId": { "type": "string", "minLength": 1, "maxLength": 128, "description": "User-supplied tag identifying the score's origin (e.g. `\"prod-pipeline\"`, `\"qa-script-v2\"`)." }, "metadata": { "type": "object", "additionalProperties": {}, "default": {}, "description": "Arbitrary user-supplied metadata persisted alongside the score." }, "_evaluation": { "type": "boolean", "enum": [ false ], "default": false, "description": "Discriminator: omit (or `false`) for custom scores. Required `true` for evaluation scores." } }, "required": [ "value", "passed", "feedback", "trace", "sourceId" ] }, "TraceRef": { "oneOf": [ { "type": "object", "properties": { "by": { "type": "string", "enum": [ "id" ], "description": "Match a single trace by its identifier. Pair with `id`." }, "id": { "type": "string", "minLength": 32, "maxLength": 32, "description": "32-character trace identifier." } }, "required": [ "by", "id" ] }, { "type": "object", "properties": { "by": { "type": "string", "enum": [ "filters" ], "description": "Match a single trace by a filter set. Pair with `filters`; exactly one trace must match." }, "filters": { "$ref": "#/components/schemas/FilterSet" } }, "required": [ "by", "filters" ] } ], "description": "Target trace. Either an explicit id or a filter set matching exactly one trace." }, "FilterSet": { "type": "object", "additionalProperties": { "type": "array", "items": { "$ref": "#/components/schemas/FilterCondition" } }, "description": "Filter set keyed by field name. Each entry holds an array of conditions ANDed together for that field; field-level groups are also ANDed across the set." }, "FilterCondition": { "type": "object", "properties": { "op": { "type": "string", "enum": [ "eq", "neq", "gt", "gte", "lt", "lte", "in", "notIn", "contains", "notContains", "gtePercentile" ], "description": "Comparison operator applied to the field's value (e.g. `eq`, `neq`, `in`). The full operator list lives in the API reference." }, "value": { "anyOf": [ { "type": "string" }, { "type": "number" }, { "type": "boolean" }, { "type": "array", "items": { "anyOf": [ { "type": "string" }, { "type": "number" } ] } } ], "description": "Right-hand value compared against the field. Arrays are required for `in` / `notIn`-style operators." } }, "required": [ "op", "value" ] }, "CreateEvaluationScoreBody": { "type": "object", "properties": { "simulationId": { "type": [ "string", "null" ], "minLength": 24, "maxLength": 24, "default": null, "description": "Simulation this score is tied to, if any. `null` (default) when not part of a simulation." }, "value": { "type": "number", "minimum": 0, "maximum": 1, "description": "Normalized score value in [0, 1]. Higher = better." }, "passed": { "type": "boolean", "description": "Whether the scored output passes the evaluator's bar." }, "feedback": { "type": "string", "description": "Free-text feedback explaining the score." }, "error": { "type": [ "string", "null" ], "minLength": 1, "default": null, "description": "Generation error text, when score generation itself failed. `null` (default) for successful scores." }, "duration": { "type": "integer", "minimum": 0, "default": 0, "description": "Score generation duration in nanoseconds. `0` for externally-computed scores." }, "tokens": { "type": "integer", "minimum": 0, "default": 0, "description": "LLM tokens consumed generating the score, if any. `0` for externally-computed scores." }, "cost": { "type": "integer", "minimum": 0, "default": 0, "description": "Score cost in microcents (1/1,000,000 of a USD). `0` for externally-computed scores." }, "trace": { "$ref": "#/components/schemas/TraceRef" }, "_evaluation": { "type": "boolean", "enum": [ true ], "description": "Discriminator: `true` flags the body as an evaluation score (internal); `false`/omit for custom." }, "sourceId": { "type": "string", "minLength": 24, "maxLength": 24, "description": "CUID of the evaluation that produced this score." }, "metadata": { "$ref": "#/components/schemas/EvaluationScoreMetadata" } }, "required": [ "value", "passed", "feedback", "trace", "_evaluation", "sourceId", "metadata" ], "description": "Internal, don't use" }, "AnnotationScoreResponse": { "type": "object", "properties": { "id": { "type": "string", "minLength": 24, "maxLength": 24, "description": "Stable annotation-score identifier." }, "organizationId": { "type": "string", "minLength": 24, "maxLength": 24, "description": "Organization that owns this annotation." }, "projectId": { "type": "string", "minLength": 24, "maxLength": 24, "description": "Project this annotation lives in." }, "sessionId": { "type": [ "string", "null" ], "maxLength": 128, "description": "Session id lifted from the trace, when set. `null` when the trace has no session." }, "traceId": { "type": [ "string", "null" ], "minLength": 32, "maxLength": 32, "description": "Identifier of the annotated trace." }, "spanId": { "type": [ "string", "null" ], "minLength": 16, "maxLength": 16, "description": "Span the annotation pins to. Defaults to the trace's last LLM-completion span." }, "simulationId": { "type": [ "string", "null" ], "minLength": 24, "maxLength": 24, "description": "Simulation reference, if any." }, "issueId": { "type": [ "string", "null" ], "minLength": 24, "maxLength": 24, "description": "Issue this annotation contributes to, if any." }, "value": { "type": "number", "minimum": 0, "maximum": 1, "description": "Normalized score value in [0, 1]." }, "passed": { "type": "boolean", "description": "Whether the annotation marks the output as passing." }, "feedback": { "type": "string", "description": "Free-text feedback explaining the score." }, "error": { "type": [ "string", "null" ], "minLength": 1, "description": "Generation error text, when the annotation itself errored. `null` for successful annotations." }, "errored": { "type": "boolean", "description": "`true` when the annotation could not be generated successfully." }, "duration": { "type": "integer", "minimum": 0, "description": "Generation duration in nanoseconds. `0` for human annotations." }, "tokens": { "type": "integer", "minimum": 0, "description": "Total LLM tokens consumed generating the score, if any. `0` for human annotations." }, "cost": { "type": "integer", "minimum": 0, "description": "Total LLM cost in microcents (1/1,000,000 of a USD). `0` for human annotations." }, "draftedAt": { "type": [ "string", "null" ], "format": "date-time", "description": "Always `null` for public-API annotations — they're written as published." }, "annotatorId": { "type": [ "string", "null" ], "minLength": 24, "maxLength": 24, "description": "User who authored the annotation. `null` for API-key callers (organization-scoped); set to the authenticated user for OAuth callers." }, "createdAt": { "type": "string", "format": "date-time", "description": "ISO-8601 timestamp at which the annotation was created." }, "updatedAt": { "type": "string", "format": "date-time", "description": "ISO-8601 timestamp of the last metadata update." }, "source": { "type": "string", "enum": [ "annotation" ], "description": "Always `\"annotation\"` for this endpoint's responses." }, "sourceId": { "anyOf": [ { "type": "string", "enum": [ "UI", "API", "SYSTEM" ] }, { "type": "string", "minLength": 24, "maxLength": 24 } ], "description": "Origin marker. Sentinel `\"UI\"` / `\"API\"` / `\"SYSTEM\"` for drafts and automation, or an annotation-queue CUID for queue-authored rows. Public-API annotations are always `\"API\"`." }, "metadata": { "$ref": "#/components/schemas/AnnotationScoreMetadata" } }, "required": [ "id", "organizationId", "projectId", "sessionId", "traceId", "spanId", "simulationId", "issueId", "value", "passed", "feedback", "error", "errored", "duration", "tokens", "cost", "draftedAt", "annotatorId", "createdAt", "updatedAt", "source", "sourceId", "metadata" ] }, "AnnotationScoreMetadata": { "type": "object", "properties": { "rawFeedback": { "type": "string", "description": "Original feedback text before enrichment. Human-authored for human annotations, model-authored for system drafts." }, "messageIndex": { "type": "integer", "minimum": 0, "description": "0-based message index inside the conversation. Omit for conversation-level annotations." }, "partIndex": { "type": "integer", "minimum": 0, "description": "0-based index into the target message's `parts[]`. Requires `messageIndex`." }, "startOffset": { "type": "integer", "minimum": 0, "description": "Inclusive start offset for substring annotations. Must be paired with `endOffset` and `partIndex`." }, "endOffset": { "type": "integer", "minimum": 0, "description": "Exclusive end offset for substring annotations. Must be paired with `startOffset` and `partIndex`, and `>= startOffset`." }, "textFormat": { "type": "string", "enum": [ "pretty-json" ], "description": "UI-side text transform applied before the offsets were captured (e.g. `\"pretty-json\"`). Resolvers must apply the same transform before slicing." } }, "required": [ "rawFeedback" ], "description": "Annotation-specific metadata: `rawFeedback` plus a snapshot of the anchor at write time." }, "CreateAnnotationBody": { "type": "object", "properties": { "simulationId": { "type": [ "string", "null" ], "minLength": 24, "maxLength": 24, "default": null, "description": "Simulation this annotation is tied to, if any. `null` (default) when not part of a simulation." }, "issueId": { "type": [ "string", "null" ], "minLength": 24, "maxLength": 24, "default": null, "description": "Pre-selected issue this annotation belongs to. Leave `null` (default) to let the automatic issue-discovery pipeline route the annotation." }, "value": { "type": "number", "minimum": 0, "maximum": 1, "description": "Normalized score value in [0, 1]. Higher = better." }, "passed": { "type": "boolean", "description": "Whether the annotated output passes the reviewer's bar." }, "feedback": { "type": "string", "minLength": 1, "description": "Free-text feedback explaining the score. Surfaced alongside the trace." }, "anchor": { "$ref": "#/components/schemas/AnnotationAnchor" }, "trace": { "$ref": "#/components/schemas/TraceRef" } }, "required": [ "value", "passed", "feedback", "trace" ] }, "AnnotationAnchor": { "type": "object", "properties": { "messageIndex": { "type": "integer", "minimum": 0, "description": "0-based message index inside the conversation. Omit for conversation-level annotations." }, "partIndex": { "type": "integer", "minimum": 0, "description": "0-based index into the target message's `parts[]`. Requires `messageIndex`." }, "startOffset": { "type": "integer", "minimum": 0, "description": "Inclusive start offset for substring annotations. Must be paired with `endOffset` and `partIndex`." }, "endOffset": { "type": "integer", "minimum": 0, "description": "Exclusive end offset for substring annotations. Must be paired with `startOffset` and `partIndex`, and `>= startOffset`." }, "textFormat": { "type": "string", "enum": [ "pretty-json" ], "description": "UI-side text transform applied before the offsets were captured (e.g. `\"pretty-json\"`). Resolvers must apply the same transform before slicing." } }, "description": "Optional anchor pinning the annotation to a specific message / part / offset range inside the trace." }, "ApiKey": { "type": "object", "properties": { "id": { "type": "string", "description": "Stable API-key identifier." }, "organizationId": { "type": "string", "description": "Organization that owns this API key." }, "name": { "type": "string", "description": "Human-readable name." }, "token": { "type": "string", "description": "The full API key token. Returned by create / get / update — store it securely; treat it as a password." }, "lastUsedAt": { "type": [ "string", "null" ], "description": "ISO-8601 timestamp of the most recent successful authentication. `null` until first use." }, "deletedAt": { "type": [ "string", "null" ], "description": "ISO-8601 timestamp at which the key was revoked. `null` while the key is active." }, "createdAt": { "type": "string", "description": "ISO-8601 timestamp of creation." }, "updatedAt": { "type": "string", "description": "ISO-8601 timestamp of the last metadata update (rename, revoke, last-used touch)." } }, "required": [ "id", "organizationId", "name", "token", "lastUsedAt", "deletedAt", "createdAt", "updatedAt" ] }, "CreateApiKeyBody": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1, "description": "Human-readable name for the API key. Used to distinguish keys in the UI." } }, "required": [ "name" ] }, "ApiKeyList": { "type": "object", "properties": { "apiKeys": { "type": "array", "items": { "$ref": "#/components/schemas/ApiKeyListItem" } } }, "required": [ "apiKeys" ] }, "ApiKeyListItem": { "type": "object", "properties": { "id": { "type": "string", "description": "Stable API-key identifier." }, "organizationId": { "type": "string", "description": "Organization that owns this API key." }, "name": { "type": "string", "description": "Human-readable name." }, "token": { "type": "string", "description": "Masked token preview safe to display in lists. Use `GET /api-keys/{id}` to retrieve the full token." }, "lastUsedAt": { "type": [ "string", "null" ], "description": "ISO-8601 timestamp of the most recent successful authentication. `null` until first use." }, "deletedAt": { "type": [ "string", "null" ], "description": "ISO-8601 timestamp at which the key was revoked. `null` while the key is active." }, "createdAt": { "type": "string", "description": "ISO-8601 timestamp of creation." }, "updatedAt": { "type": "string", "description": "ISO-8601 timestamp of the last metadata update." } }, "required": [ "id", "organizationId", "name", "token", "lastUsedAt", "deletedAt", "createdAt", "updatedAt" ] }, "UpdateApiKeyBody": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1, "description": "New human-readable name for the API key." } }, "required": [ "name" ] }, "OAuthKeyList": { "type": "object", "properties": { "oauthKeys": { "type": "array", "items": { "$ref": "#/components/schemas/OAuthKey" } } }, "required": [ "oauthKeys" ] }, "OAuthKey": { "type": "object", "properties": { "id": { "type": "string", "description": "Stable OAuth key identifier." }, "clientId": { "type": "string", "description": "Identifier of the OAuth client the key was issued to." }, "clientName": { "type": [ "string", "null" ], "description": "Display name of the OAuth client." }, "clientIcon": { "type": [ "string", "null" ], "description": "Icon URL of the OAuth client." }, "userId": { "type": "string", "description": "Identifier of the user the key belongs to." }, "userName": { "type": [ "string", "null" ], "description": "Display name of the user. `null` until the user completes onboarding." }, "userEmail": { "type": "string", "description": "Email of the user." }, "lastActivityAt": { "type": [ "string", "null" ], "description": "ISO-8601 timestamp of the last refresh on the key. `null` if the key has never been used." }, "connectedAt": { "type": "string", "description": "ISO-8601 timestamp at which the key was connected." }, "disabled": { "type": "boolean", "description": "Whether the key has been disabled." } }, "required": [ "id", "clientId", "clientName", "clientIcon", "userId", "userName", "userEmail", "lastActivityAt", "connectedAt", "disabled" ] }, "AccountResponse": { "type": "object", "properties": { "user": { "$ref": "#/components/schemas/AccountUser" }, "organization": { "$ref": "#/components/schemas/AccountOrganization" }, "role": { "type": [ "string", "null" ], "enum": [ "owner", "admin", "member", null ], "description": "Caller's role in the organization. `null` for API-key callers (no real user behind the credential)." } }, "required": [ "user", "organization", "role" ] }, "AccountUser": { "type": [ "object", "null" ], "properties": { "id": { "type": "string", "description": "Stable user identifier across the API." }, "email": { "type": "string", "description": "Verified email address of the authenticated user." }, "name": { "type": [ "string", "null" ], "description": "Display name, when set. `null` until the user completes onboarding." }, "image": { "type": [ "string", "null" ], "description": "Profile image URL, when set." } }, "required": [ "id", "email", "name", "image" ], "description": "The user the request is acting on behalf of. `null` for API-key callers — API keys are org-scoped, not user-scoped." }, "AccountOrganization": { "type": "object", "properties": { "id": { "type": "string", "description": "Stable organization identifier across the API." }, "name": { "type": "string", "description": "Human-readable organization name." }, "slug": { "type": "string", "description": "URL-safe slug. Regenerated when the organization is renamed — don't use it as a stable key." } }, "required": [ "id", "name", "slug" ], "description": "Organization the request is scoped to." }, "MemberList": { "type": "object", "properties": { "members": { "type": "array", "items": { "$ref": "#/components/schemas/Member" } } }, "required": [ "members" ] }, "Member": { "oneOf": [ { "$ref": "#/components/schemas/ActiveMember" }, { "$ref": "#/components/schemas/InvitedMember" } ], "discriminator": { "propertyName": "status", "mapping": { "active": "#/components/schemas/ActiveMember", "invited": "#/components/schemas/InvitedMember" } } }, "ActiveMember": { "type": "object", "properties": { "status": { "type": "string", "enum": [ "active" ], "description": "Discriminator for confirmed members — the user has accepted their invitation and joined the org." }, "id": { "type": "string", "description": "Stable membership identifier. Use this to address the row in update/remove endpoints." }, "organizationId": { "type": "string", "description": "Organization this membership belongs to." }, "userId": { "type": "string", "description": "Identifier of the user the membership represents." }, "role": { "type": "string", "enum": [ "owner", "admin", "member" ], "description": "Member's role within the organization." }, "name": { "type": [ "string", "null" ], "description": "Display name of the user. `null` if the user hasn't completed onboarding." }, "email": { "type": "string", "description": "User's email address, verified at signup." }, "image": { "type": [ "string", "null" ], "description": "User's profile image URL, when set." }, "joinedAt": { "type": "string", "description": "ISO-8601 timestamp at which the user joined the organization." } }, "required": [ "status", "id", "organizationId", "userId", "role", "name", "email", "image", "joinedAt" ] }, "InvitedMember": { "type": "object", "properties": { "status": { "type": "string", "enum": [ "invited" ], "description": "Discriminator for pending invitations — the invitee hasn't accepted yet, so no user record exists." }, "id": { "type": "string", "description": "Stable invitation identifier. Distinct from membership ids." }, "organizationId": { "type": "string", "description": "Organization the invitation grants access to." }, "userId": { "type": "null", "description": "Always `null` — no user record exists until the invitation is accepted." }, "role": { "type": [ "string", "null" ], "enum": [ "owner", "admin", "member", null ], "description": "Role the invitee will get once they accept. `null` means the default (`member`)." }, "name": { "type": "null", "description": "Always `null` — no user record exists yet." }, "email": { "type": "string", "description": "Email address the invitation was sent to." }, "image": { "type": "null", "description": "Always `null` — no user record exists yet." }, "invitedAt": { "type": "string", "description": "ISO-8601 timestamp at which the invitation was created." }, "expiresAt": { "type": "string", "description": "ISO-8601 timestamp at which the invitation expires." }, "inviterId": { "type": "string", "description": "User id of the member who issued the invitation." } }, "required": [ "status", "id", "organizationId", "userId", "role", "name", "email", "image", "invitedAt", "expiresAt", "inviterId" ] }, "InviteMemberBody": { "type": "object", "properties": { "email": { "type": "string", "format": "email", "description": "Email address to invite. The invitee receives an accept link by email." }, "role": { "type": "string", "enum": [ "owner", "admin", "member" ], "description": "Role to grant on acceptance. Defaults to `member` when omitted." } }, "required": [ "email" ] }, "UpdateMemberRoleBody": { "type": "object", "properties": { "role": { "type": "string", "enum": [ "admin", "member" ], "description": "New role. Owners cannot be changed via this endpoint — owner-transfer happens on the web." } }, "required": [ "role" ] } }, "parameters": {} }, "paths": { "/health": { "get": { "operationId": "health.get", "tags": [ "Health" ], "summary": "Health check", "responses": { "200": { "description": "Service is healthy", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HealthResponse" } } } } } } }, "/.well-known/oauth-protected-resource": { "get": { "operationId": "wellKnown.oauthProtectedResource", "tags": [ "Well-known" ], "summary": "OAuth protected resource metadata", "description": "RFC 9728 metadata document advertising the authorization server(s) trusted to issue access tokens for this API.", "responses": { "200": { "description": "Protected resource metadata", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OAuthProtectedResourceMetadata" } } } } } } }, "/v1/projects": { "post": { "tags": [ "Projects" ], "x-fern-sdk-group-name": "projects", "x-fern-sdk-method-name": "create", "summary": "Create project", "description": "Creates a new project within the organization. The name must be unique within the org.", "security": [ { "ApiKeyAuth": [] } ], "operationId": "createProject", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateProjectBody" } } } }, "responses": { "201": { "description": "Project created", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Project" } } } }, "400": { "description": "Validation error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "description": "Unauthorized", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } }, "get": { "tags": [ "Projects" ], "x-fern-sdk-group-name": "projects", "x-fern-sdk-method-name": "list", "summary": "List projects", "description": "Returns every project in the organization. The response uses the standard paginated shape; the project list currently fits in a single page (`nextCursor` is always `null`).", "security": [ { "ApiKeyAuth": [] } ], "operationId": "listProjects", "responses": { "200": { "description": "List of projects", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PaginatedProjects" } } } }, "400": { "description": "Validation error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "description": "Unauthorized", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } }, "/v1/projects/{projectSlug}": { "get": { "tags": [ "Projects" ], "x-fern-sdk-group-name": "projects", "x-fern-sdk-method-name": "get", "summary": "Get project", "description": "Returns a single project by slug.", "security": [ { "ApiKeyAuth": [] } ], "operationId": "getProject", "parameters": [ { "schema": { "type": "string", "description": "Project slug (human-readable identifier)" }, "required": true, "description": "Project slug (human-readable identifier)", "name": "projectSlug", "in": "path" } ], "responses": { "200": { "description": "Project", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Project" } } } }, "400": { "description": "Validation error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "description": "Unauthorized", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } }, "patch": { "tags": [ "Projects" ], "x-fern-sdk-group-name": "projects", "x-fern-sdk-method-name": "update", "summary": "Update project", "description": "Updates a project's name and/or settings. Renaming may regenerate the slug — clients should re-read the response or rely on the `id` for stable references.", "security": [ { "ApiKeyAuth": [] } ], "operationId": "updateProject", "parameters": [ { "schema": { "type": "string", "description": "Project slug (human-readable identifier)" }, "required": true, "description": "Project slug (human-readable identifier)", "name": "projectSlug", "in": "path" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateProjectBody" } } } }, "responses": { "200": { "description": "Updated project", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Project" } } } }, "400": { "description": "Validation error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "description": "Unauthorized", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } }, "delete": { "tags": [ "Projects" ], "x-fern-sdk-group-name": "projects", "x-fern-sdk-method-name": "delete", "summary": "Delete project", "description": "Deletes a project by slug.", "security": [ { "ApiKeyAuth": [] } ], "operationId": "deleteProject", "parameters": [ { "schema": { "type": "string", "description": "Project slug (human-readable identifier)" }, "required": true, "description": "Project slug (human-readable identifier)", "name": "projectSlug", "in": "path" } ], "responses": { "204": { "description": "Project deleted" }, "401": { "description": "Unauthorized", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } }, "/v1/projects/{projectSlug}/scores": { "post": { "tags": [ "Scores" ], "x-fern-sdk-group-name": "scores", "x-fern-sdk-method-name": "create", "summary": "Create project score", "description": "Creates a score against a target trace. The trace is resolved by explicit id (`trace.by = \"id\"`) or by a filter set (`trace.by = \"filters\"`, exactly one match required). Annotations use the separate `/annotations` endpoint.", "security": [ { "ApiKeyAuth": [] } ], "operationId": "createScore", "parameters": [ { "schema": { "type": "string", "description": "Project slug (human-readable identifier)" }, "required": true, "description": "Project slug (human-readable identifier)", "name": "projectSlug", "in": "path" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateScoreBody" } } } }, "responses": { "201": { "description": "Score created", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ScoreResponse" } } } }, "400": { "description": "Validation error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "description": "Unauthorized", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } }, "/v1/projects/{projectSlug}/annotations": { "post": { "tags": [ "Annotations" ], "x-fern-sdk-group-name": "annotations", "x-fern-sdk-method-name": "create", "summary": "Create project annotation", "description": "Creates a published annotation score against a target trace. The trace is resolved by explicit id (`trace.by = \"id\"`) or by a filter set (`trace.by = \"filters\"`, exactly one match required). When called with an OAuth token, the annotation is attributed to the authenticated user.", "security": [ { "ApiKeyAuth": [] } ], "operationId": "createAnnotation", "parameters": [ { "schema": { "type": "string", "description": "Project slug (human-readable identifier)" }, "required": true, "description": "Project slug (human-readable identifier)", "name": "projectSlug", "in": "path" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateAnnotationBody" } } } }, "responses": { "201": { "description": "Annotation created", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AnnotationScoreResponse" } } } }, "400": { "description": "Validation error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "description": "Unauthorized", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } }, "/v1/api-keys": { "post": { "tags": [ "API Keys" ], "x-fern-sdk-group-name": "apiKeys", "x-fern-sdk-method-name": "create", "summary": "Generate API key", "description": "Generates a new API key for the organization. The token is only returned once — store it securely.", "security": [ { "ApiKeyAuth": [] } ], "operationId": "createApiKey", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateApiKeyBody" } } } }, "responses": { "201": { "description": "API key generated", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiKey" } } } }, "400": { "description": "Validation error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "description": "Unauthorized", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } }, "get": { "tags": [ "API Keys" ], "x-fern-sdk-group-name": "apiKeys", "x-fern-sdk-method-name": "list", "summary": "List API keys", "description": "Returns all API keys for the organization. Tokens are not included in the list response.", "security": [ { "ApiKeyAuth": [] } ], "operationId": "listApiKeys", "responses": { "200": { "description": "List of API keys", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiKeyList" } } } }, "401": { "description": "Unauthorized", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } }, "/v1/api-keys/{id}": { "get": { "tags": [ "API Keys" ], "x-fern-sdk-group-name": "apiKeys", "x-fern-sdk-method-name": "get", "summary": "Get API key", "description": "Returns a single API key including the full unmasked `token`. Useful for retrieving a stored token by id without rotating it.", "security": [ { "ApiKeyAuth": [] } ], "operationId": "getApiKey", "parameters": [ { "schema": { "type": "string", "description": "Resource ID" }, "required": true, "description": "Resource ID", "name": "id", "in": "path" } ], "responses": { "200": { "description": "API key", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiKey" } } } }, "400": { "description": "Validation error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "description": "Unauthorized", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } }, "patch": { "tags": [ "API Keys" ], "x-fern-sdk-group-name": "apiKeys", "x-fern-sdk-method-name": "update", "summary": "Update API key", "description": "Renames an API key. The token itself is immutable — use create + revoke if you need a new value.", "security": [ { "ApiKeyAuth": [] } ], "operationId": "updateApiKey", "parameters": [ { "schema": { "type": "string", "description": "Resource ID" }, "required": true, "description": "Resource ID", "name": "id", "in": "path" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateApiKeyBody" } } } }, "responses": { "200": { "description": "API key updated", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiKey" } } } }, "400": { "description": "Validation error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "description": "Unauthorized", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } }, "delete": { "tags": [ "API Keys" ], "x-fern-sdk-group-name": "apiKeys", "x-fern-sdk-method-name": "revoke", "summary": "Revoke API key", "description": "Revokes an API key.", "security": [ { "ApiKeyAuth": [] } ], "operationId": "revokeApiKey", "parameters": [ { "schema": { "type": "string", "description": "Resource ID" }, "required": true, "description": "Resource ID", "name": "id", "in": "path" } ], "responses": { "204": { "description": "API key revoked" }, "401": { "description": "Unauthorized", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } }, "/v1/oauth-keys": { "get": { "tags": [ "OAuth Keys" ], "x-fern-sdk-group-name": "oauthKeys", "x-fern-sdk-method-name": "list", "summary": "List OAuth keys", "description": "Returns every OAuth key (like MCP clients) connected to the organization.", "security": [ { "ApiKeyAuth": [] } ], "operationId": "listOAuthKeys", "responses": { "200": { "description": "List of OAuth keys", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OAuthKeyList" } } } } } } }, "/v1/oauth-keys/{oauthKeyId}": { "get": { "tags": [ "OAuth Keys" ], "x-fern-sdk-group-name": "oauthKeys", "x-fern-sdk-method-name": "get", "summary": "Get OAuth key", "description": "Returns a single OAuth key (like MCP clients) by id.", "security": [ { "ApiKeyAuth": [] } ], "operationId": "getOAuthKey", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "OAuth key identifier." }, "required": true, "description": "OAuth key identifier.", "name": "oauthKeyId", "in": "path" } ], "responses": { "200": { "description": "OAuth key", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OAuthKey" } } } }, "400": { "description": "Validation error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "description": "Unauthorized", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } }, "delete": { "tags": [ "OAuth Keys" ], "x-fern-sdk-group-name": "oauthKeys", "x-fern-sdk-method-name": "revoke", "summary": "Revoke OAuth key", "description": "Revokes an OAuth key (like MCP clients). The connected client immediately loses access.", "security": [ { "ApiKeyAuth": [] } ], "operationId": "revokeOAuthKey", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "OAuth key identifier." }, "required": true, "description": "OAuth key identifier.", "name": "oauthKeyId", "in": "path" } ], "responses": { "204": { "description": "OAuth key revoked" }, "401": { "description": "Unauthorized", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } }, "/v1/account": { "get": { "tags": [ "Account" ], "x-fern-sdk-group-name": "account", "x-fern-sdk-method-name": "get", "summary": "Get account", "description": "Returns the caller's account snapshot: the organization the request is scoped to, plus the user record and their role when the request was made by a real user (OAuth). API-key callers receive `user: null` and `role: null` because API keys aren't tied to a specific user.", "security": [ { "ApiKeyAuth": [] } ], "operationId": "getAccount", "responses": { "200": { "description": "Account snapshot", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AccountResponse" } } } }, "400": { "description": "Validation error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "description": "Unauthorized", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } }, "/v1/members": { "get": { "tags": [ "Members" ], "x-fern-sdk-group-name": "members", "x-fern-sdk-method-name": "list", "summary": "List members", "description": "Returns every active member of the caller's organization with their role and user details.", "security": [ { "ApiKeyAuth": [] } ], "operationId": "listMembers", "responses": { "200": { "description": "List of members", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MemberList" } } } }, "400": { "description": "Validation error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "description": "Unauthorized", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } }, "post": { "tags": [ "Members" ], "x-fern-sdk-group-name": "members", "x-fern-sdk-method-name": "invite", "summary": "Invite a member", "description": "Issues an invitation to join the caller's organization. The invitee receives an accept link by email and becomes a member once they accept. The response is the pending invitation record. Requires OAuth authentication (API-key callers can't act on behalf of a specific user).", "security": [ { "ApiKeyAuth": [] } ], "operationId": "inviteMember", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/InviteMemberBody" } } } }, "responses": { "201": { "description": "Invitation created", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/InvitedMember" } } } }, "400": { "description": "Validation error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "description": "Unauthorized", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } }, "/v1/members/{id}": { "get": { "tags": [ "Members" ], "x-fern-sdk-group-name": "members", "x-fern-sdk-method-name": "get", "summary": "Get member", "description": "Returns a single member of the caller's organization, including their role and user details.", "security": [ { "ApiKeyAuth": [] } ], "operationId": "getMember", "parameters": [ { "schema": { "type": "string", "description": "Resource ID" }, "required": true, "description": "Resource ID", "name": "id", "in": "path" } ], "responses": { "200": { "description": "Member", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ActiveMember" } } } }, "400": { "description": "Validation error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "description": "Unauthorized", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } }, "patch": { "tags": [ "Members" ], "x-fern-sdk-group-name": "members", "x-fern-sdk-method-name": "update", "summary": "Update a member", "description": "Updates a member of the caller's organization. Today only the role is mutable. The caller must be an admin or owner; owners cannot be demoted via this endpoint. Requires OAuth authentication.", "security": [ { "ApiKeyAuth": [] } ], "operationId": "updateMember", "parameters": [ { "schema": { "type": "string", "description": "Resource ID" }, "required": true, "description": "Resource ID", "name": "id", "in": "path" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateMemberRoleBody" } } } }, "responses": { "200": { "description": "Member with the updated role", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ActiveMember" } } } }, "400": { "description": "Validation error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "description": "Unauthorized", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } }, "delete": { "tags": [ "Members" ], "x-fern-sdk-group-name": "members", "x-fern-sdk-method-name": "remove", "summary": "Remove a member", "description": "Removes a member from the caller's organization. Self-removal and removing the organization owner are rejected — transfer ownership first. Requires OAuth authentication.", "security": [ { "ApiKeyAuth": [] } ], "operationId": "removeMember", "parameters": [ { "schema": { "type": "string", "description": "Resource ID" }, "required": true, "description": "Resource ID", "name": "id", "in": "path" } ], "responses": { "204": { "description": "Member removed" }, "401": { "description": "Unauthorized", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } }, "webhooks": {} }