{"components":{"schemas":{"Code":{"description":"The stable error vocabulary. The slug (`snake_case`) is what clients see in\n`code`; the HTTP status follows the standard gRPC mapping, plus the two\nHTTP-only codes for request bodies.","enum":["bad_request","not_found","already_exists","conflict","forbidden","unauthenticated","rate_limited","quota_exceeded","failed_precondition","unimplemented","unavailable","timeout","cancelled","internal","unsupported_media_type","payload_too_large","method_not_allowed"],"type":"string"},"Detail":{"description":"A typed detail, translated from `google.rpc` error details.","oneOf":[{"description":"`google.rpc.BadRequest.FieldViolation`: which field, and why.","properties":{"description":{"description":"What is wrong with it.","type":"string"},"field":{"description":"Field path in the request.","type":"string"},"type":{"enum":["field"],"type":"string"}},"required":["field","description","type"],"type":"object"},{"description":"`google.rpc.ErrorInfo`: a machine-readable reason.","properties":{"domain":{"description":"Who owns the reason.","type":"string"},"metadata":{"additionalProperties":{"type":"string"},"description":"Extra key/values.","propertyNames":{"type":"string"},"type":"object"},"reason":{"description":"Reason, `UPPER_SNAKE_CASE` by convention.","type":"string"},"type":{"enum":["info"],"type":"string"}},"required":["reason","domain","metadata","type"],"type":"object"},{"description":"`google.rpc.RetryInfo`: when to try again; also the `Retry-After` header.","properties":{"after_seconds":{"description":"Seconds to wait, rounded up.","format":"int64","minimum":0,"type":"integer"},"type":{"enum":["retry"],"type":"string"}},"required":["after_seconds","type"],"type":"object"}]},"Health":{"description":"`GET /healthz` body.","properties":{"status":{"description":"Always `ok` when the process answers.","type":"string"}},"required":["status"],"type":"object"},"Key":{"description":"The key claims, as `OpenAPI` sees them.\n\nA mirror of `tbd_common::principal::Key`. The type itself lives in\n`tbd-common`, which cannot derive `utoipa::ToSchema` without taking a\ndependency on a documentation crate it has no other use for. Mirroring it\nhere keeps `docs/protocol/openapi.json` byte-identical across this\nrefactor -- a published contract must not shift because of an internal\nmove.","properties":{"id":{"description":"Key id.","type":"string"},"parent":{"description":"The parent key, for a sub-key.","type":["string","null"]}},"required":["id"],"type":"object"},"Me":{"description":"`GET /v1/me` body.","properties":{"client_id":{"description":"The OAuth client the call came through, if any.","type":["string","null"]},"email":{"description":"E-mail address, when the token carries one (a person's ID token does).","type":["string","null"]},"key":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/Key","description":"Key and parent key, when minted."}]},"kind":{"description":"`person`, `client` or `service`.","type":"string"},"name":{"description":"Display name, when the token carries one.","type":["string","null"]},"org":{"description":"Organisation, when minted.","type":["string","null"]},"role":{"description":"Role, when the consent step stamped one.","type":["string","null"]},"scopes":{"description":"Granted scopes.","items":{"type":"string"},"type":"array"},"subject":{"description":"The `sub` claim.","type":"string"}},"required":["subject","kind","scopes"],"type":"object"},"Problem":{"description":"`{\"code\",\"error\",\"details\"}`: the REST body and the SSE `error` payload.","properties":{"code":{"$ref":"#/components/schemas/Code","description":"The slug."},"details":{"description":"Typed details.","items":{"$ref":"#/components/schemas/Detail"},"type":"array"},"error":{"description":"The sentence.","type":"string"}},"required":["code","error","details"],"type":"object"},"Readiness":{"description":"`GET /readyz`: every backend's live state; `ready` when every required one\nis serving.","properties":{"ready":{"description":"Every required backend is `serving`.","type":"boolean"},"services":{"additionalProperties":{"$ref":"#/components/schemas/ServiceState"},"description":"Per backend, by registry name.","propertyNames":{"type":"string"},"type":"object"}},"required":["ready","services"],"type":"object"},"ServiceState":{"description":"What a backend's health service last answered, as `/readyz` reports it.","enum":["serving","not_serving","unknown"],"type":"string"},"tbd.accounts.v1.Account":{"description":"`tbd.accounts.v1.Account`","properties":{"created_at":{"type":"string"},"erase_after":{"type":"string"},"id":{"type":"string"},"kind":{"type":"string"},"name":{"type":"string"},"plan":{"type":"string"},"role":{"type":"string"},"slug":{"type":"string"},"status":{"type":"string"}},"type":"object"},"tbd.accounts.v1.GetMeResponse":{"description":"`tbd.accounts.v1.GetMeResponse`","properties":{"account":{"$ref":"#/components/schemas/tbd.accounts.v1.Account"},"email":{"type":"string"},"email_verified":{"type":"boolean"},"key":{"$ref":"#/components/schemas/tbd.accounts.v1.Key"},"name":{"type":"string"},"stub":{"type":"boolean"},"subject":{"type":"string"},"teams":{"items":{"$ref":"#/components/schemas/tbd.accounts.v1.Account"},"type":"array"},"user_id":{"type":"string"}},"type":"object"},"tbd.accounts.v1.GetUnitsResponse":{"description":"`tbd.accounts.v1.GetUnitsResponse`","properties":{"account_id":{"type":"string"},"allowance":{"format":"int64","type":"string"},"days":{"items":{"$ref":"#/components/schemas/tbd.accounts.v1.UnitDay"},"type":"array"},"granted":{"format":"int64","type":"string"},"month":{"type":"string"},"plan":{"$ref":"#/components/schemas/tbd.accounts.v1.Plan"},"remaining":{"format":"int64","type":"string"},"resets_at":{"type":"string"},"usage":{"items":{"$ref":"#/components/schemas/tbd.accounts.v1.UnitUsage"},"type":"array"},"used":{"format":"int64","type":"string"}},"type":"object"},"tbd.accounts.v1.GetUsageResponse":{"description":"`tbd.accounts.v1.GetUsageResponse`","properties":{"plan":{"type":"string"},"rows":{"items":{"$ref":"#/components/schemas/tbd.accounts.v1.UsageRow"},"type":"array"}},"type":"object"},"tbd.accounts.v1.Key":{"description":"`tbd.accounts.v1.Key`","properties":{"client_id":{"type":"string"},"created_at":{"type":"string"},"created_by":{"type":"string"},"id":{"type":"string"},"last_used_at":{"type":"string"},"name":{"type":"string"},"revoked_at":{"type":"string"},"scopes":{"items":{"type":"string"},"type":"array"},"secret_hint":{"type":"string"}},"type":"object"},"tbd.accounts.v1.ListUnitCategoriesResponse":{"description":"`tbd.accounts.v1.ListUnitCategoriesResponse`","properties":{"categories":{"items":{"$ref":"#/components/schemas/tbd.accounts.v1.UnitCategory"},"type":"array"}},"type":"object"},"tbd.accounts.v1.Plan":{"description":"`tbd.accounts.v1.Plan`","properties":{"accounts":{"format":"int64","type":"string"},"at_zero":{"type":"string"},"description":{"type":"string"},"monthly_units":{"format":"int64","type":"string"},"name":{"type":"string"},"updated_at":{"type":"string"}},"type":"object"},"tbd.accounts.v1.UnitCategory":{"description":"`tbd.accounts.v1.UnitCategory`","properties":{"description":{"type":"string"},"name":{"type":"string"},"units_per_call":{"format":"int64","type":"string"},"updated_at":{"type":"string"}},"type":"object"},"tbd.accounts.v1.UnitDay":{"description":"`tbd.accounts.v1.UnitDay`","properties":{"day":{"type":"string"},"units":{"format":"int64","type":"string"}},"type":"object"},"tbd.accounts.v1.UnitUsage":{"description":"`tbd.accounts.v1.UnitUsage`","properties":{"calls":{"format":"int64","type":"string"},"category":{"type":"string"},"key_id":{"type":"string"},"key_name":{"type":"string"},"rpc":{"type":"string"},"units":{"format":"int64","type":"string"}},"type":"object"},"tbd.accounts.v1.UsageRow":{"description":"`tbd.accounts.v1.UsageRow`","properties":{"amount":{"format":"int64","type":"string"},"day":{"type":"string"},"metric":{"type":"string"},"service":{"type":"string"}},"type":"object"},"tbd.radar.v1.Change":{"description":"`tbd.radar.v1.Change`","properties":{"advanced":{"type":"string"},"after":{"type":"string"},"area":{"type":"string"},"example":{"$ref":"#/components/schemas/tbd.radar.v1.Example"},"impact":{"description":"`tbd.radar.v1.Impact`","enum":["IMPACT_UNSPECIFIED","IMPACT_BREAKING","IMPACT_WORTH_KNOWING","IMPACT_NICE_TO_KNOW"],"type":"string"},"novice":{"type":"string"},"practitioner":{"type":"string"},"production_impact":{"type":"string"},"title":{"type":"string"},"try_it":{"type":"string"},"url":{"type":"string"},"what":{"type":"string"}},"type":"object"},"tbd.radar.v1.Digest":{"description":"`tbd.radar.v1.Digest`","properties":{"ai_written":{"type":"boolean"},"changed":{"type":"string"},"changes":{"items":{"$ref":"#/components/schemas/tbd.radar.v1.Change"},"type":"array"},"checked":{"type":"boolean"},"created_at":{"type":"string"},"drill":{"type":"string"},"drill_code":{"$ref":"#/components/schemas/tbd.radar.v1.DrillCode"},"id":{"format":"int64","type":"string"},"item_count":{"format":"int32","type":"integer"},"lang":{"type":"string"},"language":{"type":"string"},"model":{"type":"string"},"origin":{"type":"string"},"published_at":{"type":"string"},"script":{"type":"string"},"status":{"type":"string"},"stub":{"type":"boolean"},"summary":{"type":"string"},"week":{"type":"string"},"why":{"type":"string"}},"type":"object"},"tbd.radar.v1.DrillCode":{"description":"`tbd.radar.v1.DrillCode`","properties":{"output":{"type":"string"},"solution":{"type":"string"},"starter":{"type":"string"},"stub":{"type":"boolean"},"tests":{"type":"string"},"toolchain":{"type":"string"}},"type":"object"},"tbd.radar.v1.Example":{"description":"`tbd.radar.v1.Example`","properties":{"source":{"type":"string"},"stderr":{"type":"string"},"stdout":{"type":"string"},"stub":{"type":"boolean"},"tests":{"type":"string"},"toolchain":{"type":"string"}},"type":"object"},"tbd.radar.v1.GetDigestResponse":{"description":"`tbd.radar.v1.GetDigestResponse`","properties":{"digest":{"$ref":"#/components/schemas/tbd.radar.v1.Digest"}},"type":"object"},"tbd.radar.v1.Item":{"description":"`tbd.radar.v1.Item`","properties":{"id":{"format":"int64","type":"string"},"language":{"type":"string"},"published_at":{"type":"string"},"source":{"type":"string"},"summary":{"type":"string"},"title":{"type":"string"},"url":{"type":"string"}},"type":"object"},"tbd.radar.v1.ListDigestsResponse":{"description":"`tbd.radar.v1.ListDigestsResponse`","properties":{"digests":{"items":{"$ref":"#/components/schemas/tbd.radar.v1.Digest"},"type":"array"}},"type":"object"},"tbd.radar.v1.ListItemsResponse":{"description":"`tbd.radar.v1.ListItemsResponse`","properties":{"items":{"items":{"$ref":"#/components/schemas/tbd.radar.v1.Item"},"type":"array"}},"type":"object"}},"securitySchemes":{"bearer":{"bearerFormat":"JWT","description":"An access token from the identity provider: a person's, or a customer's from the client credentials grant with an API key (docs.inorbit.hr). The gateway verifies it; the audience is `tbd-api`.","scheme":"bearer","type":"http"}}},"info":{"description":"The routes an API key may call. Every body is JSON; every error is the `Problem` envelope; every route takes a bearer token except the health endpoints.","license":{"name":"Proprietary"},"title":"InOrbit API","version":"0.1.0"},"openapi":"3.1.0","paths":{"/healthz":{"get":{"operationId":"healthz","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Health"}}},"description":"The process answers"}},"security":[],"summary":"Liveness: the process is up.","tags":["health"]}},"/readyz":{"get":{"operationId":"readyz","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Readiness"}}},"description":"Every required backend is serving"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Readiness"}}},"description":"A required backend is not serving"}},"security":[],"summary":"Readiness: every required backend answers `SERVING` to a live health\ncheck. The body lists every registered backend either way, so an optional\none that is down is visible without failing the probe.","tags":["health"]}},"/v1/accounts/me":{"get":{"description":"Transcoded from `/tbd.accounts.v1.AccountsService/GetMe` on the `accounts` backend.\n\nA key needs scope `account:read`.","operationId":"AccountsService.GetMe","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/tbd.accounts.v1.GetMeResponse"}}},"description":"`tbd.accounts.v1.GetMeResponse`"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"The error envelope, with the standard gRPC-to-HTTP status"}},"summary":"tbd.accounts.v1.AccountsService/GetMe","tags":["accounts"],"x-tbd-public":true,"x-tbd-scopes":["account:read"]}},"/v1/accounts/orgs/{org_id}/units":{"get":{"description":"Transcoded from `/tbd.accounts.v1.AccountsService/GetUnits` on the `accounts` backend.\n\nA key needs scope `usage:read`.","operationId":"AccountsService.GetUnits","parameters":[{"in":"path","name":"org_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/tbd.accounts.v1.GetUnitsResponse"}}},"description":"`tbd.accounts.v1.GetUnitsResponse`"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"The error envelope, with the standard gRPC-to-HTTP status"}},"summary":"tbd.accounts.v1.AccountsService/GetUnits","tags":["accounts"],"x-tbd-public":true,"x-tbd-scopes":["usage:read"]}},"/v1/accounts/orgs/{org_id}/usage":{"get":{"description":"Transcoded from `/tbd.accounts.v1.AccountsService/GetUsage` on the `accounts` backend.\n\nA key needs scope `usage:read`.","operationId":"AccountsService.GetUsage","parameters":[{"in":"path","name":"org_id","required":true,"schema":{"type":"string"}},{"in":"query","name":"from","required":false,"schema":{"type":"string"}},{"in":"query","name":"to","required":false,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/tbd.accounts.v1.GetUsageResponse"}}},"description":"`tbd.accounts.v1.GetUsageResponse`"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"The error envelope, with the standard gRPC-to-HTTP status"}},"summary":"tbd.accounts.v1.AccountsService/GetUsage","tags":["accounts"],"x-tbd-public":true,"x-tbd-scopes":["usage:read"]}},"/v1/accounts/units/categories":{"get":{"description":"Transcoded from `/tbd.accounts.v1.AccountsService/ListUnitCategories` on the `accounts` backend.\n\nA key needs scope `usage:read`.","operationId":"AccountsService.ListUnitCategories","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/tbd.accounts.v1.ListUnitCategoriesResponse"}}},"description":"`tbd.accounts.v1.ListUnitCategoriesResponse`"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"The error envelope, with the standard gRPC-to-HTTP status"}},"summary":"tbd.accounts.v1.AccountsService/ListUnitCategories","tags":["accounts"],"x-tbd-public":true,"x-tbd-scopes":["usage:read"]}},"/v1/me":{"get":{"description":"A key needs scope `identity:read`.","operationId":"me","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Me"}}},"description":"The principal the gateway verified"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"The gateway forwarded no identity"}},"summary":"Who the verified caller is; 401 when the gateway forwarded no identity.","tags":["identity"],"x-tbd-public":true,"x-tbd-scopes":["identity:read"]}},"/v1/radar/digests":{"get":{"description":"Transcoded from `/tbd.radar.v1.RadarService/ListDigests` on the `radar` backend.\n\nA key needs scope `radar:read`.","operationId":"RadarService.ListDigests","parameters":[{"in":"query","name":"language","required":false,"schema":{"type":"string"}},{"in":"query","name":"lang","required":false,"schema":{"type":"string"}},{"in":"query","name":"limit","required":false,"schema":{"format":"int32","type":"integer"}},{"in":"query","name":"include_drafts","required":false,"schema":{"type":"boolean"}},{"in":"query","name":"before_week","required":false,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/tbd.radar.v1.ListDigestsResponse"}}},"description":"`tbd.radar.v1.ListDigestsResponse`"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"The error envelope, with the standard gRPC-to-HTTP status"}},"summary":"tbd.radar.v1.RadarService/ListDigests","tags":["radar"],"x-tbd-public":true,"x-tbd-scopes":["radar:read"]}},"/v1/radar/digests/{id}":{"get":{"description":"Transcoded from `/tbd.radar.v1.RadarService/GetDigest` on the `radar` backend.\n\nA key needs scope `radar:read`.","operationId":"RadarService.GetDigest","parameters":[{"in":"path","name":"id","required":true,"schema":{"format":"int64","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/tbd.radar.v1.GetDigestResponse"}}},"description":"`tbd.radar.v1.GetDigestResponse`"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"The error envelope, with the standard gRPC-to-HTTP status"}},"summary":"tbd.radar.v1.RadarService/GetDigest","tags":["radar"],"x-tbd-public":true,"x-tbd-scopes":["radar:read"]}},"/v1/radar/items":{"get":{"description":"Transcoded from `/tbd.radar.v1.RadarService/ListItems` on the `radar` backend.\n\nA key needs scope `radar:read`.","operationId":"RadarService.ListItems","parameters":[{"in":"query","name":"language","required":false,"schema":{"type":"string"}},{"in":"query","name":"limit","required":false,"schema":{"format":"int32","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/tbd.radar.v1.ListItemsResponse"}}},"description":"`tbd.radar.v1.ListItemsResponse`"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"The error envelope, with the standard gRPC-to-HTTP status"}},"summary":"tbd.radar.v1.RadarService/ListItems","tags":["radar"],"x-tbd-public":true,"x-tbd-scopes":["radar:read"]}}},"security":[{"bearer":[]}],"servers":[{"description":"This origin","url":"/"}]}