# Publish an API from a URL

`POST /v1/apis/publish/import`. Changed on Nov 2, 2026.

> This reference is the **skmtc/skmtc-api** API on Hub. Star it to see each revision, and add a pipeline to get its changes. https://skmtc.dev/skmtc/apis/skmtc-api

Publish an API from a schema document at a URL, as `importApi` does, with the `publish:schemas` scope. The document is fetched, validated, content-addressed and deduplicated. Re-importing a URL the owner already imported adds a revision to that API. Visibility is mandatory.

## Request

- Method: `POST`
- Path: `/v1/apis/publish/import`
- content-type: `application/json`

## Request body

Content type: `application/json`. Type: `object`.

Request body for publishing an API from a schema document at a URL.

- `url` (string, required): A URL to an OpenAPI / Swagger document - raw, a GitHub blob or a GitLab blob.
- `owner` (string): Handle of the account that will own the API - the caller, or an organization the caller is a member of. Defaults to the caller.
- `slug` (string): URL slug for the new API within the owner's namespace. Omit to derive one from the document's `info.title`. Ignored when the URL extends an API the owner has already imported.
- `visibility` (enum, required): Visibility for a newly created API.
  - One of: `public`, `private`

Example request:

```json
{
  "url": "string",
  "owner": "string",
  "slug": "string",
  "visibility": "public"
}
```

## Response

### 201

The request has succeeded and a new resource has been created as a result.

Content type: `application/json`. Type: `object`.

The outcome of importing a schema document into the catalog.

- `api` (object, required): The API the schema belongs to - newly created, or extended with a revision.
  - `id` (string, required): Stable row id, immutable across slug renames - what cross-environment tooling (the staging-sync link ledger) keys on.
  - `owner` (object, required): A user or organization account - the polymorphic resource owner.
    - `id` (string, required): Stable row id, immutable across handle renames - what cross-environment tooling (the staging-sync link ledger) keys on.
    - `handle` (string, required): Unique URL handle, e.g. `acme`.
    - `displayName` (string, required)
    - `type` (enum, required): Whether an account represents a single person or an organization.
      - One of: `user`, `org`
    - `avatarUrl` (string, required): An absolute URL.
    - `bio` (string, required)
    - `location` (string)
    - `emailDomain` (string): The company's email domain, e.g. `stripe.com` - org accounts only. A user with a verified email at this domain can claim the org.
    - `claimStatus` (enum): Claim state of the org - org accounts only.
      - One of: `claimed`, `unclaimed`
    - `joinedAt` (string, required): When the account was created.
    - `url` (string, required): API self-link for this account.
    - `htmlUrl` (string, required): Web UI link for this account.
  - `slug` (string, required)
  - `name` (string, required): Human-readable title, from the document's `info.title`.
  - `displayName` (string): The name to SHOW, when the title alone is ambiguous - present only when this owner has another live API with the same `name`, and only when something distinguishing can be derived. Azure publishes one management client as dozens of fragment files sharing an `info.title`, so 67 catalog entries read `SqlManagementClient`. They are not duplicates and must not be merged - each is a different fragment - so the qualifier names the fragment: `SqlManagementClient (DatabaseSchema)`. Absent means `name` is unambiguous, or that nothing could be derived (an upload carries no path). Render `displayName ?? name`.
  - `visibility` (enum, required): Whether a resource is world-readable or restricted to its owner.
    - One of: `public`, `private`
  - `description` (string, required): One-line summary.
  - `category` (enum): The API's primary subject category. Absent when unresolved or not yet classified.
    - One of: `ai-machine-learning`, `developer-tools`, `cloud-infrastructure`, `security-identity`, `data-analytics`, `payments-finance`, `commerce-retail`, `marketing-advertising`, `sales-customer-support`, `business-operations-hr`, `communications-messaging`, `productivity-collaboration`, `media-content`, `maps-location`, `travel-transport-logistics`, `healthcare-life-sciences`, `iot-devices`, `government-public-data`, `education-research`
  - `readme` (string, required): Rendered README / long-form documentation, Markdown.
  - `providerName` (string): Provider / publisher name, e.g. `Stripe, Inc.`.
  - `homepageUrl` (string): The provider's homepage.
  - `logoUrl` (string): A logo for the API or its provider.
  - `isVerified` (boolean, required): Whether the entry has been verified by skmtc-hub.
  - `license` (object): License of the latest version's schema document, when declared.
    - `name` (string, required): License name, e.g. `Apache 2.0`.
    - `spdxId` (string): SPDX identifier, e.g. `Apache-2.0` - OpenAPI 3.1 `info.license.identifier`.
    - `url` (string): Link to the license text.
  - `contact` (object): Contact of the latest revision's schema document, when declared.
    - `name` (string): Contact name, e.g. `Arcmira`.
    - `url` (string): The publisher's homepage, as declared.
    - `email` (string): Contact email address, as declared.
  - `externalDocs` (object): External docs of the latest revision's schema document, when declared.
    - `url` (string, required): Link to the documentation, as declared.
    - `description` (string): What the link is, e.g. `Official Arcmira API documentation`.
  - `sources` (array of ApiSource, required): Where this API's schema is fetched from.
    - `id` (string, required): Identifier of the source within its API.
    - `type` (enum, required): Where an API's schema document is fetched from.
      - One of: `direct_url`, `github`, `gitlab`, `stainless`, `google_discovery`, `upload`, `docs_derived`
    - `url` (string): Canonical fetch URL; absent for direct uploads. For a `docs_derived` source with an `extractor`, the origin of the documentation site.
    - `extractor` (enum): The extractor a refetch runs on `url`. Present only for a `docs_derived` source the hub builds itself.
      - One of: `docusaurus-openapi-docs`
    - `pages` (array of DocumentationPage): The documentation pages the latest document was written from. Present only when `type` is `docs_derived`.
      - `url` (string, required): An absolute URL.
      - `checkedAt` (string): When the page was last read.
      - `changedAt` (string): When the page's content last changed.
      - `contentHash` (string): SHA-256 of the content the page was read from.
      - `operationCount` (integer): How many operations of the document came from this page.
    - `requestMethod` (enum, required): The method every fetch of `url` sends. `GET` for an `upload` source, which has no `url`.
      - One of: `GET`, `POST`
    - `requestContentType` (string): The `content-type` of the body a `POST` sends. Absent for a `GET` and for a `POST` with no body. The body itself is not listed: it can hold project identifiers, and readers of a public API are anonymous.
    - `discoveredVia` (string): The discovery channel that surfaced this source - the harvester or aggregator it came from (e.g. `scalar`, `apis.guru`, `well-known-probe`). Absent for sources added by hand rather than through a seeding pipeline.
    - `isPrimary` (boolean, required): Whether this is the API's primary source.
    - `refetchEnabled` (boolean, required): Whether the source is refetched automatically (once a day) to pick up the latest version. Always `false` for uploads, and for a `docs_derived` source with no `extractor`.
    - `lastCheckedAt` (string): When the source was last checked for changes.
    - `lastStatus` (enum): Outcome of the most recent check.
      - One of: `updated`, `unchanged`, `error`
    - `lastError` (string): Error message of the most recent failed check.
    - `createdAt` (string, required)
  - `versions` (array of ApiVersion, required): Publisher-declared versions, newest first. Empty for the long tail - most APIs publish one unversioned stream of revisions.
    - `label` (string, required): The publisher's name for the version, verbatim: `v3`, `2026-03`, …
    - `stability` (enum, required): Lifecycle stage of a publisher-declared API version. `retired` versions keep their archived revision history.
      - One of: `ga`, `beta`, `preview`, `deprecated`, `retired`
    - `isDefault` (boolean, required): The version an API's page shows when none is selected.
    - `sortRank` (integer, required): Display order, newest first (labels mix styles and never sort lexically).
    - `releasedAt` (string): Publisher release date, when known.
    - `eolAt` (string): Publisher end-of-support date, when known.
  - `lastCheckedAt` (string): When skmtc-hub last checked any of this API's sources for updates.
  - `lastUpdatedAt` (string): When the schema last changed: the newest revision's publisher date where there is one, else when skmtc-hub observed the change. The coalesce is deliberate and is NOT the conflation `publishedAt` avoids. "Updated" is a claim about a change having happened, which the existence of a revision establishes either way - unlike "published at", which names who produced it and when.
  - `latestVersionRef` (string): Content ref of the most recent version - its URL identifier. Absent if the latest is a link-only version (no stored document).
  - `versionCount` (integer, required)
  - `retiredAt` (string): When skmtc-hub retired this API: its sources stopped serving and no move or version change was found, or every one of its versions was retired. Absent for a current API. A retired API stays listed and keeps its history.
  - `starCount` (integer, required): Number of accounts that have starred this API.
  - `consumerCount` (integer, required): Number of projects consuming this API.
  - `createdAt` (string, required)
  - `updatedAt` (string, required)
  - `url` (string, required): An absolute URL.
  - `htmlUrl` (string, required): An absolute URL.
  - `viewer` (object, required): The requesting viewer's effective permissions on this API.
    - `canRead` (boolean, required): May view the resource.
    - `canWrite` (boolean, required): May edit metadata and settings (the `writer` relation).
    - `canAdmin` (boolean, required): May manage collaborators and delete the resource (the `admin` relation).
- `revision` (object, required): The revision created - or the pre-existing one when `deduped` is true.
  - `publishedAt` (string): When the change became public, by the publisher's account: for a git source, the merge time of the pull request that brought the commit into the tracked branch, else the committer date. **Absent when no publisher timestamp was ever known**, which is most of the non-git catalog. It used to fall back to `retrievedAt`, which passed skmtc-hub's own observation time off as the publisher's and made "updated 3d ago" mean two different things. `docs/api-versioning-vocabulary.md` is explicit that `retrievedAt` is always labelled as ours; read that field for the observation, and treat its absence here as "the publisher never said". Ordering still coalesces the two - a revision with no publisher date sorts by when it was retrieved - but the ORDER is not the same claim as the date.
  - `isLatest` (boolean, required)
  - `hasDocument` (boolean, required): Whether skmtc-hub stores the version's document. `false` for link-only history versions of git-sourced APIs; the document fields below are absent for those.
  - `documentUrl` (string): Upstream link to the document at this version (git-sourced APIs).
  - `commit` (object): The commit this version came from - present for git-sourced APIs.
    - `sha` (string, required): The commit SHA.
    - `message` (string, required): First line of the commit message.
    - `date` (string, required): Commit (author) date.
    - `htmlUrl` (string): Link to the commit on the host, when known.
  - `linkedRepositoryRun` (object): The workflow run that added this revision with a linked repository token. Absent for a revision added any other way.
    - `repository` (string, required): The repository, as `owner/name`.
    - `sha` (string, required): The commit the run ran on.
    - `runId` (string, required): GitHub's id of the workflow run.
    - `runAttempt` (string, required): The attempt of the run, from 1.
    - `workflowRef` (string, required): The workflow file and ref, e.g. `owner/name/.github/workflows/publish.yml@refs/heads/main`.
    - `htmlUrl` (string, required): Link to the run attempt on GitHub.
  - `specType` (enum, required): The spec family of an ingested API document.
    - One of: `openapi`, `swagger`
  - `specVersion` (string)
  - `documentVersion` (string)
  - `license` (object): License declared by the document - absent for link-only versions.
    - `name` (string, required): License name, e.g. `Apache 2.0`.
    - `spdxId` (string): SPDX identifier, e.g. `Apache-2.0` - OpenAPI 3.1 `info.license.identifier`.
    - `url` (string): Link to the license text.
  - `contact` (object): `info.contact` declared by the document - absent for link-only versions.
    - `name` (string): Contact name, e.g. `Arcmira`.
    - `url` (string): The publisher's homepage, as declared.
    - `email` (string): Contact email address, as declared.
  - `externalDocs` (object): Root `externalDocs` declared by the document - absent for link-only versions.
    - `url` (string, required): Link to the documentation, as declared.
    - `description` (string): What the link is, e.g. `Official Arcmira API documentation`.
  - `retrievedAt` (string, required)
  - `sourceType` (enum, required): As on `ApiRevisionSummary`.
    - One of: `direct_url`, `github`, `gitlab`, `stainless`, `google_discovery`, `upload`, `docs_derived`
  - `derivedFrom` (object): As on `ApiRevisionSummary`.
    - `pages` (array of DocumentationPage, required): The documentation pages the document was written from.
      - `url` (string, required): An absolute URL.
      - `checkedAt` (string): When the page was last read.
      - `changedAt` (string): When the page's content last changed.
      - `contentHash` (string): SHA-256 of the content the page was read from.
      - `operationCount` (integer): How many operations of the document came from this page.
    - `snapshotAt` (string, required): When the pages were read.
    - `extractor` (string, required): The deterministic code that built the document, with its version where it has one, e.g. "docusaurus-openapi-docs embedded api data (docusaurus-plugin-openapi-docs 3.0.0-beta.10)". Never a model.
    - `repairs` (array of DerivedRepair): The fixes made to errors in the vendor's own data.
      - `repair` (string, required): The kind of fix, named by the extractor (e.g. `status-label`).
      - `at` (string, required): JSON pointer into the document, to what the fix changed.
  - `operationCount` (integer): Number of operations in the document - absent for link-only versions.
  - `schemaCount` (integer): Number of component schemas in the document - absent for link-only versions.
  - `serverUrl` (string): The document's first top-level server URL, as written: variables at their defaults, a relative URL left unresolved. Swagger 2 gives `schemes[0]://host` + `basePath`, or the bare `basePath` when the document has no `schemes` or no `host`. An empty string when the document declares no server. Absent when not derived yet, and for link-only versions.
  - `authSchemes` (array of AuthScheme): Auth mechanisms the document declares, sorted. Absent means not known (not derived yet, or a link-only version); it does not mean "none".
  - `documentFormat` (enum): Serialization of the stored document - absent for link-only versions.
    - One of: `json`, `yaml`
  - `byteSize` (integer): Size of the raw document, in bytes - absent for link-only versions.
  - `contentHash` (string): SHA-256 of the raw document bytes - absent for link-only versions.
  - `contentRef` (string): Short content ref (first 12 hex chars of `contentHash`) - the version's URL identifier (git-style). Absent for link-only versions, which have no bytes.
  - `externalRefs` (object): The other files the document's `$ref`s point at. Present only when the document has a `$ref` that does not start with `#`; the hub stores one file per revision, so docs, the deep index, new summaries and generation are off for this revision. Absent when there are none, when the document has not been scanned yet, and for link-only versions.
    - `fileCount` (integer, required): How many different files the `$ref`s point at.
    - `refCount` (integer, required): How many `$ref`s point at another file.
    - `files` (array of ExternalRefFile, required): Up to 10 of those files, most referenced first.
      - `path` (string, required): The file as the `$ref` writes it, without its `#` fragment.
      - `refs` (integer, required): How many `$ref`s point at this file.
  - `url` (string, required): An absolute URL.
  - `htmlUrl` (string, required): An absolute URL.
- `deduped` (boolean, required): True when identical content already existed; no new revision was created.
- `isNewApi` (boolean, required): True when the import created a brand-new API entry.
- `docsUrl` (string, required): The absolute URL of the API's docs page.
- `diffsPending` (boolean, required): True when the API's full revision history is still being archived + diffed in the background - a large GitHub history deferred to the diff-backfill queue so the import responds without waiting on minutes of container diffs. The returned `revision` (the newest) is complete; older revisions' diffs fill in shortly. False for single-revision imports, which diff inline.

Example response:

```json
{
  "api": {
    "id": "string",
    "owner": {
      "id": "string",
      "handle": "string",
      "displayName": "string",
      "type": "user",
      "avatarUrl": "string",
      "bio": "string",
      "location": "string",
      "emailDomain": "string",
      "claimStatus": "claimed",
      "joinedAt": "2026-10-30T12:00:00Z",
      "url": "string",
      "htmlUrl": "string"
    },
    "slug": "string",
    "name": "string",
    "displayName": "string",
    "visibility": "public",
    "description": "string",
    "category": "ai-machine-learning",
    "readme": "string",
    "providerName": "string",
    "homepageUrl": "string",
    "logoUrl": "string",
    "isVerified": true,
    "license": {
      "name": "string",
      "spdxId": "string",
      "url": "string"
    },
    "contact": {
      "name": "string",
      "url": "string",
      "email": "string"
    },
    "externalDocs": {
      "url": "string",
      "description": "string"
    },
    "sources": [
      {
        "id": "string",
        "type": "direct_url",
        "url": "string",
        "extractor": "docusaurus-openapi-docs",
        "pages": [
          {
            "url": "string",
            "checkedAt": "2026-10-30T12:00:00Z",
            "changedAt": "2026-10-30T12:00:00Z",
            "contentHash": "string",
            "operationCount": 0
          }
        ],
        "requestMethod": "GET",
        "requestContentType": "string",
        "discoveredVia": "string",
        "isPrimary": true,
        "refetchEnabled": true,
        "lastCheckedAt": "2026-10-30T12:00:00Z",
        "lastStatus": "updated",
        "lastError": "string",
        "createdAt": "2026-10-30T12:00:00Z"
      }
    ],
    "versions": [
      {
        "label": "string",
        "stability": "ga",
        "isDefault": true,
        "sortRank": 0,
        "releasedAt": "2026-10-30T12:00:00Z",
        "eolAt": "2026-10-30T12:00:00Z"
      }
    ],
    "lastCheckedAt": "2026-10-30T12:00:00Z",
    "lastUpdatedAt": "2026-10-30T12:00:00Z",
    "latestVersionRef": "string",
    "versionCount": 0,
    "retiredAt": "2026-10-30T12:00:00Z",
    "starCount": 0,
    "consumerCount": 0,
    "createdAt": "2026-10-30T12:00:00Z",
    "updatedAt": "2026-10-30T12:00:00Z",
    "url": "string",
    "htmlUrl": "string",
    "viewer": {
      "canRead": true,
      "canWrite": true,
      "canAdmin": true
    }
  },
  "revision": {
    "publishedAt": "2026-10-30T12:00:00Z",
    "isLatest": true,
    "hasDocument": true,
    "documentUrl": "string",
    "commit": {
      "sha": "string",
      "message": "string",
      "date": "2026-10-30T12:00:00Z",
      "htmlUrl": "string"
    },
    "linkedRepositoryRun": {
      "repository": "string",
      "sha": "string",
      "runId": "string",
      "runAttempt": "string",
      "workflowRef": "string",
      "htmlUrl": "string"
    },
    "specType": "openapi",
    "specVersion": "string",
    "documentVersion": "string",
    "license": {
      "name": "string",
      "spdxId": "string",
      "url": "string"
    },
    "contact": {
      "name": "string",
      "url": "string",
      "email": "string"
    },
    "externalDocs": {
      "url": "string",
      "description": "string"
    },
    "retrievedAt": "2026-10-30T12:00:00Z",
    "sourceType": "direct_url",
    "derivedFrom": {
      "pages": [
        {
          "url": "string",
          "checkedAt": "2026-10-30T12:00:00Z",
          "changedAt": "2026-10-30T12:00:00Z",
          "contentHash": "string",
          "operationCount": 0
        }
      ],
      "snapshotAt": "2026-10-30T12:00:00Z",
      "extractor": "string",
      "repairs": [
        {
          "repair": "string",
          "at": "string"
        }
      ]
    },
    "operationCount": 0,
    "schemaCount": 0,
    "serverUrl": "string",
    "authSchemes": [
      "apiKey"
    ],
    "documentFormat": "json",
    "byteSize": 0,
    "contentHash": "string",
    "contentRef": "string",
    "externalRefs": {
      "fileCount": 0,
      "refCount": 0,
      "files": [
        {
          "path": "string",
          "refs": 0
        }
      ]
    },
    "url": "string",
    "htmlUrl": "string"
  },
  "deduped": true,
  "isNewApi": true,
  "docsUrl": "string",
  "diffsPending": true
}
```

### 400

Binds a concrete HTTP `Status` to the shared `ApiError` body.

Content type: `application/json`. Type: `object`.

The uniform error envelope returned for every non-2xx response.

- `code` (enum, required): Machine-readable error category. Each value pairs with one HTTP status.
  - One of: `badRequest`, `unauthorized`, `forbidden`, `notFound`, `conflict`, `unprocessable`, `gone`, `payloadTooLarge`, `unsupportedMediaType`, `documentTooLarge`, `documentRefersToOtherFiles`, `webhookLimitReached`, `rateLimited`, `internal`, `unavailable`, `badGateway`, `notImplemented`
- `message` (string, required): Human-readable summary safe to surface to end users.
- `requestId` (string, required): Correlates the response with server logs for support.
- `details` (array of ErrorDetail)
  - `field` (string): Dotted path to the offending field, when applicable.
  - `message` (string, required): Human-readable explanation of this specific problem.

Example response:

```json
{
  "code": "badRequest",
  "message": "string",
  "requestId": "string",
  "details": [
    {
      "field": "string",
      "message": "string"
    }
  ]
}
```

### 401

Binds a concrete HTTP `Status` to the shared `ApiError` body.

Content type: `application/json`. Type: `object`.

The uniform error envelope returned for every non-2xx response.

- `code` (enum, required): Machine-readable error category. Each value pairs with one HTTP status.
  - One of: `badRequest`, `unauthorized`, `forbidden`, `notFound`, `conflict`, `unprocessable`, `gone`, `payloadTooLarge`, `unsupportedMediaType`, `documentTooLarge`, `documentRefersToOtherFiles`, `webhookLimitReached`, `rateLimited`, `internal`, `unavailable`, `badGateway`, `notImplemented`
- `message` (string, required): Human-readable summary safe to surface to end users.
- `requestId` (string, required): Correlates the response with server logs for support.
- `details` (array of ErrorDetail)
  - `field` (string): Dotted path to the offending field, when applicable.
  - `message` (string, required): Human-readable explanation of this specific problem.

Example response:

```json
{
  "code": "badRequest",
  "message": "string",
  "requestId": "string",
  "details": [
    {
      "field": "string",
      "message": "string"
    }
  ]
}
```

### 403

Binds a concrete HTTP `Status` to the shared `ApiError` body.

Content type: `application/json`. Type: `object`.

The uniform error envelope returned for every non-2xx response.

- `code` (enum, required): Machine-readable error category. Each value pairs with one HTTP status.
  - One of: `badRequest`, `unauthorized`, `forbidden`, `notFound`, `conflict`, `unprocessable`, `gone`, `payloadTooLarge`, `unsupportedMediaType`, `documentTooLarge`, `documentRefersToOtherFiles`, `webhookLimitReached`, `rateLimited`, `internal`, `unavailable`, `badGateway`, `notImplemented`
- `message` (string, required): Human-readable summary safe to surface to end users.
- `requestId` (string, required): Correlates the response with server logs for support.
- `details` (array of ErrorDetail)
  - `field` (string): Dotted path to the offending field, when applicable.
  - `message` (string, required): Human-readable explanation of this specific problem.

Example response:

```json
{
  "code": "badRequest",
  "message": "string",
  "requestId": "string",
  "details": [
    {
      "field": "string",
      "message": "string"
    }
  ]
}
```

### 422

Binds a concrete HTTP `Status` to the shared `ApiError` body.

Content type: `application/json`. Type: `object`.

The uniform error envelope returned for every non-2xx response.

- `code` (enum, required): Machine-readable error category. Each value pairs with one HTTP status.
  - One of: `badRequest`, `unauthorized`, `forbidden`, `notFound`, `conflict`, `unprocessable`, `gone`, `payloadTooLarge`, `unsupportedMediaType`, `documentTooLarge`, `documentRefersToOtherFiles`, `webhookLimitReached`, `rateLimited`, `internal`, `unavailable`, `badGateway`, `notImplemented`
- `message` (string, required): Human-readable summary safe to surface to end users.
- `requestId` (string, required): Correlates the response with server logs for support.
- `details` (array of ErrorDetail)
  - `field` (string): Dotted path to the offending field, when applicable.
  - `message` (string, required): Human-readable explanation of this specific problem.

Example response:

```json
{
  "code": "badRequest",
  "message": "string",
  "requestId": "string",
  "details": [
    {
      "field": "string",
      "message": "string"
    }
  ]
}
```

## Changes

### Nov 2, 2026 (`ed0217ce7303`)

- endpoint added

[Operation history](https://skmtc.dev/skmtc/apis/skmtc-api/changes/v1/apis/publish/import/post)
