Skip to main content

Remote Catalogs

Remote Catalogs brings Infrastructure as Code (IaC) and GitOps capabilities to Otoroshi. It allows you to define your API gateway configuration (routes, backends, apikeys, certificates, etc.) as declarative files stored in Git repositories, S3 buckets, Consul KV, or any HTTP endpoint, and have Otoroshi automatically synchronize and reconcile the desired state.

This enables DevOps teams to manage their API gateway configuration using the same workflows they use for application code: version control, pull requests, code review, CI/CD pipelines, and automated deployments. Changes pushed to a Git repository can be automatically deployed to Otoroshi via webhooks or scheduled polling, ensuring that the running configuration always matches the declared state.

How it works​

A Remote Catalog is an entity that defines:

  • A source where entity definitions are stored (GitHub, GitLab, Bitbucket, Gitea, Forgejo, Codeberg, S3, HTTP, local file, Git repository, Consul KV)
  • An optional scheduling configuration to automatically sync entities at regular intervals
  • A reconciliation engine that creates, updates, and deletes local entities to match the remote desired state

When a catalog is deployed, Otoroshi fetches the entity definitions from the remote source, then reconciles them with the local state using a declarative approach similar to tools like Terraform or Kubernetes: the remote source represents the desired state, and Otoroshi converges towards it. Entities managed by a catalog are tagged with a created_by metadata field set to remote_catalog=<catalog_id>, which allows Otoroshi to track ownership and lifecycle of managed entities.

Entity format​

Remote entities can be defined in JSON or YAML format. Multi-document YAML files (using --- as separator) are supported. Two entity formats are supported: flat format and Kubernetes-style format.

Flat format​

Each entity must contain at least an id field and a kind field. The kind field should match one of the existing Otoroshi resource kinds (e.g., Route, Backend, ApiKey, Certificate, etc.) including entities provided by Otoroshi extensions. You can also use the fully qualified kind with group prefix, like proxy.otoroshi.io/Route. This is the RECOMMENDED format to perform well !

{
"id": "my-route-1",
"kind": "Route",
"name": "My Route",
"frontend": {
"domains": ["myapi.oto.tools"]
},
"backend": {
"targets": [
{
"hostname": "my-backend.internal",
"port": 8080
}
]
}
}

or in YAML:

id: my-route-1
kind: Route
name: My Route
frontend:
domains:
- myapi.oto.tools
backend:
targets:
- hostname: my-backend.internal
port: 8080

Kubernetes-style format​

Entities can also be written using a Kubernetes-style structure with apiVersion, kind at the root level and the actual entity definition nested under spec:

apiVersion: proxy.otoroshi.io/v1
kind: Route
spec:
id: my-route-1
name: My Route
frontend:
domains:
- myapi.oto.tools
backend:
targets:
- hostname: my-backend.internal
port: 8080

The kind from the root level is automatically injected into the entity content. If the spec already contains a kind field that matches the root kind (either identical or with a group prefix, e.g., proxy.otoroshi.io/Route for a root kind: Route), the existing kind in spec is preserved.

Multiple entities in a single file​

Multiple entities can be placed in a single file using the YAML multi-document separator ---:

apiVersion: proxy.otoroshi.io/v1
kind: Route
spec:
id: my-route-1
name: My Route 1
frontend:
domains:
- api1.oto.tools
backend:
targets:
- hostname: backend1.internal
port: 8080
---
apiVersion: proxy.otoroshi.io/v1
kind: Route
spec:
id: my-route-2
name: My Route 2
frontend:
domains:
- api2.oto.tools
backend:
targets:
- hostname: backend2.internal
port: 8080

Path modes​

When configuring a source, the path parameter determines how entities are fetched:

  • File path (e.g., entities/routes.json): fetches a single file and parses it for entities
  • Directory path (e.g., entities/): lists all .json, .yaml, and .yml files in the directory and parses each one
  • Catalog listing file (e.g., catalog.json): a file containing an array of relative file paths to fetch

Catalog listing file​

A catalog listing file can be written in JSON or YAML, using two possible formats.

Simple array format (JSON or YAML):

[
"./routes/route1.json",
"./route2.yaml",
"./backends/backend1.json",
"./apikeys/key1.yaml"
]
- ./routes/route1.json
- ./route2.yaml
- ./backends/backend1.json
- ./apikeys/key1.yaml

Kubernetes-style RemoteCatalogListing format (JSON or YAML):

apiVersion: proxy.otoroshi.io/v1
kind: RemoteCatalogListing
spec:
catalog_listing:
- ./routes/route1.json
- ./route2.yaml
- ./backends/backend1.json
- ./apikeys/key1.yaml

The RemoteCatalogListing format requires both apiVersion: proxy.otoroshi.io/v1 and kind: RemoteCatalogListing at the root level. The file paths are listed under spec.catalog_listing.

Glob patterns in catalog listing files​

Catalog listing files support glob/wildcard patterns to match multiple files at once. This is useful when you have a large number of entity files organized in directories and don't want to list each one individually.

Supported glob syntax:

  • * matches any sequence of characters within a single directory (does not cross /)
  • ** matches any sequence of characters across directories (crosses /)
  • ? matches any single character
  • [abc] matches any character in the set

Examples:

apiVersion: proxy.otoroshi.io/v1
kind: RemoteCatalogListing
spec:
catalog_listing:
- ./project-1/*.yaml
- ./project-2/**.json
- ./project-3/team-*/**.yaml
- ./shared/route?.json

In this example:

  • ./project-1/*.yaml matches all .yaml files directly in the project-1 directory
  • ./project-2/**.json matches all .json files in project-2 and any subdirectory
  • ./project-3/team-*/**.yaml matches all .yaml files under any team-* directory inside project-3
  • ./shared/route?.json matches files like route1.json, routeA.json, etc.
note

Glob patterns are supported by the following sources: file, git, github, gitlab, gitea, forgejo, codeberg, bitbucketserver, s3, and consulkv. The http and bitbucket (Cloud) sources do not support glob patterns because they lack a recursive directory listing API. When a glob pattern is used with a source that does not support it, the pattern is treated as a literal path.

Remote Catalog configuration​

A Remote Catalog entity has the following structure:

{
"id": "my-catalog", // unique identifier
"name": "My Remote Catalog", // display name
"description": "...", // description
"enabled": true, // is the catalog active
"source_kind": "github", // source type (see below)
"source_config": { ... }, // source-specific configuration
"scheduling": { // optional auto-sync schedule
"enabled": false,
"kind": "ScheduledEvery", // ScheduledEvery or Cron
"interval": 60000, // interval in milliseconds (for ScheduledEvery)
"cron_expression": "0 */5 * * * ?", // cron expression (for Cron)
"initial_delay": 10000, // initial delay in milliseconds
"deploy_args": {} // arguments passed during scheduled deploy
},
"test_deploy_args": {} // arguments for manual test/dry-run
}

Supported sources​

HTTP​

Fetches entities from an HTTP endpoint.

{
"source_kind": "http",
"source_config": {
"url": "https://my-server.com/entities.json", // URL to fetch
"headers": { // optional HTTP headers
"Authorization": "Bearer my-token"
},
"timeout": 30000 // request timeout in ms (default: 30000)
}
}

File​

Reads entities from the local filesystem.

{
"source_kind": "file",
"source_config": {
"path": "/path/to/entities", // file or directory path
"pre_command": ["sh", "-c", "..."] // optional command to run before reading
}
}

The pre_command can be used to run a script before reading (e.g., to pull from a repository).

GitHub​

Fetches entities from a GitHub repository using the GitHub API.

{
"source_kind": "github",
"source_config": {
"repo": "owner/repo", // repository (owner/repo) or organization name
"branch": "main", // branch name (default: main)
"path": "entities/", // file or directory path in the repo
"token": "ghp_xxx", // optional personal access token
"base_url": "https://api.github.com", // API base URL (for GitHub Enterprise)
"repo_patterns": ["otoroshi-*", "api-*"] // optional: filter repos when scanning an org
}
}

Supports webhook-triggered deployments (see the Webhook deployment section).

Organization scanning mode​

When repo is set to an organization or user name (without /, e.g., cloud-apim instead of cloud-apim/my-repo), Otoroshi will list all repositories in that organization and scan each one for the specified path. If a repository does not contain the specified path, it is silently skipped.

The repo_patterns option allows filtering which repositories to scan using glob patterns. For example, ["otoroshi-*"] will only scan repositories whose name starts with otoroshi-. If repo_patterns is not set, all repositories in the organization are scanned.

{
"source_kind": "github",
"source_config": {
"repo": "cloud-apim",
"path": "otoroshi-remote-catalog.yaml",
"token": "ghp_xxx",
"repo_patterns": ["otoroshi-*"]
}
}

GitLab​

Fetches entities from a GitLab repository using the GitLab API.

{
"source_kind": "gitlab",
"source_config": {
"repo": "group/project", // project path or group name
"branch": "main", // branch name (default: main)
"path": "entities/", // file or directory path in the repo
"token": "glpat-xxx", // optional private token
"base_url": "https://gitlab.com", // GitLab instance URL (for self-hosted)
"repo_patterns": ["otoroshi-*"] // optional: filter projects when scanning a group
}
}

Supports webhook-triggered deployments (see the Webhook deployment section).

Group scanning mode​

When repo is set to a group name (without /, e.g., cloud-apim instead of cloud-apim/my-project), Otoroshi will list all projects in that group (including subgroups) and scan each one for the specified path. If a project does not contain the specified path, it is silently skipped.

The repo_patterns option filters projects by their name (last segment of the path) using glob patterns.

{
"source_kind": "gitlab",
"source_config": {
"repo": "cloud-apim",
"path": "otoroshi-remote-catalog.yaml",
"token": "glpat-xxx",
"repo_patterns": ["otoroshi-*"]
}
}

Bitbucket​

Fetches entities from a Bitbucket Cloud repository using the Bitbucket API 2.0.

{
"source_kind": "bitbucket",
"source_config": {
"repo": "workspace/repo", // repository (workspace/repo) or workspace name
"branch": "main", // branch name (default: main)
"path": "entities/", // file or directory path
"token": "xxx", // app password or OAuth token
"username": "my-user", // username (for Basic auth with app password)
"base_url": "https://api.bitbucket.org", // API base URL (Bitbucket Cloud API 2.0 only)
"repo_patterns": ["otoroshi-*"] // optional: filter repos when scanning a workspace
}
}

If username is provided, authentication uses Basic auth (username:token). Otherwise, Bearer token authentication is used.

This source targets Bitbucket Cloud only. Bitbucket Server / Data Center exposes a different API (/rest/api/1.0), so pointing base_url at a Bitbucket Server instance will not work -- use the Bitbucket Server / Data Center source kind for those.

Supports webhook-triggered deployments (see the Webhook deployment section).

Workspace scanning mode​

When repo is set to a workspace name (without /, e.g., cloud-apim instead of cloud-apim/my-repo), Otoroshi will list all repositories in that workspace and scan each one for the specified path. If a repository does not contain the specified path, it is silently skipped.

The repo_patterns option filters repositories by their slug using glob patterns.

{
"source_kind": "bitbucket",
"source_config": {
"repo": "cloud-apim",
"path": "otoroshi-remote-catalog.yaml",
"token": "xxx",
"repo_patterns": ["otoroshi-*"]
}
}

Bitbucket Server / Data Center​

Fetches entities from a self-hosted Bitbucket Server or Data Center instance, using the REST API 1.0. Bitbucket Server exposes a completely different API from Bitbucket Cloud, which is why it has its own source kind.

{
"source_kind": "bitbucketserver",
"source_config": {
"repo": "PRJ/my-repo", // projectKey/repoSlug, or a project key alone to scan it
"branch": "main", // branch name (default: main)
"path": "entities/", // file or directory path
"token": "xxx", // HTTP access token
"username": "my-user", // optional username (switches to Basic auth)
"base_url": "https://bitbucket.example.com", // instance URL (default: http://localhost:7990)
"repo_patterns": ["otoroshi-*"] // optional: filter repos when scanning a project
}
}

base_url is the root URL of the instance: the /rest/api/1.0 prefix is appended automatically (providing it explicitly also works). The repo field accepts a project key and repository slug (PRJ/my-repo), or a browse URL such as https://bitbucket.example.com/projects/PRJ/repos/my-repo/browse. Personal repositories live in a project whose key is ~username, so ~jdoe/my-repo is a valid value.

If username is provided, authentication uses Basic auth (username:token). Otherwise the token is sent as a Bearer token, which is what Bitbucket Server HTTP access tokens expect.

Unlike the Bitbucket Cloud source, this one supports glob patterns in catalog listing files, because the REST API 1.0 exposes a recursive file listing endpoint. All listing endpoints are paginated by Bitbucket Server (25 items per page by default) and Otoroshi follows every page.

Supports webhook-triggered deployments (see the Webhook deployment section). Configure a repo:refs_changed webhook on the repository.

Project scanning mode​

When repo is set to a project key alone (without /, e.g., PRJ instead of PRJ/my-repo), Otoroshi will list all repositories of that project and scan each one for the specified path. If a repository does not contain the specified path, it is silently skipped.

The repo_patterns option filters repositories by their slug using glob patterns.

{
"source_kind": "bitbucketserver",
"source_config": {
"repo": "PRJ",
"path": "otoroshi-remote-catalog.yaml",
"token": "xxx",
"base_url": "https://bitbucket.example.com",
"repo_patterns": ["otoroshi-*"]
}
}

Gitea​

Fetches entities from a Gitea instance using the Gitea API v1.

{
"source_kind": "gitea",
"source_config": {
"repo": "owner/repo", // repository (owner/repo) or organization name
"branch": "main", // branch name (default: main)
"path": "entities/", // file or directory path in the repo
"token": "xxx", // optional personal access token
"base_url": "http://localhost:3000", // Gitea instance URL (default: http://localhost:3000)
"repo_patterns": ["otoroshi-*"] // optional: filter repos when scanning an org
}
}

Supports webhook-triggered deployments (see the Webhook deployment section).

Organization scanning mode​

When repo is set to an organization or user name (without /, e.g., cloud-apim instead of cloud-apim/my-repo), Otoroshi will list all repositories in that organization and scan each one for the specified path. If a repository does not contain the specified path, it is silently skipped. The API first tries /api/v1/orgs/{org}/repos, then falls back to /api/v1/users/{org}/repos.

The repo_patterns option filters repositories by name using glob patterns.

{
"source_kind": "gitea",
"source_config": {
"repo": "cloud-apim",
"path": "otoroshi-remote-catalog.yaml",
"token": "xxx",
"base_url": "https://my-gitea.example.com",
"repo_patterns": ["otoroshi-*"]
}
}

Forgejo​

Fetches entities from a Forgejo instance. Forgejo is a fork of Gitea and uses the same API, so the configuration is identical to Gitea.

{
"source_kind": "forgejo",
"source_config": {
"repo": "owner/repo", // repository (owner/repo) or organization name
"branch": "main", // branch name (default: main)
"path": "entities/", // file or directory path in the repo
"token": "xxx", // optional personal access token
"base_url": "http://localhost:3000", // Forgejo instance URL (default: http://localhost:3000)
"repo_patterns": ["otoroshi-*"] // optional: filter repos when scanning an org
}
}

Supports the same features as Gitea: webhook-triggered deployments, organization scanning, glob patterns in catalog listing files.

Any hosted service running Forgejo or Gitea works with this source kind: just point base_url at the instance. That covers private instances as well as the managed Forgejo offerings (Codebahn, OpenCommit, Codey, etc.), without needing a dedicated source kind for each one.

Codeberg​

Fetches entities from Codeberg (a hosted Forgejo instance at codeberg.org). Uses the same Gitea-compatible API.

{
"source_kind": "codeberg",
"source_config": {
"repo": "owner/repo", // repository (owner/repo) or organization name
"branch": "main", // branch name (default: main)
"path": "entities/", // file or directory path in the repo
"token": "xxx", // optional personal access token
"base_url": "https://codeberg.org", // API base URL (default: https://codeberg.org)
"repo_patterns": ["otoroshi-*"] // optional: filter repos when scanning an org
}
}

Supports the same features as Gitea: webhook-triggered deployments, organization scanning, glob patterns in catalog listing files.

Git (generic)​

Clones a Git repository and reads entities from the local clone. Works with any Git hosting provider or self-hosted repository.

{
"source_kind": "git",
"source_config": {
"repo": "https://github.com/owner/repo.git", // repository URL (HTTPS or SSH)
"branch": "main", // branch name (default: main)
"path": "entities/", // file or directory path in the repo
"token": "ghp_xxx", // optional token (injected in HTTPS URL)
"username": "oauth2", // optional username for HTTPS auth
"ssh_private_key_path": "/path/to/id_rsa" // SSH private key path (for SSH URLs)
}
}

The git source uses shallow clones (--depth 1) for efficiency. Subsequent fetches reuse the existing clone directory and do a git fetch --all + git reset --hard to update.

For SSH authentication, the ssh_private_key_path is passed via GIT_SSH_COMMAND environment variable with StrictHostKeyChecking=no.

S3​

Fetches entities from an Amazon S3 (or compatible) bucket.

{
"source_kind": "s3",
"source_config": {
"bucket": "my-bucket", // S3 bucket name
"key": "entities/deploy.json", // object key (file path)
"endpoint": "https://s3.amazonaws.com", // S3 endpoint URL
"region": "eu-west-1", // AWS region
"access": "AKIAIOSFODNN7EXAMPLE", // AWS access key ID
"secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCY..." // AWS secret access key
}
}

Works with any S3-compatible storage (MinIO, DigitalOcean Spaces, etc.) by changing the endpoint URL.

Consul KV​

Fetches entities from a Consul KV store.

{
"source_kind": "consulkv",
"source_config": {
"endpoint": "http://localhost:8500", // Consul HTTP API endpoint
"prefix": "otoroshi/entities", // KV key prefix (file or directory)
"token": "xxx", // optional ACL token
"dc": "dc1" // optional datacenter
}
}

When prefix points to a key with a file extension (e.g., otoroshi/entities/routes.json), it fetches that single key. Otherwise, it lists all keys under the prefix and fetches each one that has a .json, .yaml, or .yml extension.

Deploy, dry-run, and undeploy​

Deploy​

Deploying a catalog fetches entities from the remote source and reconciles them with the local state:

  • New entities are created with created_by: remote_catalog=<catalog_id> metadata
  • Existing entities (same ID) are updated
  • Orphaned entities (present locally with the catalog's metadata but absent from remote) are deleted
curl -X POST 'http://otoroshi-api.oto.tools:8080/api/extensions/remote-catalogs/_deploy' \
-u admin-api-apikey-id:admin-api-apikey-secret \
-H 'Content-Type: application/json' \
-d '[{"id": "my-catalog", "args": {}}]'

You can deploy multiple catalogs in a single request by adding more entries to the array.

APIs​

An API (apis.otoroshi.io/Api) written by a catalog does not go through a draft: the source plays the role of the draft, and each deploy of the catalog is a deploy of the API.

  • The API is created in the state of the source: a source can hold a published API, and its routes are served after the deploy.
  • The fields locked in production (domain, contextPath, routes, backends, flows, documentation, testing) take the content of the source. A deploy that changes what is live adds an entry, owned by remote_catalog=<catalog_id>, to the deployment history of the API. An unchanged source adds none.
  • The state transitions are the ones of a deploy: a published API cannot go back to staging, and a removed API has to be reopened in staging first.
  • The deployment history and the secret of the testing header stay the ones of the live API, whatever the source holds.
  • An edit of the API from the backoffice is replaced by the source at the next deploy of the catalog.
  • An API removed from the source is deleted with its routes. The subscriptions that are not in the source, their apikeys and the draft of the API are not deleted.

Dry-run (test)​

A dry-run performs the same fetch and reconciliation logic but without actually writing any changes. It returns a report showing what would be created, updated, or deleted.

curl -X POST 'http://otoroshi-api.oto.tools:8080/api/extensions/remote-catalogs/_test' \
-u admin-api-apikey-id:admin-api-apikey-secret \
-H 'Content-Type: application/json' \
-d '{"id": "my-catalog", "args": {}}'

Undeploy​

Undeploying a catalog removes all entities that were created by that catalog (identified by the created_by metadata).

curl -X POST 'http://otoroshi-api.oto.tools:8080/api/extensions/remote-catalogs/_undeploy' \
-u admin-api-apikey-id:admin-api-apikey-secret \
-H 'Content-Type: application/json' \
-d '[{"id": "my-catalog"}]'

Deploy report​

All operations return a deploy report with per-entity-kind counts:

{
"catalog_id": "my-catalog",
"results": [
{
"entity_kind": "proxy.otoroshi.io/Route",
"created": 2,
"updated": 1,
"deleted": 0,
"errors": []
},
{
"entity_kind": "proxy.otoroshi.io/Backend",
"created": 1,
"updated": 0,
"deleted": 1,
"errors": []
}
],
"timestamp": "2024-01-01T00:00:00.000Z"
}

Scheduling​

Remote catalogs can be configured to automatically deploy at regular intervals. When scheduling is enabled, a job is registered in the Otoroshi job manager.

Two scheduling modes are available:

  • ScheduledEvery: runs the deploy at a fixed interval (e.g., every 60 seconds)
  • Cron: runs the deploy according to a cron expression (another kind is read as ScheduledEvery)
{
"scheduling": {
"enabled": true,
"kind": "ScheduledEvery",
"interval": 60000, // every 60 seconds
"initial_delay": 10000, // wait 10 seconds before first run
"deploy_args": {} // arguments passed to deploy
}
}
{
"scheduling": {
"enabled": true,
"kind": "Cron",
"cron_expression": "0 */5 * * * ?", // every 5 minutes
"deploy_args": {}
}
}

Webhook deployment​

For Git-based sources (GitHub, GitLab, Bitbucket, Gitea, Forgejo, Codeberg), you can set up webhook-triggered deployments. This allows Otoroshi to automatically deploy entities when changes are pushed to the repository.

To set this up, create a route in Otoroshi with the Remote Catalog Deploy Webhook plugin and expose it to your Git provider as a webhook URL.

Webhook plugin configuration​

{
"plugin": "cp:otoroshi.next.catalogs.RemoteCatalogDeployWebhook",
"config": {
"catalog_refs": ["my-github-catalog", "my-gitlab-catalog"], // catalogs to consider
"source_type": "github" // or "gitlab", "bitbucket", "gitea", "forgejo", "codeberg"
}
}

When a push event is received:

  1. The plugin identifies the source type and parses the webhook payload
  2. It matches the repository and branch against configured catalogs
  3. Matched catalogs are deployed automatically

GitHub webhook​

Set up a webhook in your GitHub repository settings pointing to your Otoroshi route. The plugin matches on repository.full_name and ref (branch) from the push event payload.

GitLab webhook​

Set up a webhook in your GitLab project settings. The plugin matches on project.web_url and ref from the push event payload.

Bitbucket webhook​

Set up a webhook in your Bitbucket repository settings. The plugin matches on repository.full_name and push.changes[].new.name from the push event payload.

Gitea / Forgejo / Codeberg webhook​

Set up a webhook in your Gitea, Forgejo, or Codeberg repository settings. The webhook payload format is the same across all three platforms. The plugin matches on repository.full_name and ref (branch) from the push event payload, similar to GitHub.

Other plugins​

In addition to the webhook plugin, two other plugins are available for programmatic deployment:

Remote Catalog Deploy Single​

Deploys entities from a single catalog. The request body is passed as deploy arguments.

{
"plugin": "cp:otoroshi.next.catalogs.RemoteCatalogDeploySingle",
"config": {
"catalog_ref": "my-catalog"
}
}

Remote Catalog Deploy Many​

Deploys entities from multiple catalogs. The request body should be an array of {id, args} objects. Only catalogs listed in catalog_refs are allowed.

{
"plugin": "cp:otoroshi.next.catalogs.RemoteCatalogDeployMany",
"config": {
"catalog_refs": ["catalog-1", "catalog-2", "catalog-3"]
}
}

Request body:

[
{"id": "catalog-1", "args": {}},
{"id": "catalog-2", "args": {}}
]

Admin API​

Remote catalogs are managed through the standard Otoroshi admin API:

# List all remote catalogs
curl 'http://otoroshi-api.oto.tools:8080/apis/catalogs.otoroshi.io/v1/remote-catalogs' \
-u admin-api-apikey-id:admin-api-apikey-secret

# Get a specific remote catalog
curl 'http://otoroshi-api.oto.tools:8080/apis/catalogs.otoroshi.io/v1/remote-catalogs/my-catalog' \
-u admin-api-apikey-id:admin-api-apikey-secret

# Create a remote catalog
curl -X POST 'http://otoroshi-api.oto.tools:8080/apis/catalogs.otoroshi.io/v1/remote-catalogs' \
-u admin-api-apikey-id:admin-api-apikey-secret \
-H 'Content-Type: application/json' \
-d '{
"id": "my-catalog",
"name": "My HTTP Catalog",
"enabled": true,
"source_kind": "http",
"source_config": {
"url": "https://my-server.com/entities.json"
}
}'

# Update a remote catalog
curl -X PUT 'http://otoroshi-api.oto.tools:8080/apis/catalogs.otoroshi.io/v1/remote-catalogs/my-catalog' \
-u admin-api-apikey-id:admin-api-apikey-secret \
-H 'Content-Type: application/json' \
-d '{ ... }'

# Delete a remote catalog
curl -X DELETE 'http://otoroshi-api.oto.tools:8080/apis/catalogs.otoroshi.io/v1/remote-catalogs/my-catalog' \
-u admin-api-apikey-id:admin-api-apikey-secret

Backoffice UI​

Remote catalogs can be managed from the Otoroshi admin backoffice. Navigate to the extensions section and select "Remote Catalogs". From there you can:

  • Create, edit, and delete remote catalogs
  • Configure the source type and source-specific settings
  • Deploy a catalog manually using the deploy button
  • Test a catalog with a dry-run to see what would change
  • Undeploy a catalog to remove all its managed entities
  • Configure scheduling for automatic synchronization