OpenAPI · Version 1.0.0

The registry,
in detail.

Find the request you need. Explore discovery, package uploads, signed metadata, and reviewed assets.

Client trust and authentication requirements

Experimental Tabs-native registry discovery and TUF transport API. Catalog JSON, Digest, and ETag are not installation authority. Clients must independently pin a TUF root, verify current signed metadata and target length/hash, then validate the .tabsext archive. Public instances permit anonymous discovery/downloads. Private instances require a current allowlisted session or scoped read bearer token, including signed-metadata transport. Authentication never replaces signature verification.

One contract. Compatible clients.

Requests use your configured registry origin. The example origin is not a hosted service.

Download OpenAPI JSON Read the client integration guide
GET/v1/extensions

Search published extension heads

Returns at most one highest-semver signed, approved release per namespace/name. Results are discovery hints only.

Parameters

qquery · optional
Literal case-insensitive substring match across publisher namespace, package name, qualified identifier, display name, description, and listing keywords. SQL wildcard characters are treated literally.
Type and limits
{
  "type": "string",
  "maxLength": 100,
  "default": ""
}
limitquery · optional
Type and limits
{
  "type": "integer",
  "minimum": 1,
  "maximum": 100,
  "default": 30
}
cursorquery · optional
Opaque cursor from nextCursor; keep q, category, sort and limit unchanged. Legacy identity-only name cursors and submission-time newest cursors are rejected; restart without a cursor after upgrading.
Type and limits
{
  "type": "string",
  "maxLength": 16384
}
categoryquery · optional
Type and limits
{
  "type": "string",
  "pattern": "^[a-z][a-z0-9-]{1,39}$"
}
sortquery · optional
Defaults to relevance for a nonblank query, newest otherwise. Relevance ranks exact names, partial names, keywords, then descriptions, with identity tie-breakers. Newest orders by the exact release digest's first signed-publication time, descending, with unknown historical dates last and namespace/name tie-breakers. Name orders by trimmed, case-folded display name with namespace/name tie-breakers using PostgreSQL C collation; missing historical display names fall back to the package name.
Type and limits
{
  "enum": [
    "name",
    "newest",
    "relevance"
  ]
}

Responses

200
Search page
400
401
Current registry authentication required; reconnect after expiry or revocation.
GET/v1/extensions/{namespace}/{name}/overview

Get the highest signed stable release without loading history

Selects the highest published stable semantic version. If none exists, returns the highest published prerelease. This is presentation metadata, not installation authority or desktop compatibility resolution.

Parameters

namespacepath · required
Type and limits
{
  "$ref": "#/components/schemas/Segment"
}
namepath · required
Type and limits
{
  "$ref": "#/components/schemas/Segment"
}

Responses

200
Current published overview
401
Current registry authentication required on private instances.
404
No signed approved release is published.
GET/v1/extensions/{namespace}/{name}

List signed, approved versions of one extension

Parameters

namespacepath · required
Type and limits
{
  "$ref": "#/components/schemas/Segment"
}
namepath · required
Type and limits
{
  "$ref": "#/components/schemas/Segment"
}
cursorquery · optional
Opaque cursor from nextCursor.
Type and limits
{
  "type": "string",
  "maxLength": 512
}

Responses

200
Up to 100 versions in descending submission-time order
400
401
Current registry authentication required; reconnect after expiry or revocation.
404
GET/v1/extensions/{namespace}/{name}/versions/{version}

Get exact published release metadata

Parameters

namespacepath · required
Type and limits
{
  "$ref": "#/components/schemas/Segment"
}
namepath · required
Type and limits
{
  "$ref": "#/components/schemas/Segment"
}
versionpath · required
Type and limits
{
  "type": "string",
  "maxLength": 128
}

Responses

200
Exact release, not an installation authorization
401
Current registry authentication required; reconnect after expiry or revocation.
404
GET/v1/extensions/{namespace}/{name}/versions/{version}/download

Download an approved archive for inspection

The desktop installer uses the signed TUF target route instead. Digest and ETag alone do not authorize installation.

Parameters

namespacepath · required
Type and limits
{
  "$ref": "#/components/schemas/Segment"
}
namepath · required
Type and limits
{
  "$ref": "#/components/schemas/Segment"
}
versionpath · required
Type and limits
{
  "type": "string",
  "maxLength": 128
}

Responses

200
Exact archive bytes
401
Current registry authentication required; reconnect after expiry or revocation.
404
GET/v1/tuf/metadata/{file}

Fetch signed TUF metadata

Supports root.json, timestamp.json, snapshot.json, targets.json, and numbered root/snapshot/targets files. Clients verify signatures, freshness, rollback protection, and root rotation.

Parameters

filepath · required
Type and limits
{
  "type": "string"
}

Responses

200
Signed TUF JSON bytes
401
Current registry authentication required; reconnect after expiry or revocation.
404
GET/v1/tuf/targets/extensions/{namespace}/{name}/{version}.tabsext

Fetch a currently approved signed target

The filename may have a leading SHA-256 and dot for consistent-snapshot clients. The response is served only while the exact version remains approved and indexed by published signed targets.

Parameters

namespacepath · required
Type and limits
{
  "$ref": "#/components/schemas/Segment"
}
namepath · required
Type and limits
{
  "$ref": "#/components/schemas/Segment"
}
versionpath · required
Type and limits
{
  "type": "string",
  "maxLength": 193,
  "pattern": "^(?:[a-f0-9]{64}\\.)?[0-9A-Za-z.+-]{1,128}$"
}

Responses

200
Archive bytes; verify against the signed TUF target length and SHA-256
401
Current registry authentication required; reconnect after expiry or revocation.
404
GET/v1/tuf/events

Best-effort signed-publication wake-up hints

Optional server-sent events. An event named signed-metadata with data refresh only asks clients to refetch and verify signed metadata. It conveys no trust decision. Reconnect and continue periodic polling when unavailable.

No parameters declared.

Responses

200
Event stream
401
Current registry authentication required; reconnect after expiry or revocation.
503
GET/v1/registry

Protocol capabilities and instance limits; no package metadata

No parameters declared.

Responses

200
Registry capabilities
401
Current registry authentication required; reconnect after expiry or revocation.
POST/v1/publisher/{namespace}/{name}/versions

Submit immutable bytes for scanning and manual exact-digest review

Requires namespace-bound publish token or same-origin publisher session and CSRF header. Disabled instances return 503. Token membership is rechecked. Package identity must match URL.

Parameters

namespacepath · required
Type and limits
{
  "$ref": "#/components/schemas/Segment"
}
namepath · required
Type and limits
{
  "$ref": "#/components/schemas/Segment"
}
Request body contract
{
  "required": true,
  "content": {
    "application/octet-stream": {
      "schema": {
        "type": "string",
        "format": "binary",
        "description": "Validated .tabsext archive, at most 25 MiB"
      }
    }
  }
}

Responses

202
Queued package digest and version
400
Invalid archive or manifest
401
Authentication required
403
No publishing membership
409
Immutable version already exists
413
Package too large
503
Publishing disabled
POST/v1/publisher/upload

Submit immutable bytes for scanning and manual exact-digest review

Same submission pipeline as namespace upload. Server derives namespace/name from validated manifest. Requires same-origin publisher session and CSRF header; bearer tokens use the namespace-bound route.

No parameters declared.

Request body contract
{
  "required": true,
  "content": {
    "application/octet-stream": {
      "schema": {
        "type": "string",
        "format": "binary",
        "description": "Validated .tabsext archive, at most 25 MiB"
      }
    }
  }
}

Responses

202
Queued package digest and version
400
Invalid archive or manifest
401
Authentication required
403
No publishing membership
409
Immutable version already exists
413
Package too large
503
Publishing disabled
GET/v1/publisher/{namespace}/{name}/versions/{version}

Read own namespace submission and signed publication status

Requires publisher session or matching publish token. Status is queued/scanning/review/rejected/approved/revoked; approved with published=false awaits signing, approved with published=true is publicly downloadable.

Parameters

namespacepath · required
Type and limits
{
  "$ref": "#/components/schemas/Segment"
}
namepath · required
Type and limits
{
  "$ref": "#/components/schemas/Segment"
}
versionpath · required
Type and limits
{
  "type": "string",
  "maxLength": 128
}

Responses

200
Immutable digest, lifecycle status, review reason and published boolean
401
Publisher authentication required
404
No accessible submission
GET/v1/extensions/{namespace}/{name}/versions/{version}/assets/screenshot/{index}

Read a declared screenshot from an approved signed package

Zero-based manifest listing.screenshots index. PNG/JPEG/WebP only, magic-checked and bounded to 1 MiB. No arbitrary paths, SVG, remote images, or unreviewed versions. Requires package API minimum 1.7.0.

Parameters

namespacepath · required
Type and limits
{
  "$ref": "#/components/schemas/Segment"
}
namepath · required
Type and limits
{
  "$ref": "#/components/schemas/Segment"
}
versionpath · required
Type and limits
{
  "type": "string",
  "maxLength": 128
}
indexpath · required
Type and limits
{
  "type": "integer",
  "minimum": 0,
  "maximum": 5
}

Responses

200
Reviewed packaged raster; private/no-store/nosniff
401
Private read access required
404
No published release or declared screenshot
GET/v1/extensions/{namespace}/{name}/versions/{version}/assets/{kind}

Read bounded manifest-selected assets from an approved signed package

README is UTF-8 plain text, at most 512 KiB. Icons are magic-checked PNG/JPEG/WebP at most 1 MiB. No raw HTML/SVG or arbitrary package file access. Private instances require read access.

Parameters

namespacepath · required
Type and limits
{
  "$ref": "#/components/schemas/Segment"
}
namepath · required
Type and limits
{
  "$ref": "#/components/schemas/Segment"
}
versionpath · required
Type and limits
{
  "type": "string",
  "maxLength": 128
}
kindpath · required
Type and limits
{
  "enum": [
    "readme",
    "icon"
  ]
}

Responses

200
Reviewed packaged asset; no-store/nosniff
401
Private read access required
404
No published release or declared asset