{"openapi":"3.0.3","info":{"title":"BC Object Registry API","version":"1.0.0","description":"Track Business Central object ID ranges for PTE and AppSource apps, and issue new collision-free ranges from Business Central, VS Code, scripts, CI or Copilot Studio.\n\nAuthenticate with an API key from the portal (API keys) in the `X-API-Key` header, or `Authorization: Bearer <key>`. Keys have scopes: read, allocate, write. Errors use RFC 9457 problem+json. Requests are rate limited per key by plan (X-RateLimit-* headers). Send `Idempotency-Key` on POSTs that create things.","contact":{"name":"OnlyBCFans","email":"info@onlybcfans.com"}},"servers":[{"url":"https://bcregistry.ai/api/v1"}],"security":[{"ApiKey":[]},{"Bearer":[]}],"tags":[{"name":"Apps","description":"The registry: apps and their object ranges."},{"name":"Ranges","description":"Issue new ranges and check proposed ones."},{"name":"Pools","description":"Windows that ranges are issued from, and their free ranges."},{"name":"Tenants","description":"Business Central tenants and their environments."},{"name":"Import","description":"Bulk import of existing apps."},{"name":"Workspace","description":"The workspace behind the API key."}],"paths":{"/apps":{"get":{"operationId":"ListApps","summary":"List apps","description":"Apps in the registry with their ranges, environments and overlaps. Filter by tenant, type, status, App ID or text.\n\nScope: `read`.","tags":["Apps"],"parameters":[{"name":"tenantId","in":"query","required":false,"description":"Our id for the tenant.","schema":{"type":"string","format":"uuid"}},{"name":"bcTenantId","in":"query","required":false,"description":"The Business Central (Microsoft Entra) tenant ID. From AL: TenantId().","schema":{"type":"string","format":"uuid"}},{"name":"type","in":"query","required":false,"description":"PTE or AppSource.","schema":{"type":"string","enum":["PTE","AppSource"]}},{"name":"status","in":"query","required":false,"description":"Pending, Active or Retired.","schema":{"type":"string","enum":["Pending","Active","Retired"]}},{"name":"appId","in":"query","required":false,"description":"The id in app.json.","schema":{"type":"string","format":"uuid"}},{"name":"q","in":"query","required":false,"description":"Text in the name, App ID, repo, publisher or ranges.","schema":{"type":"string"}}],"responses":{"200":{"description":"The apps.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppList"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key lacks the \"read\" scope.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The request was refused; see detail.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded; see Retry-After.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"operationId":"CreateApp","summary":"Register an app","description":"Add an app that already has its object range(s), e.g. from app.json in a CI step. Overlaps are allowed and returned as warnings.\n\nScope: `write`.","tags":["Apps"],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Any unique string (e.g. a UUID). Retrying with the same key returns the first response instead of doing it twice.","schema":{"type":"string"}}],"requestBody":{"required":true,"description":"The app.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppInput"}}}},"responses":{"201":{"description":"The new app and any warnings.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppResult"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key lacks the \"write\" scope.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The request was refused; see detail.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded; see Retry-After.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/apps/{id}":{"get":{"operationId":"GetApp","summary":"Get an app","description":"One app with ranges, environments and overlaps.\n\nScope: `read`.","tags":["Apps"],"parameters":[{"name":"id","in":"path","required":true,"description":"The app's id.","schema":{"type":"string"}}],"responses":{"200":{"description":"The app.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppResult"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key lacks the \"read\" scope.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The request was refused; see detail.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded; see Retry-After.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"patch":{"operationId":"UpdateApp","summary":"Update an app","description":"Change only the fields sent, e.g. set the App ID and mark the app Active, or retire it.\n\nScope: `write`.","tags":["Apps"],"parameters":[{"name":"id","in":"path","required":true,"description":"The app's id.","schema":{"type":"string"}}],"requestBody":{"required":true,"description":"Fields to change.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppPatch"}}}},"responses":{"200":{"description":"The updated app.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppResult"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key lacks the \"write\" scope.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The request was refused; see detail.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded; see Retry-After.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"delete":{"operationId":"DeleteApp","summary":"Delete an app","description":"Delete an app and free its ranges. Confirm with the app's exact name, like the portal's typed confirmation. Org admins can restore it for 30 days.\n\nScope: `write`.","tags":["Apps"],"parameters":[{"name":"id","in":"path","required":true,"description":"The app's id.","schema":{"type":"string"}},{"name":"confirm","in":"query","required":true,"description":"The app's exact name.","schema":{"type":"string"}}],"responses":{"200":{"description":"What was deleted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteResult"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key lacks the \"write\" scope.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The request was refused; see detail.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded; see Retry-After.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/ranges/allocate":{"post":{"operationId":"AllocateRange","summary":"Issue a new range","description":"Reserve the first free block of the size asked for and save it as a Pending app. Collisions are checked across the whole tenant. Send an Idempotency-Key so retries never issue twice.\n\nScope: `allocate`.","tags":["Ranges"],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Any unique string (e.g. a UUID). Retrying with the same key returns the first response instead of doing it twice.","schema":{"type":"string"}}],"requestBody":{"required":true,"description":"What to issue.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AllocateInput"}}}},"responses":{"201":{"description":"The issued range, ready for app.json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AllocateResult"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key lacks the \"allocate\" scope.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The request was refused; see detail.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded; see Retry-After.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/ranges/check":{"post":{"operationId":"CheckRange","summary":"Check a range","description":"Is from–to free in the tenant (or AppSource registry)? Lists the apps it would overlap.\n\nScope: `read`.","tags":["Ranges"],"requestBody":{"required":true,"description":"The range to check.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckInput"}}}},"responses":{"200":{"description":"Whether it's free, and any overlaps.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckResult"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key lacks the \"read\" scope.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The request was refused; see detail.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded; see Retry-After.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/pools":{"get":{"operationId":"ListPools","summary":"List pools","description":"Each tenant's PTE pool and the partner-wide AppSource pools, with usage.\n\nScope: `read`.","tags":["Pools"],"responses":{"200":{"description":"The pools.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PoolList"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key lacks the \"read\" scope.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The request was refused; see detail.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded; see Retry-After.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/pools/{id}/free":{"get":{"operationId":"GetFreeRanges","summary":"Free ranges in a pool","description":"The pool's free ranges, computed live.\n\nScope: `read`.","tags":["Pools"],"parameters":[{"name":"id","in":"path","required":true,"description":"The pool's id.","schema":{"type":"string"}}],"responses":{"200":{"description":"Free ranges.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FreeRanges"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key lacks the \"read\" scope.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The request was refused; see detail.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded; see Retry-After.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/tenants":{"get":{"operationId":"ListTenants","summary":"List tenants","description":"The workspace's Business Central tenants with their environments.\n\nScope: `read`.","tags":["Tenants"],"responses":{"200":{"description":"The tenants.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantList"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key lacks the \"read\" scope.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The request was refused; see detail.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded; see Retry-After.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"operationId":"CreateTenant","summary":"Add a tenant","description":"Add a customer tenant (Premium (Partner)). It gets its own PTE pool and a Production environment.\n\nScope: `write`.","tags":["Tenants"],"requestBody":{"required":true,"description":"The tenant.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantInput"}}}},"responses":{"201":{"description":"The new tenant.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantResult"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key lacks the \"write\" scope.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The request was refused; see detail.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded; see Retry-After.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/tenants/{id}":{"get":{"operationId":"GetTenant","summary":"Get a tenant","description":"One tenant, by our id or its BC Tenant ID.\n\nScope: `read`.","tags":["Tenants"],"parameters":[{"name":"id","in":"path","required":true,"description":"The tenant's id.","schema":{"type":"string"}}],"responses":{"200":{"description":"The tenant.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantResult"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key lacks the \"read\" scope.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The request was refused; see detail.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded; see Retry-After.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"patch":{"operationId":"UpdateTenant","summary":"Update a tenant","description":"Rename it, change its domain or Tenant ID, or activate/deactivate it.\n\nScope: `write`.","tags":["Tenants"],"parameters":[{"name":"id","in":"path","required":true,"description":"The tenant's id.","schema":{"type":"string"}}],"requestBody":{"required":true,"description":"Fields to change.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantPatch"}}}},"responses":{"200":{"description":"The tenant.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantResult"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key lacks the \"write\" scope.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The request was refused; see detail.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded; see Retry-After.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/import":{"post":{"operationId":"ImportApps","summary":"Import existing apps","description":"Bulk import from a JSON array or a file (registry.json, ObjectRegistry.md, app.json, CSV, .zip). dryRun (default) returns the preview and a previewId; commit with dryRun false and that previewId.\n\nScope: `write`.","tags":["Import"],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Any unique string (e.g. a UUID). Retrying with the same key returns the first response instead of doing it twice.","schema":{"type":"string"}}],"requestBody":{"required":true,"description":"Apps or a file.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportInput"}}}},"responses":{"200":{"description":"The preview report, and what was committed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportReport"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key lacks the \"write\" scope.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The request was refused; see detail.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded; see Retry-After.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/import/{id}":{"get":{"operationId":"GetImport","summary":"Get an import","description":"An import job's status and counts.\n\nScope: `write`.","tags":["Import"],"parameters":[{"name":"id","in":"path","required":true,"description":"The import's id.","schema":{"type":"string"}}],"responses":{"200":{"description":"The import job.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportJob"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key lacks the \"write\" scope.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The request was refused; see detail.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded; see Retry-After.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/import/{id}/undo":{"post":{"operationId":"UndoImport","summary":"Undo an import","description":"Undo a committed import within 24 hours, if none of its apps were edited since.\n\nScope: `write`.","tags":["Import"],"parameters":[{"name":"id","in":"path","required":true,"description":"The import's id.","schema":{"type":"string"}}],"responses":{"200":{"description":"What was undone.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UndoResult"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key lacks the \"write\" scope.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The request was refused; see detail.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded; see Retry-After.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/me":{"get":{"operationId":"GetWorkspace","summary":"Who am I","description":"The workspace, plan and scopes this API key acts with.\n\nScope: `read`.","tags":["Workspace"],"responses":{"200":{"description":"The workspace and key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Me"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key lacks the \"read\" scope.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"The request was refused; see detail.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded; see Retry-After.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}}},"components":{"securitySchemes":{"ApiKey":{"type":"apiKey","in":"header","name":"X-API-Key","description":"An API key from the portal."},"Bearer":{"type":"http","scheme":"bearer","description":"The same API key as a Bearer token."}},"schemas":{"Range":{"type":"object","required":["from","to"],"properties":{"from":{"type":"integer","example":50100},"to":{"type":"integer","example":50119}}},"TenantRef":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"bcTenantId":{"type":"string","format":"uuid"},"customerName":{"type":"string"}}},"App":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string","example":"Warehouse Labels"},"appId":{"type":"string","format":"uuid","description":"The id in app.json; empty while Pending.","x-nullable":true},"type":{"type":"string","enum":["PTE","AppSource"]},"status":{"type":"string","enum":["Pending","Active","Retired"]},"tenant":{"$ref":"#/components/schemas/TenantRef"},"ranges":{"type":"array","items":{"$ref":"#/components/schemas/Range"}},"rangesText":{"type":"string","example":"50100–50119; 50200–50209"},"environments":{"type":"array","items":{"type":"string"},"description":"BC environments the app is deployed to."},"publisher":{"type":"string"},"repo":{"type":"object","properties":{"name":{"type":"string"},"url":{"type":"string"},"visibility":{"type":"string","enum":["Public","Private"]}}},"issuedOn":{"type":"string","format":"date"},"overlapsWith":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"}}}},"notes":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"AppList":{"type":"object","properties":{"apps":{"type":"array","items":{"$ref":"#/components/schemas/App"}},"count":{"type":"integer"}}},"AppResult":{"type":"object","properties":{"app":{"$ref":"#/components/schemas/App"},"warnings":{"type":"array","items":{"type":"string"}}}},"AppInput":{"type":"object","required":["name","ranges"],"properties":{"name":{"type":"string"},"type":{"type":"string","enum":["PTE","AppSource"],"default":"PTE"},"tenantId":{"type":"string","format":"uuid"},"bcTenantId":{"type":"string","format":"uuid","description":"Name the tenant by its BC Tenant ID instead of tenantId."},"appId":{"type":"string","format":"uuid","description":"The id in app.json. Required for Active."},"ranges":{"type":"array","items":{"$ref":"#/components/schemas/Range"},"description":"The app's object ranges. A string such as \"50100-50119; 50200-50209\" is accepted too."},"status":{"type":"string","enum":["Pending","Active","Retired"]},"publisher":{"type":"string"},"repoName":{"type":"string"},"repoUrl":{"type":"string"},"repoVisibility":{"type":"string","enum":["Public","Private"]},"notes":{"type":"string"},"environments":{"type":"array","items":{"type":"string"},"description":"BC environment names, case-insensitive."}}},"AppPatch":{"type":"object","description":"Send only the fields to change.","properties":{"name":{"type":"string"},"appId":{"type":"string","format":"uuid"},"ranges":{"type":"array","items":{"$ref":"#/components/schemas/Range"}},"status":{"type":"string","enum":["Pending","Active","Retired"]},"publisher":{"type":"string"},"repoName":{"type":"string"},"repoUrl":{"type":"string"},"repoVisibility":{"type":"string","enum":["Public","Private"]},"notes":{"type":"string"},"environments":{"type":"array","items":{"type":"string"}}}},"DeleteResult":{"type":"object","properties":{"deleted":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"freed":{"type":"string"}}},"restorableDays":{"type":"integer"}}},"AllocateInput":{"type":"object","required":["name","size"],"properties":{"name":{"type":"string","description":"A project name; saved as a Pending app.","example":"Contoso Labels"},"size":{"type":"integer","description":"How many object IDs.","example":20},"type":{"type":"string","enum":["PTE","AppSource"],"default":"PTE"},"tenantId":{"type":"string","format":"uuid"},"bcTenantId":{"type":"string","format":"uuid","description":"From AL: TenantId(). Optional on single-tenant plans."},"poolId":{"type":"string","format":"uuid","description":"A specific pool (e.g. one of several AppSource pools)."},"environments":{"type":"array","items":{"type":"string"},"description":"BC environment names the app will be deployed to."}}},"AllocateResult":{"type":"object","properties":{"range":{"$ref":"#/components/schemas/Range"},"rangeText":{"type":"string","example":"50120–50139"},"idRanges":{"type":"array","items":{"$ref":"#/components/schemas/Range"},"description":"Ready for app.json."},"app":{"$ref":"#/components/schemas/App"}}},"CheckInput":{"type":"object","required":["from","to"],"properties":{"from":{"type":"integer"},"to":{"type":"integer"},"type":{"type":"string","enum":["PTE","AppSource"]},"tenantId":{"type":"string","format":"uuid"},"bcTenantId":{"type":"string","format":"uuid"}}},"CheckResult":{"type":"object","properties":{"range":{"$ref":"#/components/schemas/Range"},"rangeText":{"type":"string"},"free":{"type":"boolean","description":"True when no app in the tenant (or AppSource registry) uses any of these IDs."},"overlaps":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"status":{"type":"string"},"ranges":{"type":"array","items":{"$ref":"#/components/schemas/Range"}}}}},"pool":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"from":{"type":"integer"},"to":{"type":"integer"}}},"tenant":{"$ref":"#/components/schemas/TenantRef"}}},"Pool":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"type":{"type":"string","enum":["PTE","AppSource"]},"from":{"type":"integer"},"to":{"type":"integer"},"tenant":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"customerName":{"type":"string"},"active":{"type":"boolean"}}},"apps":{"type":"integer"},"usedIds":{"type":"integer"},"freeIds":{"type":"integer"}}},"PoolList":{"type":"object","properties":{"pools":{"type":"array","items":{"$ref":"#/components/schemas/Pool"}}}},"FreeRanges":{"type":"object","properties":{"pool":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"type":{"type":"string"},"from":{"type":"integer"},"to":{"type":"integer"}}},"free":{"type":"array","items":{"$ref":"#/components/schemas/Range"}},"freeText":{"type":"string"},"freeIds":{"type":"integer"}}},"Tenant":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"hosting":{"type":"string","enum":["online","onprem"],"description":"onprem: no Tenant ID and no admin center; address it by id."},"bcTenantId":{"type":"string","format":"uuid","description":"Null for on-premises tenants.","x-nullable":true},"customerName":{"type":"string"},"domain":{"type":"string"},"active":{"type":"boolean"},"adminCenterUrl":{"type":"string","description":"Null for on-premises tenants.","x-nullable":true},"environments":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"type":{"type":"string","enum":["Production","Sandbox"]}}}}}},"TenantList":{"type":"object","properties":{"tenants":{"type":"array","items":{"$ref":"#/components/schemas/Tenant"}}}},"TenantResult":{"type":"object","properties":{"tenant":{"$ref":"#/components/schemas/Tenant"}}},"TenantInput":{"type":"object","required":["customerName"],"properties":{"hosting":{"type":"string","enum":["online","onprem"],"default":"online"},"bcTenantId":{"type":"string","description":"Required for online tenants; omit for on-premises."},"customerName":{"type":"string"},"domain":{"type":"string"}}},"TenantPatch":{"type":"object","properties":{"customerName":{"type":"string"},"domain":{"type":"string"},"bcTenantId":{"type":"string"},"hosting":{"type":"string","enum":["online","onprem"]},"active":{"type":"boolean"}}},"ImportInput":{"type":"object","properties":{"dryRun":{"type":"boolean","default":true,"description":"Preview only (default). Commit with dryRun false and the previewId."},"previewId":{"type":"string","format":"uuid","description":"Commit this previewed import exactly as previewed."},"decisions":{"type":"object","additionalProperties":{"type":"string","enum":["skip","update","new"]},"description":"Per row index; duplicates default to skip."},"tenantId":{"type":"string","format":"uuid"},"bcTenantId":{"type":"string","format":"uuid"},"apps":{"type":"array","items":{"$ref":"#/components/schemas/AppInput"}},"file":{"type":"object","properties":{"name":{"type":"string","example":"registry.json"},"content":{"type":"string"},"encoding":{"type":"string","enum":["utf8","base64"],"default":"utf8"}},"description":"registry.json, ObjectRegistry.md, app.json, CSV, or a base64 .zip of repos."}}},"ImportReport":{"type":"object","properties":{"dryRun":{"type":"boolean"},"previewId":{"type":"string","format":"uuid"},"counts":{"type":"object","properties":{"new":{"type":"integer"},"duplicate":{"type":"integer"},"invalid":{"type":"integer"},"overLimit":{"type":"integer"},"overlapping":{"type":"integer"}}},"rows":{"type":"array","items":{"type":"object","properties":{"index":{"type":"integer"},"source":{"type":"string"},"name":{"type":"string"},"appId":{"type":"string"},"outcome":{"type":"string","enum":["new","duplicate","invalid","over-limit"]},"reason":{"type":"string"},"decision":{"type":"string"},"overlaps":{"type":"array","items":{"type":"string"}},"warnings":{"type":"array","items":{"type":"string"}}}}},"committed":{"type":"object","properties":{"created":{"type":"integer"},"updated":{"type":"integer"},"skipped":{"type":"integer"}}}}},"ImportJob":{"type":"object","properties":{"import":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["previewed","committed","undone"]},"source":{"type":"string"},"fileName":{"type":"string"},"format":{"type":"string"},"createdAt":{"type":"string"},"committedAt":{"type":"string"}}}}},"UndoResult":{"type":"object","properties":{"undone":{"type":"object","properties":{"removed":{"type":"integer"},"restored":{"type":"integer"}}}}},"Me":{"type":"object","properties":{"workspace":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"slug":{"type":"string"},"kind":{"type":"string"},"multiTenant":{"type":"boolean"}}},"plan":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"maxTenants":{"type":"integer"},"maxPteApps":{"type":"integer"},"requestsPerMinute":{"type":"integer"}}},"key":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"scopes":{"type":"array","items":{"type":"string"}},"role":{"type":"string"}}}}},"Problem":{"type":"object","description":"RFC 9457 problem details.","properties":{"type":{"type":"string"},"title":{"type":"string","example":"Tenant required"},"status":{"type":"integer"},"detail":{"type":"string"},"errors":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}}}}}}}}}