Skip to main content

Connectors

Route/ade/dashboard/connectors

A connector points Apiome at somewhere your APIs already live — an API gateway, a schema registry, a URL — and keeps the Catalog in step with it. Each API the connector finds becomes a catalog item, and each new revision of that API becomes a new revision of the item.

Connectors are refreshed by the same engine as Repositories: one cadence, one quota, one audit trail. Go to Bring in → Connectors to see them.

Connectors: one connector with its kind, health, last run and schedule, a Sync now button, and Add connector in the headerConnectors: one connector with its kind, health, last run and schedule, a Sync now button, and Add connector in the header
Route/ade/dashboard/connectors

The list shows each connector's kind, Health (active, failing or paused), Last run and Schedule. Switch between List and Grid. Sync now runs one sync and reports what it imported. Govern → Shadow APIs shows what your connectors found that the catalog does not describe.

note

Each kind needs a source before it can sync. The two Kong kinds, AWS API Gateway, Azure API Management, Apigee, the schema registry and the MCP registry sync today; the URL source follows. A kind your deployment cannot sync yet is shown as Not available on this deployment when you add a connector.

Source kinds​

KindWhere the APIs come from
kong-konnectKong Konnect control planes
kong-adminA Kong Gateway Admin API
aws-apigatewayAmazon API Gateway, by region and account
azure-apimAzure API Management, by resource group
apigeeApigee, by organization and environment
urlA specification published at a URL
schema-registryA Confluent, Karapace or Apicurio schema registry. Its subjects become schema subjects with their version history
mcp-registryAn MCP registry: the official registry, Azure API Center, a Kong registry or another Apiome workspace. Its servers become MCP servers, not catalog items
registryA registry of artifacts, crawled by protocol: an A2A agent registry, a CNCF xRegistry, or a FHIR server's /metadata. Every artifact becomes its own catalog item. See Registry crawl

A connector has a name, an optional base URL (the control-plane or admin address), a scope (the kind's coordinates: control-plane ids, region and account, resource group, org and environment), a refresh interval and a conflict policy (hold-for-review, overwrite or new-branch, the same choices as a repository).

Add a connector​

  1. Go to Bring in → Connectors and click Add connector.

  2. Kind: choose where your APIs live, for example Kong Gateway (Admin API), and click Continue.

  3. Credentials: enter what the kind needs, such as an admin token. Apiome never shows a stored credential again.

  4. Scope: enter the Base URL when the kind has one, and the kind's coordinates (workspace, region, organization and environments, …). A required field you leave empty is named under the form, and Continue stays disabled until it is filled.

  5. Dry run: click Run the dry run. Apiome asks the provider once what the connector would sync and shows how many APIs it found, with the first few by name. Nothing is stored yet.

    Add a connector, Dry run step: 3 APIs found, with the first one listed by name and environment, and Continue enabledAdd a connector, Dry run step: 3 APIs found, with the first one listed by name and environment, and Continue enabled
    Route/ade/dashboard/connectors/new

    If the provider refuses, the dry run shows its reason, for example The dry run failed (auth, HTTP 401): invalid credentials, and you cannot continue until a dry run succeeds. Going back and changing any credential or scope field clears the dry run, so the one you save is always of the current settings.

  6. Schedule: give the connector a Name, choose how often it syncs under Refresh (or keep the deployment default), and choose what happens When a synced API was edited in Apiome: the same conflict policies as a repository. Click Save connector.

Apiome registers the connector, stores its credential and opens the connector's page.

You need the Imports permission: View to read connectors, Create to add one (and run a dry run), Edit to change, sync or set credentials, and Delete to remove one.

A connector's page​

The header shows the connector's health, its last run and whether a credential is stored. Sync now runs a sync; the tabs below fill in as soon as it finishes, without a reload.

A connector's Items tab: two APIs, one imported with an Open in the catalog link, one discovered and not imported yetA connector's Items tab: two APIs, one imported with an Open in the catalog link, one discovered and not imported yet
Route/ade/dashboard/connectors/c1
  • Items lists every API the connector has seen, with its environment, revision and status. Open in the catalog opens the catalog item an imported API became.

  • Environments lists one gateway config per environment the connector's syncs found, with how many APIs it serves and its auth and rate limits.

  • Runs lists this connector's runs, newest first, with their outcome, for example Imported 2 of 3 or Failed: auth (HTTP 401).

    A connector's Runs tab: a Connector run that imported 2 of 3, next to a Git refresh, each with a source badgeA connector's Runs tab: a Connector run that imported 2 of 3, next to a Git refresh, each with a source badge
    Route/ade/dashboard/connectors/c1
  • Settings changes the name, base URL, scope, refresh and conflict policy, replaces the credential, pauses or resumes scheduled syncs, and deletes the connector. Deleting stops its syncs and destroys its credential; the catalog items it imported stay.

The same runs table, unfiltered, is at the bottom of Bring in → Repositories as Recent runs. Git refreshes and connector runs are listed together, newest first, each with a Git or Connector badge.

With the CLI​

apiome connectors add --kind kong-admin --name "Prod gateway" \
--base-url https://kong-admin.example.com --scope '{"workspace": "default"}' \
--credentials-file kong-token.json
apiome connectors list
apiome connectors sync <id> --wait
apiome connectors items <id> --status imported
apiome connectors runs <id>
apiome connectors remove <id> --yes

add runs the dry run first and saves nothing if it fails. The credential comes from a JSON file (or - for standard input), never from the command line. sync --wait exits 0 when the run succeeded and 7 when it failed, so a pipeline can gate on it. Every command takes --format json. See the apiome connectors reference.

Register with the API​

  1. Check it (optional): POST /v1/tenants/{tenant}/connectors/dry-run with the same kind, baseUrl and scope you will create, plus the credentials. It returns itemCount, a sample of up to 20 items and any findings, and stores nothing. A refused dry run is a 422 with detail.code connector-check-failed and the provider's reason in detail.message.

  2. Create it: POST /v1/tenants/{tenant}/connectors with kind, name and, when the kind has one, baseUrl and scope. For example:

    {
    "kind": "kong-admin",
    "name": "Prod gateway",
    "baseUrl": "https://kong-admin.example.com",
    "scope": { "workspace": "default" },
    "refreshIntervalSeconds": 3600
    }
  3. Store its credential: PUT /v1/tenants/{tenant}/connectors/{id}/credentials with the fields the kind needs, for example {"credentials": {"token": "…"}}.

  4. Sync it: POST /v1/tenants/{tenant}/connectors/{id}/sync. The response is the finished run.

Credentials​

A credential is write-only. Apiome encrypts it as soon as it arrives. No response, log line or audit entry ever contains it, and the API only reports hasCredentials and the names of the stored fields. To change a credential, send the whole credential again; there is no partial edit. Deleting a connector destroys its credential.

Secrets do not belong in scope: a scope key that looks like one (token, password, apiKey, clientSecret, …) is refused.

An AWS API Gateway connector stores no credential at all: Apiome assumes a role in your account instead. Sending it one is refused with connector-credentials-refused.

An Azure API Management connector stores its application's client secret as {"credentials": {"clientSecret": "…"}}, or nothing at all when it uses a federated credential.

An Apigee connector stores a Google service-account key, or a workload identity federation configuration, as {"credentials": {"credentialJson": "…"}}.

A schema registry connector stores {"credentials": {"username": "…", "password": "…"}} for basic auth, {"credentials": {"token": "…"}} for a bearer token, or nothing for an open registry.

Base URLs and private networks​

Apiome calls the base URL itself, so it must be http or https, carry no user:password@, and resolve only to public addresses. A URL that resolves to a private, loopback or link-local address is refused with the reason private-address. For a gateway that only listens inside your network, an operator can allow its range with APIOME_CONNECTOR_PRIVATE_NETWORK_ALLOWLIST, a comma-separated list of CIDRs such as 10.20.0.0/16.

What a sync does​

Each sync is a run:

  1. It lists the connector's inventory: every API the source can see.
  2. It records what it saw under GET …/connectors/{id}/items, with each API's environment, hosts, base path, remote revision and, for gateways, its deployment details.
  3. It skips what has not changed. An API whose remote revision or update time is not newer than the last import is not fetched.
  4. It fetches and imports the rest into the catalog. The document always becomes a catalog item, even when it is OpenAPI. To make it a Project, convert it.
  5. It writes a change report whenever it adds a revision to an item that already had one, so you can see which paths and operations changed between the two revisions.

Problems that belong to the connector rather than to one API, such as a gateway route that is not attached to any service, are listed as findings in the run's summary.findings.

Item statusMeaning
discoveredSeen in the inventory, not imported yet (or, like a non-current Azure API revision, not imported by design). An MCP registry server Apiome cannot reach, or a schema registry subject Apiome cannot mirror, stays here with its discoveredReason
importedImported; catalogItemId is its catalog item (mcpEndpointId, its MCP server, for an MCP registry)
ignoredNever fetched. Ignored from Shadow APIs, with a reason
missingNo longer in the inventory

Environments (gateway configs)​

Route/ade/dashboard/connectors/environments/[slug]

Every sync turns each environment the connector reports — a Kong control plane, an AWS stage, an Azure APIM instance, an Apigee environment — into a gateway config: an entity of its own in the catalog and the dependency graph. Open a connector, click “Environments” and click an environment to see its page.

A Kong environment's page: two APIs served with Push back buttons, the auth and rate-limit posture, the declared loss notice and the owner teamA Kong environment's page: two APIs served with Push back buttons, the auth and rate-limit posture, the declared loss notice and the owner team
Route/ade/dashboard/connectors/environments/kong-konnect-prod
  • APIs served — every API the last sync saw in the environment, its route, and the catalog item or Project it was imported as (Not imported when it was only discovered).
  • Posture — the Auth schemes and the plugin or policy that enforces each, the Rate limits and the Other policies (CORS, transforms, …), read from the imported configuration. Only names and schemes are kept: credentials are redacted at import, and the page says how many were.
  • Declared loss — Gateway configs carry no request/response schemas: a gateway configuration says where a request goes, not what it carries, so its APIs are operations only. Supply schemas and convert the catalog item to promote it.
  • Owner — the owner team; choose a team and click “Assign owner”.
  • Graph — the APIs deployed_on this environment.

An environment the connector no longer reports disappears on the next sync. A gateway config's deployed_on edges come from its APIs, so the blast radius and the graph show where each API runs.

Push a catalog item back to the gateway​

Click “Push back” on an imported API to export the governed catalog item back to the gateway's own format. The export opens on that format's fidelity report — what is preserved, approximated and dropped — before anything is exported; acknowledge a lossy conversion to continue.

The export opened by Push back on Kong Declarative Config: 71% preserved, 5 dropped and 2 approximated, with the acknowledgement checkboxThe export opened by Push back on Kong Declarative Config: 71% preserved, 5 dropped and 2 approximated, with the acknowledgement checkbox
Route/ade/dashboard/connectors/environments/kong-konnect-prod
ConnectorPush back to
Kong (Konnect or Admin API)Kong Declarative Config (decK)
AWS API GatewayAWS API Gateway — an OpenAPI 3.0 definition with an integration on every operation
Azure API ManagementAzure API Management — the OpenAPI definition with its policy XML
ApigeeApigee API proxy — an apiproxy/ bundle

How the fidelity report is worked out is in Understand export fidelity; what each gateway export writes is in Export to an API gateway.

With the API: GET /v1/tenants/{tenant}/gateway-configs (?connector= for one connector) and GET /v1/tenants/{tenant}/gateway-configs/{slug} — see Gateway configs. pushBack.target names the export target (kong, aws-apigateway, azure-apim or apigee) to use with POST /v1/export/{tenant}/preview.

What never changes on a refresh​

  • Nothing is deleted. An API that disappears from the inventory becomes missing. Its catalog item, and every revision of it, stays in the catalog.
  • Ignored APIs stay ignored, even when they leave and come back.
  • A converted item is not written to. Once a catalog item has been converted, the next sync creates a new catalog item instead of changing the old one.

Runs and failures​

A connector's Runs tab, and GET …/connectors/{id}/runs, list runs, newest first, with their status, trigger (manual or scheduled), counts and, for a failure, errorClass and httpStatus. GET /v1/tenants/{tenant}/refresh-runs lists every connector run and Git refresh together, each with its source (connector or git); ?connector= and ?source= filter it.

A run that could not fetch anything is a failed run, never a success with zero changes. For example, if a run fetches 0 of 12 APIs because the gateway refused the credential, it fails with errorClass: "auth" and httpStatus: 401. The connector's status then turns failing until a run succeeds. The error classes are auth, not-found, rate-limited, unavailable, credentials-unreadable, import-failed, invalid-configuration (the connector is missing a token, client secret or base URL it needs, or Apiome has no AWS or Azure workload identity to use), address-refused (a request was redirected to a private address) and unexpected.

A run also lists, under summary.unchangedItems, every API it did not re-import and why. For example: "deploymentId rv7b2yhnzn is unchanged since the last import".

Set status to paused to stop scheduled syncs; a manual sync still runs. Scheduled syncs stop with every other refresh when APIOME_REFRESH_ENABLED is off.

Kong​

The two Kong kinds read your gateway configuration live, so you do not need to keep a kong.yaml in a repository. Each Kong service becomes one catalog item. Its document is the service with its routes and plugins, written as the Kong declarative file it is equivalent to, so a synced service imports exactly like that file would.

KindBase URLCredentialScope
kong-konnectOptional. Leave it empty to use your region's Konnect API.{"token": "kpat_…"} or {"token": "spat_…"}region and controlPlanes
kong-adminRequired: the Admin API address{"token": "…"}, optionalworkspace and environment, both optional

Konnect​

  1. Create a token in Konnect. Use a personal access token (kpat_…) or the system access token (spat_…) of a system account. The token needs the Viewer role on every control plane you want to sync. The connector only reads, so read-only access is enough.

  2. Register the connector. Set region to us, eu, au, me, in or sg (default us). List the ids of the control planes to sync in controlPlanes. Leave it out to sync every control plane the token can read.

    {
    "kind": "kong-konnect",
    "name": "Konnect EU",
    "scope": { "region": "eu", "controlPlanes": ["5f1c2a3b-…"] }
    }
  3. Store the token: PUT …/connectors/{id}/credentials with {"credentials": {"token": "kpat_…"}}.

  4. Sync it.

A synced item's environment is its control plane's name.

Admin API​

For a self-managed gateway, set the connector's base URL to the Admin API address. When your Admin API uses RBAC, store a token with read access; Apiome sends it in the Kong-Admin-Token header. With Kong Enterprise workspaces, set workspace to the workspace to read. Set environment to label the items; it defaults to the workspace name. If your Admin API only listens inside your network, an operator has to allow its range (see Base URLs and private networks).

What a Kong sync records​

  • Deployment details. Each item's deployment lists the control plane id and name (or the workspace), the service's tags and enabled flag, and the protocols, hosts and paths its routes declare.
  • Suggested owners. A service tag of the form owner:<team-slug>, such as owner:payments, makes that team a suggested owner of the catalog item (it is also kept under deployment.suggestedOwners). A suggestion never makes the team the owner until someone confirms it. A tag naming a team that does not exist is a finding, unknown team x in tag; a malformed owner tag is a finding too.
  • Plugins. Auth plugins such as key-auth become the item's security schemes, labelled inferred. Every other plugin, such as rate-limiting or a custom plugin, is listed in the item's coverage ledger as partially mapped. Its configuration stays in the item's captured source, so nothing is dropped. Plugin settings that hold secrets are redacted before import.
  • Findings. A route that is not attached to a service has no catalog item to land in, so it is reported as a route-without-service finding. Consumers and consumer-scoped plugins configure callers, not the API, and are counted as findings but never imported.

A Kong service only gets a new revision when its document changes. If you change one route, the next sync imports one new revision of that service's item, writes one change report, and leaves the other items alone. If the token is revoked, the run fails with errorClass: "auth", httpStatus: 401 and Kong's error message.

AWS API Gateway​

The aws-apigateway kind reads the REST and HTTP APIs in one AWS account. Each deployed stage becomes one catalog item. Its definition is the stage's export with its API Gateway extensions, imported exactly as an exported file would be.

Apiome never stores AWS keys. You create a read-only role in your account, and Apiome assumes it for each sync. Apiome uses its own AWS identity to do so: the AWS credentials of the deployment it runs on, such as an instance profile, a workload identity or environment variables.

Create the role​

  1. Choose an external ID, a value only you and Apiome know, such as apiome-7c1d9a2f.

  2. Create an IAM role whose trust policy lets Apiome's AWS identity assume it with that external ID. Replace the principal with the identity your Apiome operator gives you:

    {
    "Version": "2012-10-17",
    "Statement": [
    {
    "Effect": "Allow",
    "Principal": { "AWS": "arn:aws:iam::111122223333:role/apiome" },
    "Action": "sts:AssumeRole",
    "Condition": { "StringEquals": { "sts:ExternalId": "apiome-7c1d9a2f" } }
    }
    ]
    }
  3. Attach this permissions policy. It is read-only; the connector never changes anything:

    {
    "Version": "2012-10-17",
    "Statement": [
    {
    "Sid": "ApiomeCatalogRead",
    "Effect": "Allow",
    "Action": "apigateway:GET",
    "Resource": [
    "arn:aws:apigateway:*::/account",
    "arn:aws:apigateway:*::/restapis",
    "arn:aws:apigateway:*::/restapis/*",
    "arn:aws:apigateway:*::/apis",
    "arn:aws:apigateway:*::/apis/*"
    ]
    }
    ]
    }
What a sync callsIAM actionResource
AssumeRolests:AssumeRoleYour role, from its trust policy
GetAccount (dry run)apigateway:GETarn:aws:apigateway:<region>::/account
GetRestApisapigateway:GETarn:aws:apigateway:<region>::/restapis
GetStages, GetExport (REST APIs)apigateway:GETarn:aws:apigateway:<region>::/restapis/*
GetApisapigateway:GETarn:aws:apigateway:<region>::/apis
GetStages, ExportApi (HTTP APIs)apigateway:GETarn:aws:apigateway:<region>::/apis/*

Register the connector​

Create it with the role, the external ID and the regions to read. There is no base URL and no credential:

{
"kind": "aws-apigateway",
"name": "AWS production",
"scope": {
"roleArn": "arn:aws:iam::123456789012:role/apiome-catalog",
"externalId": "apiome-7c1d9a2f",
"regions": ["eu-west-1", "us-east-1"]
}
}

Apiome checks the role before it saves the connector. It assumes the role, calls GetAccount, and lists one REST and one HTTP API in each region. If AWS refuses any call, the connector is not created. The response is a 422 with detail.code set to connector-check-failed, and detail.reason names what is missing, for example apigateway:GET on arn:aws:apigateway:eu-west-1::/account. The same check runs again whenever you change the scope.

What an AWS sync records​

  • One item per deployed stage. The item's environment is the stage name, its hosts hold the stage's invoke URL, and its remote revision is the stage's deploymentId.
  • Unchanged stages are skipped. A stage whose deploymentId has not changed since the last import is not exported again. The run lists it under summary.unchangedItems with that reason. When a redeploy produces the same definition, the stage is exported but nothing new is imported.
  • Deployment details. Each item's deployment records the region, account, API id and type (rest or http), stage, deploymentId, invoke URL and the API's tags.
  • Suggested owners. An API tagged apiome:owner with a team slug, such as payments, gets that team as a suggested owner of its catalog item; a team that does not exist is an unknown team finding. A suggestion never makes the team the owner until someone confirms it. A malformed value is a finding.
  • Findings. A region with no APIs is a successful run with no candidates and a region-empty finding, so an empty result is visible. A stage with no deployment (stage-not-deployed) and a WebSocket API (websocket-api-not-exported) are findings, because neither can be exported.
  • Failures name the permission. If AWS refuses the role or a call, the run fails with errorClass: "auth", and its message names the missing permission, such as Missing permission sts:AssumeRole on arn:aws:iam::123456789012:role/apiome-catalog.

Azure API Management​

The azure-apim kind reads the APIs in one Azure API Management (APIM) instance through Azure Resource Manager. The current revision of each API becomes one catalog item. Each item holds the API's OpenAPI definition and its policies, the API's and each operation's, imported exactly as an archive of the same files would be. JWT validation, rate limits, backends and the other policies are recorded on each operation.

Apiome signs in as a Microsoft Entra ID application (a service principal) that you give read-only access to the instance.

Give Apiome read access​

  1. Register an application in Microsoft Entra ID (App registrations → New registration). Note its Application (client) ID and your Directory (tenant) ID.

  2. Give it a credential, one of:

    • a client secret (Certificates & secrets → New client secret). Copy the value now: you store it in Apiome in the next section;
    • a federated credential (Certificates & secrets → Federated credentials) that trusts your Apiome deployment's workload identity. Your Apiome operator gives you the issuer and subject. No secret is stored.
  3. Assign the role. On the API Management instance, open Access control (IAM) → Add role assignment, choose API Management Service Reader Role, and assign it to the application. The role is read-only: the connector never changes anything.

    az role assignment create --assignee <client-id> \
    --role "API Management Service Reader Role" \
    --scope /subscriptions/<subscription-id>/resourceGroups/rg-apis/providers/Microsoft.ApiManagement/service/contoso-apim
What a sync calls (api-version=2024-05-01)Why
GET …/service/{name}The instance's gateway URL
GET …/apis, …/apis/{api}/revisionsEvery API and its revisions
GET …/apis/{api}?export=true&format=openapi+json-linkThe definition, downloaded from the link it returns
GET …/apis/{api}/policies/policy, …/operations/{op}/policies/policyThe API's and each operation's policy
GET …/products, …/products/{product}/apisWhich products each API is in
GET …/namedValues, …/backendsThe named values and backends the policies refer to. Only names and backend URLs are kept, never a named value's value.

Register the connector​

  1. Create it with the application, the subscription, the resource group and the instance name. There is no base URL:

    {
    "kind": "azure-apim",
    "name": "APIM production",
    "scope": {
    "tenantId": "0a1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d",
    "clientId": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
    "subscriptionId": "5f1c3a2e-8d4b-4e6f-9a7c-2b1d0e3f4a5b",
    "resourceGroup": "rg-apis",
    "serviceName": "contoso-apim",
    "authMethod": "client-secret"
    }
    }

    Set authMethod to federated for a federated credential. Set includeNonCurrentRevisions to true to import every revision, not only the current one.

  2. Store the client secret (skip this for a federated credential): PUT …/connectors/{id}/credentials with {"credentials": {"clientSecret": "…"}}.

  3. Sync it: POST …/connectors/{id}/sync.

What an Azure sync records​

  • One item per current revision. The item's environment is the APIM instance, and its hosts hold the API's gateway URL. Its revision label is rev<n>-<digest>.
  • Other revisions are recorded, not imported. A non-current revision appears in the inventory as discovered, and the run counts it under summary.discovered. With includeNonCurrentRevisions, it is imported as its own item, named "API (revision n)".
  • Products become tags. Each product the API is in becomes a tag on its catalog item, named after the product. When the API leaves a product, the tag is removed. Tags you add yourself are never touched.
  • Every sync reads every API. A policy change does not change an API's revision number, so each sync fetches each API. An API whose definition and policies are unchanged is not imported again.
  • Deployment details. Each item's deployment records the subscription, resource group, instance, API name, revision, whether it is current and online, its path, version and products.
  • Findings. A WebSocket, GraphQL or gRPC API cannot be exported as OpenAPI and is listed as an api-type-not-exported finding. An instance with nothing to import gives a service-empty finding.
  • Failures name the cause. If Microsoft Entra ID refuses the credential, the run fails with errorClass: "auth", and its message carries Entra ID's error code. For example, an expired client secret gives AADSTS7000222. If Azure Resource Manager refuses a call, the message names its code, such as AuthorizationFailed when the role assignment is missing.

Apigee​

The apigee kind reads the API proxies of one Apigee X or hybrid organization. Each proxy becomes one catalog item. Each environment it is deployed to is its own inventory row, with the deployed revision, and every revision deployed somewhere is a revision of the item. Each revision's bundle is imported exactly as an uploaded bundle would be.

Give Apiome read access​

  1. Choose the identity. Either:

    • create a service account and a JSON key for it (IAM & Admin → Service accounts → Keys → Add key), or
    • create a workload identity federation credential configuration for your Apiome deployment's external identity (gcloud iam workload-identity-pools create-cred-config …). No key is stored.
  2. Grant the role. Give the identity Apigee Read-only Admin (roles/apigee.readOnlyAdmin) on the Google Cloud project of the Apigee organization:

    gcloud projects add-iam-policy-binding acme-prod \
    --member "serviceAccount:apiome-catalog@acme-prod.iam.gserviceaccount.com" \
    --role roles/apigee.readOnlyAdmin

Apiome asks for an access token with the https://www.googleapis.com/auth/cloud-platform scope.

What a sync callsWhy
GET …/organizations/{org}/apisThe API proxies
GET …/organizations/{org}/environmentsThe environments, when the scope names none
GET …/environments/{env}/deploymentsWhich revision each proxy runs in each environment
GET …/apis/{api}/revisionsThe latest revision of a proxy deployed nowhere
GET …/apis/{api}/revisions/{rev}?format=bundleThe bundle of a deployed revision

Register the connector​

  1. Create it with the organization and, optionally, the environments to read. There is no base URL:

    {
    "kind": "apigee",
    "name": "Apigee production",
    "scope": { "organization": "acme-prod", "environments": ["test", "prod"] }
    }

    Leave out environments to read every environment of the organization.

  2. Store the credential: PUT …/connectors/{id}/credentials with {"credentials": {"credentialJson": "<the key or configuration file's JSON>"}}.

  3. Sync it: POST …/connectors/{id}/sync.

What an Apigee sync records​

  • One item per proxy, one row per environment. A proxy deployed to test at revision 5 and to prod at revision 3 is one catalog item with two inventory rows, environments test and prod, and revisions 5 and 3. A revision both environments run is imported once.
  • Undeployed proxies are recorded, not imported. A proxy deployed nowhere appears as discovered, with its latest revision.
  • Unchanged deployments are skipped. A row whose deployed revision has not changed is not downloaded again; the run lists it under summary.unchangedItems.
  • Declared conditions come with the bundle. A route rule with no target endpoint, or a flow condition that is not a path and verb, is recorded on the item as a declared condition.
  • Failures name the cause. A refused credential gives errorClass: "auth" with Google's error (invalid_grant …). A missing IAM permission is named, for example Missing permission apigee.deployments.list. A token without the cloud-platform scope says so (ACCESS_TOKEN_SCOPE_INSUFFICIENT).

Schema registry​

The schema-registry kind crawls a registry that speaks the Confluent Schema Registry REST API: Confluent Platform or Confluent Cloud, Karapace, or Apicurio Registry's compatibility API. Each subject becomes a schema subject of your workspace, with its versions, schema ids and compatibility level, and every version becomes a revision of a catalog item. The connector only reads: nothing is ever written to the upstream registry.

Add a schema registry​

  1. Go to Bring in → Connectors and click Add connector.

  2. Kind: choose Schema registry and click Continue.

  3. Credentials: leave every field empty for an open registry. For basic auth, enter a Username or API key and a Password or API secret; Confluent Cloud takes its Schema Registry API key and secret here. For a registry behind a token, enter a Bearer token. Click Continue.

    Add a connector, Credentials step for a schema registry: Username or API key and Password or API secret filled in, Bearer token emptyAdd a connector, Credentials step for a schema registry: Username or API key and Password or API secret filled in, Bearer token empty
    Route/ade/dashboard/connectors/new
  4. Scope: enter the registry's REST address as the Base URL, for example https://psrc-123.eu-west-1.aws.confluent.cloud. For Apicurio, use its compatibility API: https://<apicurio>/apis/ccompat/v7. A schema registry takes no other scope.

  5. Dry run and Schedule work as for every other kind: the dry run lists the subjects the registry returns, and nothing is stored until you click Save connector.

With the API, register it with an empty scope:

{
"kind": "schema-registry",
"name": "Prod schema registry",
"baseUrl": "https://psrc-123.eu-west-1.aws.confluent.cloud",
"scope": {}
}

What a schema registry sync does​

Each sync lists the registry with GET /subjects, then, for each subject, GET /subjects/{subject}/versions and GET /config/{subject}?defaultToGlobal=true. A registry that answers 404 there, such as Apicurio for a subject with no level of its own, falls back to GET /config. Each subject is one inventory row. A subject is fetched again only when it has a new or deleted version or a different compatibility level. For each one:

  1. It reads each version it has not mirrored yet, oldest first, with GET /subjects/{subject}/versions/{version}. When the answer has no schema text, GET /schemas/ids/{id} supplies it.
  2. It deduplicates by schema id. A schema id the connector has already seen, under any subject and in any sync, is not parsed or imported again. A schema your workspace already holds keeps its Apiome schema id and revision. Only new content is imported, as a new revision of the subject's catalog item, labelled with the upstream version number.
  3. It copies the subject's settings. The upstream compatibility level is copied onto the subject. When the subject states no strategy, it is read from the name: <topic>-key or <topic>-value is topic, the record name alone is record, and <topic>-<record name> is topic_record.
  4. It mirrors deletions. A version the registry no longer lists is deleted from the subject. The catalog revision behind it stays.

A mirrored subject shows where it came from: sourceRef is registry:<base URL> and sourceConnectorId names the connector. Each mirrored version keeps the upstream upstreamVersion and upstreamSchemaId beside Apiome's own version number and schema id. Compatibility checks are not run on mirrored versions, because the upstream registry already admitted them.

Each version read counts as one pull against the workspace's polling quota, and so does each /schemas/ids/{id} call. A subject Apiome cannot mirror stays discovered, and the Items tab shows why under its status:

discoveredReasonWhat it meansWhat to do
subject-name-takenYour workspace already has a subject with this name, registered in Apiome or mirrored by another connector. It is never overwrittenRename or delete the other subject
references-unsupportedA version refers to schemas in other subjects and cannot be read on its ownNothing yet: the versions before it are mirrored
schema-type-unavailableThe deployment cannot read this schema type (Protobuf without the bundled buf)An operator can install the toolchain

Any other schema the importer refuses fails that subject for this run. The versions mirrored before it stay, and the next sync carries on from there. Schema registry connectors are left out of Shadow APIs: schema subjects are not APIs a gateway serves.

MCP registry​

The mcp-registry kind reads GET /v0.1/servers from any registry that speaks the MCP Registry API: the official registry at https://registry.modelcontextprotocol.io, Azure API Center, a Kong registry, or another Apiome workspace's MCP registry endpoint. Each server becomes an MCP server of your workspace's MCP catalog, not a catalog item.

Add an MCP registry​

  1. Go to Bring in → Connectors and click Add connector.

  2. Kind: choose MCP registry and click Continue.

  3. Credentials: leave both fields empty for a public registry. Enter a Bearer token for a registry that asks for one, or an Apiome workspace API key to read another Apiome workspace. Click Continue.

  4. Scope: enter the registry root as the Base URL. Optionally narrow what is read:

    • Search: only servers whose name matches, for example io.github.acme.
    • Updated since: only servers updated at or after an RFC 3339 instant, for example 2026-01-01T00:00:00Z. Servers the filter hides are reported missing, so leave it empty to keep the whole registry in view.
    Add a connector, Scope step for an MCP registry: the registry root as Base URL, a Search of io.github.acme and an Updated since instantAdd a connector, Scope step for an MCP registry: the registry root as Base URL, a Search of io.github.acme and an Updated since instant
    Route/ade/dashboard/connectors/new
  5. Dry run and Schedule work as for every other kind: the dry run lists the servers the registry returns, and nothing is stored until you click Save connector.

With the API, register it with the registry root as baseUrl (a trailing /v0.1 or /v0.1/servers is accepted):

{
"kind": "mcp-registry",
"name": "Official MCP registry",
"baseUrl": "https://registry.modelcontextprotocol.io",
"scope": { "search": "io.github.acme", "updatedSince": "2026-01-01T00:00:00Z" }
}

Store a credential, when the registry needs one, with PUT …/connectors/{id}/credentials and {"credentials": {"token": "…"}} (sent as Authorization: Bearer) or {"credentials": {"apiKey": "…"}} (sent as X-API-Key).

What an MCP registry sync does​

Each sync pages through /v0.1/servers (version=latest, with your search and updated_since). Each server name is one inventory row; a server the registry marks deleted turns missing. For every server that is new or changed since the last sync:

  1. It picks a remote. The first remotes[] entry of type streamable-http or sse with a concrete URL.
  2. It adds or refreshes the MCP server. A new server is added as private and unpublished, marked as imported from a registry. A server it added before has its name, URL, transport and description refreshed from the registry.
  3. It links the server's sources with the provenance registry published: the registry entry itself, repository.url as a Git source, and each npm, PyPI, NuGet, Cargo or OCI entry of packages[]. A package is pinned only when the registry names an exact version. A link this connector made that the registry no longer lists is retired; links you added yourself are never touched.
  4. It runs discovery, which also lints and grades the server. Any answer from the server, even 401, means it is there, and the row becomes imported.

Discovery runs inside the sync, one server at a time, so the first sync of a large registry takes a while. Narrow it with Search. A scheduled sync stops at the workspace's polling quota and defers the rest to its next run; unchanged servers are skipped.

A server that cannot be reached stays discovered, and the Items tab shows why under its status. The reason starts with a stable code:

discoveredReasonWhat it meansWhat to do
no-remoteThe server lists only packages, which run locally over stdio, or no HTTP remote at allNothing: there is nothing to discover remotely
remote-templatedThe remote URL contains a {variable} the client fills inAdd the server by hand with its concrete URL
remote-refusedThe remote resolves to a private address (the base URL rule)An operator can allow the range
remote-unreachableDiscovery could not connect (connect_error, tls_error, timeout, …). The server was added; Apiome tries again on the next syncCheck the server is up

On the Items tab, the column MCP server says Added to the MCP servers for every server the connector added (Open the MCP server on deployments where the MCP servers screen is turned on). MCP registry connectors are left out of Shadow APIs: MCP servers are not APIs a gateway serves.

Registry crawl​

The registry kind crawls a registry rather than one document: it lists every artifact the registry holds, fetches each one and imports each as its own catalog item, versioned on its own. The connector's scope names the protocol, which picks the importer that reads the artifacts:

ProtocolBase URLWhat becomes a catalog itemImported as
a2a-registryThe registry's listing URLEach agent the registry listsA2A Agent Card
xregistryThe xRegistry root, for example https://<host>/regEach schema in each schema group, each message group and each endpointA schema: JSON Schema, Avro, Protobuf or XSD, from its format. A message group or endpoint: CNCF xRegistry
fhir-metadataThe FHIR server base, for example https://fhir.example.com/r4The server's CapabilityStatement and, with Include profiles, each profile its resources declareFHIR

Add a registry crawl​

  1. Go to Bring in → Connectors and click Add connector.

  2. Kind: choose Registry crawl and click Continue.

  3. Credentials: leave both fields empty for a public registry. Enter a Bearer token, or an API key sent as X-API-Key. Click Continue.

  4. Scope: enter the registry's Base URL and choose its Protocol. For an xRegistry, list Groups to crawl only those schema and message groups (comma-separated), or leave it empty for every group. For a FHIR server, tick Include profiles to import each StructureDefinition too.

    Add a connector, Scope step for a registry crawl: an xRegistry root as Base URL, Protocol CNCF xRegistry (schemas, messages, endpoints) and Groups orders, paymentsAdd a connector, Scope step for a registry crawl: an xRegistry root as Base URL, Protocol CNCF xRegistry (schemas, messages, endpoints) and Groups orders, payments
    Route/ade/dashboard/connectors/new
  5. Dry run lists the artifacts the registry returns, and Schedule sets how often it is crawled again. Nothing is stored until you click Save connector.

With the API or the CLI, put the protocol in the scope:

{
"kind": "registry",
"name": "Event schemas",
"baseUrl": "https://xreg.example.com/reg",
"scope": { "protocol": "xregistry", "groups": ["orders", "payments"], "requestsPerSecond": 2 }
}
apiome connectors add --kind registry --name "Event schemas" \
--base-url https://xreg.example.com/reg --scope '{"protocol": "xregistry"}'

What a registry crawl does​

Each sync lists the whole registry, following its pages, and records one inventory row per artifact, keyed by the artifact's id in the registry (an Agent Card URL, schemagroups/<group>/schemas/<id>, messagegroups/<group>, endpoints/<id>, a profile's canonical URL). For each artifact:

  • A new artifact is fetched and imported as a new catalog item.
  • A changed artifact is fetched again and imported as a new revision of the same catalog item, with a change report against the previous one. An artifact counts as changed when its revision in the registry moved (an A2A entry's version or updatedAt, an xRegistry schema's version and epoch, a CapabilityStatement's version and date). An artifact the registry gives no revision is fetched every sync and imported again only when its content differs.
  • An unchanged artifact is skipped, and nothing is fetched. A revision that moves while the content stays the same is also not imported again.
  • An artifact the registry no longer lists turns missing. Its catalog item stays.

Every revision records where it came from: the connector, the registry protocol, the artifact's id and revision in the registry, and its URL there. It shows on the catalog item's Provenance tab.

Limits. Every request goes through the connector's address rule, on every redirect too. A crawl sends at most requestsPerSecond requests a second to one host (5 by default, 20 at most), at most 2,000 requests a sync, reads at most 100 pages of a listing and 5,000 artifacts, and refuses a response over 5 MB. Each artifact fetched counts as one pull against the workspace's polling quota. An artifact that fails to fetch or import fails only itself: the rest of the registry is still imported.

A2A agent registry​

A2A does not define a registry API yet, so the crawl reads the shape registries publish today. GET <base URL> answers either a JSON array of entries, or {"agents": [entries], "nextPageToken": "…"}. The next page is GET <base URL>?pageToken=…. An entry is one of these:

  • An Agent Card URL (https://agent.example.com/.well-known/agent-card.json), or an agent's address (https://agent.example.com), whose card is read from /.well-known/agent-card.json and then the legacy /.well-known/agent.json.
  • An object with url (or cardUrl), and optionally name, version and updatedAt.
  • An object holding the Agent Card itself, under card or as the entry.

xRegistry​

An xRegistry holds three registries, and the crawl reads each one the registry serves. Every collection follows Link: <…>; rel="next" pages.

Schemas. The crawl reads GET <base>/schemagroups and, for each group, its schemas collection. A schema's format picks the importer:

  • JsonSchema/… imports as JSON Schema.
  • Avro/… imports as Avro.
  • Protobuf/… imports as Protobuf.
  • XSD/… imports as XSD.

A schema in any other format is skipped and listed in the run's findings. A schema whose listing carries the document (schema or schemabase64) is not fetched again; any other schema is read from GET <base>/schemagroups/<group>/schemas/<id>, or from its schemaurl.

Message groups. The crawl reads GET <base>/messagegroups and each group's messages (GET <base>/messagegroups/<group>/messages, unless the listing carries them). Each group becomes one catalog item, imported as a CNCF xRegistry document: its messages are operations on the channels their CloudEvents type names. A group with no messages is skipped and listed in the run's findings.

Endpoints. The crawl reads GET <base>/endpoints and each endpoint's own messages. Each endpoint becomes one catalog item holding the endpoint, its messages and the message groups it references, so its operations, payloads and broker URIs read on their own.

A registry that answers 404 for one of the three collections simply has none of it; a base URL that serves none of them fails the sync. Message groups and endpoints carry no revision, so they are imported again only when their content changes; the epoch, createdat and modifiedat stamps are left out of the document, so a stamp that moves alone imports nothing.

Two scope keys narrow the crawl:

  • groups — the schema and message group ids to crawl. Endpoints are always crawled, with the groups they reference.
  • include — which registries to crawl: any of schemas, messages, endpoints (all three when left out). For example {"protocol": "xregistry", "include": ["messages", "endpoints"]}.

FHIR /metadata​

The crawl reads GET <base>/metadata and imports the CapabilityStatement. With Include profiles, every profile and supportedProfile of its resources is read from the same server with GET <base>/StructureDefinition?url=<canonical>. Requests ask for application/fhir+json.

Registry connectors are left out of Shadow APIs: a registry's artifacts are published, not found on a gateway.

Quota and audit​

Every document a connector fetches counts against the workspace's repository polling quota, the same budget Git refreshes use. Fetches show under Polls on Quota & rate limits. A scheduled sync that runs out of quota defers the rest to a later run, and a manual sync is never held back by the quota.

Every connector change and run is written to the audit trail as repository.connector.*, so the repository audit export lists connector runs next to Git refreshes.

API​

Method and pathWhat it does
GET /v1/tenants/{tenant}/connectorsList connectors, the kinds, and the kinds that can sync
POST /v1/tenants/{tenant}/connectorsRegister a connector
POST /v1/tenants/{tenant}/connectors/dry-runAsk the provider once what a connector would sync; stores nothing
GET / PATCH / DELETE …/connectors/{id}Read, change or delete one
POST …/connectors/{id}/syncSync now and return the run
GET …/connectors/{id}/itemsThe inventory (?status= filters it), with each item's deployment
GET …/connectors/{id}/runsThe runs, newest first
GET /v1/tenants/{tenant}/refresh-runsConnector runs and Git refreshes together (?connector=, ?source=git|connector)
PUT …/connectors/{id}/credentialsStore or replace the credential
POST …/connectors/{id}/items/{itemId}/link · ignore · unignore · importAct on one inventory item (see Shadow APIs)

See the API reference for the request and response shapes.

Where next​

  • Catalog: where synced APIs land, and the Provenance tab that names their connector.
  • Repositories: the Git side of the same refresh engine.
  • Shadow APIs: what your connectors serve that the catalog does not describe.