Shipcatalog
GET/catalog/services/{service_id}/overview
Everything a service page shows, in one call
get_service_overview
catalog:read
A token needs thecatalog:readscope: Read the service catalog: services, their bindings, their owners and their overviewsGranted byread_api,write_api.Every operation this scope unlocks
Returns the service with the bound repositories you can see, the latest release and pipeline run across them, their open merge requests, what is deployed in each environment, the service's scorecard standing, its dependency counts and the technical debt in the paths it owns. Anyone who can see the declaring group may call it.
Parameters
Path
- service_idServiceId (string · uuid)The service's id
Responses
200The service, its repositories, its latest release and pipeline run, its open merge requests and its technical-debt rollupapplication/json
debtServiceDebt
- The ServiceDebt schema
- driftedinteger · int320–∞
- open_bugsinteger · int320–∞
rowsarray of AnchorDebtRow
- The AnchorDebtRow schema
- driftedinteger · int320–∞
- markersinteger · int320–∞
- open_bugsinteger · int320–∞
- open_storiesinteger · int320–∞
- pathRepoPath (string)
- totalinteger · int320–∞
- ownersarray of ActorSummaryoptionalWho the repository's CODEOWNERS file says owns this file. Absent when there is no CODEOWNERS file, or it names nobody for this path.
dependency_countsDependencyCountsHow many dependencies the service has and how many services depend on it, with how many of those you cannot see.
- The DependencyCounts schema
- hiddeninteger · int320–∞Dependencies left out, in either direction, because you cannot see the service at the far end.
- inboundinteger · int320–∞
- outboundinteger · int320–∞
- open_merge_requestsinteger · int320–∞
repositoriesarray of ServiceRepositoryRefThe repositories holding the service's code. Repositories you cannot see are left out.
- The ServiceRepositoryRef schema
- default_branchstring
- full_pathstring
- path_globsarray of string
- repository_idRepositoryId (string · uuid)
- visibilityVisibilitypublicinternalprivate
serviceService
- The Service schema
- created_atstring
- display_namestring
- group_idGroupId (string · uuid)The declaring group — where the entry lives for listing and quota purposes. Not necessarily the owner.
- kindServiceKindservicelibrarywebsitejobdatastoreapiml_modelotherWhat sort of thing a service is. The kind decides which scorecard checks apply: a
libraryhas no deployments, so a deployment check is not applicable to it rather than failing. For your own classifications, use annotations. - lifecycleServiceLifecycleexperimentalproductiondeprecatedretiredWhere a service is in its life.
- service_idServiceId (string · uuid)
- slugServiceSlug (string)
- sourceServiceSourceinferreddeclaredapiHow the catalog entry came to exist. Set by the platform, never accepted from a request. Any source other than
inferredmeans a person has vouched for the entry. - updated_atstring
- versioninteger · int64The service's revision, incremented on every change. Send it with an update to have the update refused with a
409if someone changed the service since you read it. - annotationsobjectoptional
api_specsarray of ApiSpecRefoptional
- The ApiSpecRef schema
- pathRepoPath (string)
- repository_idRepositoryId (string · uuid)
- spec_kindApiSpecKindopenapigrpcasyncapiWhich interface-description format a spec is written in.
created_byActorSummary or nulloptional
- The ActorSummary schema
- emailstring
- idstring
- usernamestring
- avatar_urlstring or nulloptional
- descriptionstring or nulloptional
- externalbooleanoptionalWhether the service is built outside gitmoap — a vendor SaaS, a service on another forge, a database provisioned elsewhere. The catalog records its name, owner and the dependencies on it, and nothing else. An external service has no repository paths.
linksarray of ServiceLinkoptional
- The ServiceLink schema
- link_typeServiceLinkTyperunbookdashboarddocschatotherWhat a service link points at.
othercovers anything the listed kinds do not. - urlHttpsUrl (string)
- orphaned_atstring or nulloptionalWhen the catalog file declaring this service stopped declaring it. The service is kept, with its history, rather than deleted.
providesarray of ProvidedArtifactoptional
- The ProvidedArtifact schema
- formatPackageRegistryFormatnpmcargopypiThe package ecosystem a registry speaks. A group has at most one registry per format.
- namePackageName (string)
repo_pathsarray of ServiceRepoPathoptional
- The ServiceRepoPath schema
- path_globstring
- path_prefixstringThe longest literal prefix of
path_glob, worked out by the platform. Read-only. - repository_idRepositoryId (string · uuid)
- is_excludebooleanoptionalWhether this glob removes its matches from the service's paths instead of adding them. It affects only its own service.
current_deploymentsarray of DeploymentSummaryoptionalWhat is currently deployed, one entry per environment the service is running in. Absent when it has never been deployed.
- The DeploymentSummary schema
- commit_shastring
- deployed_atstring
- deployment_idDeploymentId (string · uuid)
- environment_idEnvironmentId (string · uuid)
- repository_idRepositoryId (string · uuid)
- service_idServiceId (string · uuid)
- statusDeploymentStatusrequestedawaiting_approvalrejectedrunningsucceededfailedcancelledsupersededskippedWhere a deployment is in its life. It starts
requested; waits asawaiting_approvalwhen the environment needs approval, endingrejectedif refused; thenrunning, endingsucceeded,failedorcancelled.skippedmeans another deploy held the environment and its policy is to skip. A successful deployment becomessupersededwhen a later one replaces it. - pipeline_run_idPipelineRunId (string · uuid) or nulloptional
latest_pipeline_runPipelineRunSummary or nulloptional
- The PipelineRunSummary schema
- pipeline_namestring
- pipeline_run_idPipelineRunId (string · uuid)
- repo_idRepositoryId (string · uuid)
- started_atstring
- statusPipelineStatusrunningsucceededsucceeded_with_warningsfailedtimed_outcancelledPer-
PipelineRunstatus. triggerTriggerContext
- The TriggerContext schema
- repo_idRepositoryId (string · uuid)
- repo_pathstring
- before_shastring or nulloptionalThe commit the ref pointed at before the push — what a
pathsfilter compares against. On a run started by hand, the commit its starter named to compare from, if any. - branchstring or nulloptional
- buildMrBuildTargetmerge_resultsourceor nulloptionalWhich commit a merge-request-triggered run built.
- commit_shastring or nulloptional
- depthinteger · int32optional0–∞How many pushes made by pipeline runs led to this run, one after another;
0when no pipeline's push started it. - every_stepbooleanoptionalEvery step runs, whatever its path filter says — asked for by whoever started the run.
- extraobjectoptionalAdditional fields supplied by whatever started the run, passed along without being interpreted.
- kindTriggerKindpushmerge_requesttagschedulemanualoptionalWhat started this run.
- mr_idMergeRequestId (integer · int64) or nulloptional
- paramsobjectoptionalThe values a person supplied when starting the run, keyed by the parameter names the pipeline's manual trigger declares.
- ref_namestring or nulloptionalThe full ref (e.g.
refs/tags/v1.2.0). Set for runs a tag started, whichbranchcannot describe. - root_group_idGroupId (string · uuid) or nulloptionalThe organisation this run belongs to — the root group of the repository it was triggered for. Recorded when the run starts and never recalculated, so a repository moved to a different organisation part-way through a run keeps the artifacts, logs and cache it has already produced. Absent on runs that started before runs recorded this.
- schedule_stemstring or nulloptionalWhich scheduled trigger fired, when
kindisschedule. - source_shastring or nulloptionalThe source-branch commit this run tested: a merge request's source head for a merge-request run, whichever commit it built, and the commit itself for a push or manual run. Set by the platform; absent on a run whose graph the caller supplied, which never counts toward a merge request's pipelines.
- target_branchstring or nulloptionalThe merge request's target branch.
- target_shastring or nulloptionalThe target branch's tip this merge-request run was tested against. Once the target branch moves on, the merge check reports a merge-result run as out of date.
- triggered_byActorSummaryoptionalWho started the run, set by the platform from the authenticated caller; a value supplied in a request is ignored.
- trustTriggerTrusttrusteduntrustedoptionalWhether the code being built is trusted with the repository's connections and secrets. Set by the platform when the run starts, whatever a request says.
- trust_reasonTrustReason or nulloptionalWhy the run has the trust it has: who wrote the code, a person's merge or approval, or the organization's AI configuration. Absent on runs that started before this was recorded.
- finished_atstring or nulloptional
- pipeline_idPipelineId (string · uuid) or nulloptionalThe pipeline definition this run was started from. Absent when that definition has since been deleted;
pipeline_namestill names what ran. - re_run_ofPipelineRunId (string · uuid) or nulloptional
stagesarray of StageRollupoptionalPer-stage counts of how many steps are in each status, in execution order — enough to draw the run's shape in a list. Empty for older runs recorded before these counts existed.
- The StageRollup schema
- barrier_passedbooleanWhether every step in the stage has finished.
- countsNodeStatusCounts
- stage_idStageId (string)
- stage_indexinteger · int320–∞
- tolerated_failuresinteger · int32optional0–∞How many of the stage's failed or timed-out steps were allowed to fail, so they degrade the run rather than fail it. Left out when zero.
latest_releaseRelease or nulloptional
- The Release schema
authorActorSummaryWho created the release.
- The ActorSummary schema
- emailstring
- idstring
- usernamestring
- avatar_urlstring or nulloptional
- commit_shaCommitHash (string)The commit the tag pointed to when the release was created.
- created_atstring
- nameReleaseName (string)
- repository_idRepositoryId (string · uuid)
- tag_nameTagName (string)
- updated_atstring
assetsarray of ReleaseAssetoptionalThe release's files. Included when a single release is fetched.
- The ReleaseAsset schema
- asset_idReleaseAssetId (string · uuid)
- content_typestring
- created_atstring
- nameAssetName (string)
- repository_idRepositoryId (string · uuid)
- sizeinteger · int640–∞
- stateAssetStateuploadingavailableWhether a release file has been uploaded:
uploading(an upload URL was issued, but the upload has not been confirmed yet) oravailable. - tag_nameTagName (string)
- updated_atstring
- download_urlstring or nulloptionalWhere to download the file.
- bodyReleaseBody (string) or nulloptional
- draftbooleanoptionalWhether the release is an unpublished draft, visible only to people with Developer access or above.
- prereleasebooleanoptionalWhether the release is marked as a pre-release. A pre-release is never returned as the latest release.
- published_atstring or nulloptionalSet when the release leaves draft.
- tarball_urlstring or nulloptionalWhere to download the tagged source as a
.tar.gzarchive. - versioninteger · int64optional0–∞Increases with every change. Send it with an update so that a change made since you read the release is not overwritten.
- zipball_urlstring or nulloptionalWhere to download the tagged source as a
.ziparchive.
scorecardsarray of ServiceScorecardSummaryoptionalEvery scorecard that applies to this service, with the level it reaches and its check counts. Absent when no scorecard applies.
- The ServiceScorecardSummary schema
countsCheckStateCounts
- The CheckStateCounts schema
- expiredinteger · int320–∞
- failinginteger · int320–∞
- not_applicableinteger · int320–∞
- passinginteger · int320–∞
- staleinteger · int320–∞
- unknowninteger · int320–∞
- namestring
- scorecard_idScorecardId (string · uuid)
- slugScorecardSlug (string)
- levelstring or nulloptionalThe highest level every required check satisfies, or
nullwhen the scorecard has no levels or the service reaches none of them.
200 exampleSynthesized example
{
"debt": {
"drifted": 64,
"open_bugs": 65,
"rows": [
{
"drifted": 14,
"markers": 11,
"open_bugs": 68,
"open_stories": 81,
"path": "path-915f",
"total": 5
},
{
"drifted": 24,
"markers": 40,
"open_bugs": 85,
"open_stories": 1,
"path": "path-b630",
"total": 4
}
]
},
"dependency_counts": {
"hidden": 58,
"inbound": 52,
"outbound": 48
},
"open_merge_requests": 79,
"repositories": [
{
"default_branch": "main",
"full_path": "acme/payments-api",
"path_globs": [],
"repository_id": "5b0e7c2a-9d14-4e8b-a6f1-2c3d4e5f6a70",
"visibility": "public"
}
],
"service": {
"created_at": "2026-10-12T05:05:19Z",
"display_name": "Tomás Reyes",
"group_id": "4c1d8e2f-6a3b-4f90-b7c5-1e2d3c4b5a69",
"kind": "service",
"lifecycle": "experimental",
"service_id": "3732fe38-5427-41d1-a445-ba2421e22df8",
"slug": "slug-bedd",
"source": "inferred",
"updated_at": "2026-10-11T21:46:49Z",
"version": 36,
"annotations": {},
"api_specs": [
{
"path": "path-fdad",
"repository_id": "5b0e7c2a-9d14-4e8b-a6f1-2c3d4e5f6a70",
"spec_kind": "openapi"
}
],
"created_by": {
"email": "lin@acme.example",
"id": "id-fffb",
"username": "tomas",
"avatar_url": "https://gitmoap.example/acme/3fb8a882"
},
"description": "Renders each region as density contours of its operations.",
"external": false,
"links": [
{
"link_type": "runbook",
"url": "https://gitmoap.example/acme/a5fe81b6"
},
{
"link_type": "runbook",
"url": "https://gitmoap.example/acme/1caa2562"
}
],
"orphaned_at": "2026-10-15T14:32:38Z",
"owner": {
"group_id": "4c1d8e2f-6a3b-4f90-b7c5-1e2d3c4b5a69",
"kind": "group",
"full_path": "acme/payments-api"
},
"provides": [
{
"format": "npm",
"name": "payments-api"
}
],
"repo_paths": [
{
"path_glob": "path-glob-a1e6",
"path_prefix": "path-prefix-3c0d",
"repository_id": "5b0e7c2a-9d14-4e8b-a6f1-2c3d4e5f6a70"
},
{
"path_glob": "path-glob-4ae4",
"path_prefix": "path-prefix-ac5e",
"repository_id": "5b0e7c2a-9d14-4e8b-a6f1-2c3d4e5f6a70"
}
]
},
"current_deployments": [
{
"commit_sha": "f913d458f7ab00a4318a99ec875d94dd60dacbff",
"deployed_at": "2026-10-08T12:22:17Z",
"deployment_id": "0aa1b40f-3d23-4d3e-8c5d-d012ab879e1b",
"environment_id": "2d380447-d8bd-499c-b798-da3ebe350e41",
"repository_id": "5b0e7c2a-9d14-4e8b-a6f1-2c3d4e5f6a70",
"service_id": "998bf097-4e2a-49b4-b33c-eabbeb045c86",
"status": "requested"
}
],
"latest_pipeline_run": {
"pipeline_name": "payments-api",
"pipeline_run_id": "9e2b7c41-3d5a-4f8e-b1c2-7a6d5e4f3c2b",
"repo_id": "5b0e7c2a-9d14-4e8b-a6f1-2c3d4e5f6a70",
"started_at": "2026-10-14T01:17:52Z",
"status": "running",
"trigger": {
"repo_id": "5b0e7c2a-9d14-4e8b-a6f1-2c3d4e5f6a70",
"repo_path": "repo-path-627d",
"before_sha": "c212027b0d3c90c815a814db5673c3290f26ac4f",
"branch": "fix/payload-build-pin",
"build": "merge_result",
"commit_sha": "65f44131ae2da8ee7749a0d4f690e3a5293116fe",
"depth": 3,
"every_step": false,
"extra": {},
"kind": "push",
"mr_id": 42,
"params": {},
"ref_name": "payments-api",
"root_group_id": "4c1d8e2f-6a3b-4f90-b7c5-1e2d3c4b5a69",
"schedule_stem": "schedule-stem-7c05",
"source_sha": "59cc7d6414ae85af3f0232c75d574027f119889f",
"target_branch": "main",
"target_sha": "ed04c307b30a60ab74d4e54eb0f7ee7829c0af51",
"triggered_by": {
"email": "mara@acme.example",
"id": "id-b018",
"username": "tomas",
"avatar_url": "https://gitmoap.example/acme/385ff0bd"
},
"trust": "trusted",
"trust_reason": {
"kind": "written_by_people"
}
},
"finished_at": "2026-10-15T01:36:43Z",
"pipeline_id": "12c4cb6c-0508-4e44-90f5-6acf982c54a4",
"re_run_of": "9e2b7c41-3d5a-4f8e-b1c2-7a6d5e4f3c2b",
"stages": [
{
"barrier_passed": false,
"counts": {},
"stage_id": "32e46e36-3b1a-47d7-aaf2-a199948f5198",
"stage_index": 3
}
]
},
"latest_release": {
"author": {
"email": "mara@acme.example",
"id": "id-054b",
"username": "mara",
"avatar_url": "https://gitmoap.example/acme/2015a115"
},
"commit_sha": "4888dd86d7bcd3933fe43a3a1c3394e424b96b15",
"created_at": "2026-10-14T20:08:27Z",
"name": "payments-api",
"repository_id": "5b0e7c2a-9d14-4e8b-a6f1-2c3d4e5f6a70",
"tag_name": "payments-api",
"updated_at": "2026-10-12T07:13:41Z",
"assets": [
{
"asset_id": "09f28b62-3d07-44d8-87aa-13cb63ec96e8",
"content_type": "content-type-c7b5",
"created_at": "2026-10-08T14:01:08Z",
"name": "payments-api",
"repository_id": "5b0e7c2a-9d14-4e8b-a6f1-2c3d4e5f6a70",
"size": 1,
"state": "uploading",
"tag_name": "payments-api",
"updated_at": "2026-10-16T15:37:50Z",
"uploader": {
"email": "lin@acme.example",
"id": "id-5537",
"username": "mara"
}
},
{
"asset_id": "7aa115f9-60b7-4e4c-bde5-4bd9fc1bd77e",
"content_type": "content-type-c254",
"created_at": "2026-10-15T12:58:51Z",
"name": "payments-api",
"repository_id": "5b0e7c2a-9d14-4e8b-a6f1-2c3d4e5f6a70",
"size": 7,
"state": "uploading",
"tag_name": "payments-api",
"updated_at": "2026-10-08T12:37:23Z",
"uploader": {
"email": "lin@acme.example",
"id": "id-6594",
"username": "tomas"
}
}
],
"body": "Renders each region as density contours of its operations.",
"draft": false,
"prerelease": false,
"published_at": "2026-10-15T23:23:06Z",
"tarball_url": "https://gitmoap.example/acme/17e90d5b",
"version": 88,
"zipball_url": "https://gitmoap.example/acme/2afa564f"
},
"owner": {
"group_id": "4c1d8e2f-6a3b-4f90-b7c5-1e2d3c4b5a69",
"kind": "group",
"full_path": "acme/payments-api"
},
"scorecards": [
{
"counts": {
"expired": 80,
"failing": 74,
"not_applicable": 64,
"passing": 81,
"stale": 85,
"unknown": 37
},
"name": "payments-api",
"scorecard_id": "771f8a03-69da-4a9a-9280-5cf7a85c1c98",
"slug": "slug-a1fa"
},
{
"counts": {
"expired": 86,
"failing": 51,
"not_applicable": 48,
"passing": 59,
"stale": 77,
"unknown": 32
},
"name": "payments-api",
"scorecard_id": "a62a9c89-3829-4a97-aeb0-08699b3cfc33",
"slug": "slug-5022"
}
]
}
400Bad request — a path parameter is not a well-formed value of its typeapplication/json
Error codes
- BAD_REQUESTThe request is malformed: a parameter or a body field is not a well-formed value of its type
errorErrorBody
- The ErrorBody schema
- codestringThe coarse category, tied to the status:
NOT_FOUND,CONFLICT,INSUFFICIENT_SCOPE. Every error has one; the API reference's error catalogue lists them all. - messagestringWhat went wrong, for a person. Written to be read, not parsed: match on
reasonorcode. - fieldstring or nulloptionalOn a
400that refused one field's value, the field, as its JSON path:email,items[0].name. Put the message under that input. Absent on every other error. - reasonstring or nulloptionalThe specific code, when the error has one:
LAST_ORGANIZATION_OWNER,BRANCH_PROTECTED. The message starts with it too. Match on this when it is present, and oncodeotherwise. - required_scopestring or nulloptionalThe scope the access token was missing, on
INSUFFICIENT_SCOPE. - violationsanyoptionalPresent on the structured-validation errors (
PROVIDER_VALIDATION_FAILEDper-node,PIPELINE_VALIDATION_FAILEDDAG): a JSON array of the offending elements, so a caller can fix every one in a single round-trip. Absent (omitted) on every other error.
400 exampleSynthesized example
{
"error": {
"code": "code-9a2c",
"message": "Label every synthesized example"
}
}
401Unauthenticated — no credential, or an invalid oneapplication/json
Error codes
- UNAUTHORIZEDNo credential was sent, or the one sent is invalid, expired or revoked
errorErrorBody
- The ErrorBody schema
- codestringThe coarse category, tied to the status:
NOT_FOUND,CONFLICT,INSUFFICIENT_SCOPE. Every error has one; the API reference's error catalogue lists them all. - messagestringWhat went wrong, for a person. Written to be read, not parsed: match on
reasonorcode. - fieldstring or nulloptionalOn a
400that refused one field's value, the field, as its JSON path:email,items[0].name. Put the message under that input. Absent on every other error. - reasonstring or nulloptionalThe specific code, when the error has one:
LAST_ORGANIZATION_OWNER,BRANCH_PROTECTED. The message starts with it too. Match on this when it is present, and oncodeotherwise. - required_scopestring or nulloptionalThe scope the access token was missing, on
INSUFFICIENT_SCOPE. - violationsanyoptionalPresent on the structured-validation errors (
PROVIDER_VALIDATION_FAILEDper-node,PIPELINE_VALIDATION_FAILEDDAG): a JSON array of the offending elements, so a caller can fix every one in a single round-trip. Absent (omitted) on every other error.
401 exampleSynthesized example
{
"error": {
"code": "code-2cd5",
"message": "Label every synthesized example"
}
}
403Forbidden — the caller's access level or token scope is insufficientapplication/json
Error codes
- FORBIDDENYou are signed in but may not do this here;
reasonnames the permission or the rule that refused it - INSUFFICIENT_SCOPEThe access token lacks the scope this operation needs;
required_scopenames it - PERMISSION_REQUIREDYou need a permission you do not hold here; the message names it
errorErrorBody
- The ErrorBody schema
- codestringThe coarse category, tied to the status:
NOT_FOUND,CONFLICT,INSUFFICIENT_SCOPE. Every error has one; the API reference's error catalogue lists them all. - messagestringWhat went wrong, for a person. Written to be read, not parsed: match on
reasonorcode. - fieldstring or nulloptionalOn a
400that refused one field's value, the field, as its JSON path:email,items[0].name. Put the message under that input. Absent on every other error. - reasonstring or nulloptionalThe specific code, when the error has one:
LAST_ORGANIZATION_OWNER,BRANCH_PROTECTED. The message starts with it too. Match on this when it is present, and oncodeotherwise. - required_scopestring or nulloptionalThe scope the access token was missing, on
INSUFFICIENT_SCOPE. - violationsanyoptionalPresent on the structured-validation errors (
PROVIDER_VALIDATION_FAILEDper-node,PIPELINE_VALIDATION_FAILEDDAG): a JSON array of the offending elements, so a caller can fix every one in a single round-trip. Absent (omitted) on every other error.
403 exampleSynthesized example
{
"error": {
"code": "code-8049",
"message": "Pin a page's payload to the build that rendered it"
}
}
404No such service, or it is not visible to the callerapplication/json
Error codes
- NOT_FOUNDThe resource does not exist — or exists and you cannot see it: a private resource you have no access to answers exactly as an absent one does
errorErrorBody
- The ErrorBody schema
- codestringThe coarse category, tied to the status:
NOT_FOUND,CONFLICT,INSUFFICIENT_SCOPE. Every error has one; the API reference's error catalogue lists them all. - messagestringWhat went wrong, for a person. Written to be read, not parsed: match on
reasonorcode. - fieldstring or nulloptionalOn a
400that refused one field's value, the field, as its JSON path:email,items[0].name. Put the message under that input. Absent on every other error. - reasonstring or nulloptionalThe specific code, when the error has one:
LAST_ORGANIZATION_OWNER,BRANCH_PROTECTED. The message starts with it too. Match on this when it is present, and oncodeotherwise. - required_scopestring or nulloptionalThe scope the access token was missing, on
INSUFFICIENT_SCOPE. - violationsanyoptionalPresent on the structured-validation errors (
PROVIDER_VALIDATION_FAILEDper-node,PIPELINE_VALIDATION_FAILEDDAG): a JSON array of the offending elements, so a caller can fix every one in a single round-trip. Absent (omitted) on every other error.
404 exampleSynthesized example
{
"error": {
"code": "code-c503",
"message": "Pin a page's payload to the build that rendered it"
}
}
CLI
gitmoap catalog get-service-overview
- --service-ididThe service's id