Skip to content
Talk to our solutions team

Meta API

Reference for the meta.svc HTTP surface. For concepts see the Meta block docs.

The API is mounted at the server root. /health and /ready are plain endpoints; everything else goes through the middleware chain: auth → conditional requests → compression (gzip/zstd).

Auth is a cascade — any one of: API key (X-Api-Key), certificate-derived JWT, or tenant JWT. Tenant headers X-Customer, X-Product, X-Env, X-Tenant populate context; X-Customer selects the customer whose repositories are visible. Per-repo JS access rules (access.read / access.write) and license entitlements apply after authentication.

Conditional requests: every file read returns a SHA-256 ETag; send If-None-Match to get 304s.

All read routes accept ?version=<name>&versionType=branch|tag.

MethodPathPurpose
GETfilesDirectory listing (?path=&depth=)
GETfile/{path…}Raw bytes + ETag
POSTbatch{"paths":[…]}{"files":[{path,content,hash,size,error}]}
POSTresolve{"path","have":{hash:path},"depth"} → server-side transitive import: resolution; returns only what the client is missing
GETmanifestMerkle tree of the repo → {root_hash, entries:[{path,hash,size,mod_time,is_dir}]} — cheap “did anything change?” sync
MethodPathPurpose
GETgit/refs, git/versionRefs / current HEAD
POSTgit/status, git/diff, git/fetch, git/pull, git/reset, git/stage, git/commit, git/pushPorcelain over the working tree (local repos, used by the authoring UI)
PATCHgit/patchApply a patch
PATCHgit/commitfileWrite + stage + commit in one call — body {"path","file"}
MethodPathPurpose
GETservice/{service}/configThe critical endpoint — merged envelope for one block (see below)
GETservice/{service}/datastoreMerged datastore definition (params: format, array, filepath, injectproduct, injectservices, onlyinjected)
GETservice/{service}/type/{type}[/file[/{path…}]]Type-mapped reads (being retired — prefer file/)

Read-only stat/read surface used by clients that mount meta as a filesystem:

GET fs/stat/{path…}{name,size,mode,mod_time,is_dir} · fs/readfile/{path…} · fs/readdir/{path…} · fs/exists/{path…} (never 404s).

GET categories, categories/all, category/{category…}, component/{name}[/full], component/{name}/files/{path…}, components[/path/{path…}].

Writes (authoring; repo must not be readonly)

Section titled “Writes (authoring; repo must not be readonly)”
MethodPathPurpose
PUT / DELETEfilesmkdir / rmdir
POSTfile/{path…}Upload (multipart field files)
POSTzip/{path…}Upload a zip, expanded in place
POST / PUTtype/{type}/file/{path…}Typed create / update
PUTtype/{type}/renameRename
StreamPurpose
watchFile-level change stream (snapshot-diff based)
eventsGit HEAD push: snapshot, repo-updated {repo,ref,hash,prevHash,ts}, ping every 30s

GET /product/{id}/service/{service}/config is called by every block on every poll. Response:

{
"load": true,
"service": { "…": "the block's folder config" },
"product": { "…": "product-level config" },
"data": { "…": "datastore definitions" },
"version": { "service": "", "product": "" },
"lastupdated": { "service": "", "product": "" }
}

load is true only when the timestamps differ from the caller’s servicelastupdated / productlastupdated query params — a cheap no-op poll otherwise.

Standalone service routes — /service/{name}/…

Section titled “Standalone service routes — /service/{name}/…”

Serves each block’s binary-embedded base definitions (GET /service/{name}/type/datastore, lastupdated). The server config’s services: block can override embeds for hotfixes.

MethodPathPurpose
GET/repositoriesRegistered repositories
GET/tenant-repositoriesPer-tenant on-demand repositories
GET/embedded-infoWhat products are compiled into this binary
POST/license-activate{"token"} → entitlement map
GET/license-statusCurrent entitlements
POST/license-deactivateDrop a license

POST git/fetch · GET git/zip · GET fileorfolderzip/{path…} · GET file/{path…} · PATCH paths (batch read) · GET components/{path…} · POST index · DELETE indexdocuments · DELETE index.

CodeMeaning
META_READONLYWrite against a read-only repo
META_NOT_LOCALGit porcelain against a non-local repo
META_MISSING_CUSTOMERNo X-Customer header and no JWT customer claim
”given version is not allowed”?version= outside the repo’s allowedversions
403Entitlement/access-rule denial

Meta accepts three credentials, tried in order, and the first that succeeds wins:

OrderCredential
1API key
2Certificate JWT
3Bearer token

A credential that is simply absent falls through to the next. The last is strict: a request that reaches it without a valid token is rejected.

Meta is served over a protocol layer rather than plain HTTP handlers, so authentication runs as middleware over the request metadata rather than per route. The effect is the same cascade every other service reaches through its HTTP guard.

CPET is populated from request metadata before authentication runs, so tenant resolution and credential validation are separate steps. A request can therefore resolve a tenant and still be rejected for credentials, which is why a tenancy failure and an auth failure look different.

StatusMeaning
400Request parse or validation failure
401No credential validated
403The tenant may not access this repository
404No such repository, bundle or artefact
500Unexpected server error