App catalog
The APIANT app catalog lists every app you can connect, and a public unauthenticated JSON feed at app.apiant.ai/catalog/v1 serves it with each app's triggers and actions.
The APIANT app catalog lists the apps you can connect, each with its triggers and actions. Browse it at apiant.ai/apps, where each app has its own page (for example https://apiant.ai/connections/slack), or read it as JSON from the public catalog feed documented below.
Every app in the feed can be picked inside the product: the feed uses the same visibility rule as the app picker in APIANT, so an app you find here is one you can connect. To connect one, see Connecting accounts. If an app or an operation you need is missing, see Build a connector, action or trigger.
What an app entry holds
| Field | Type | Meaning |
|---|---|---|
slug | string | The app's public identifier, lowercase letters, digits and hyphens. The only handle the feed exposes. |
name | string | Display name. |
description | string | One-paragraph description of the app. |
category | string or null | App category. null when no category has been set yet. |
auth_type | string | How the app connects. Values seen on 2026-09-15: api_key, none, oauth_v2, managed_auth, token_mint. |
app_domain | string | The vendor's domain, for example slack.com. |
logo_url | string | URL of the app icon (/catalog/v1/apps/{slug}/logo). |
connect_url | string | Sign-up link that starts on this app: https://app.apiant.ai/signup?app={slug}. |
last_updated | string | RFC 3339 time the connector or one of its listed operations was last edited. Informational; use etag to detect change. |
etag | string | Validator for this app's entry, including its operations. |
retired | boolean | true when the app has been withdrawn. A retired app stays in the feed with this marker for a retirement window (180 days by default), then drops out. |
retired_at | string | Present only when retired is true. |
tier | string | Popularity band: A, B, C, or D for unranked. |
sort_order | integer | Position 1 to N in the feed's popularity ordering. It shifts when apps enter or leave the feed, so treat it as a sort key, not an identifier. |
trigger_count | integer | Number of triggers. |
action_count | integer | Number of actions. |
last_op_modified | string or null | When a trigger or action on this app was last added or edited. null when the app has none. |
triggers | array | Detail and bulk responses only. Each item is {name, description}. |
actions | array | Detail and bulk responses only. Each item is {name, description}. |
The feed publishes names and descriptions of operations only. It does not expose endpoints, request bodies, credentials or internal identifiers.
Catalog feed endpoints
Base URL: https://app.apiant.ai/catalog/v1
| Method and path | Returns | Cache-Control | Default rate limit per IP |
|---|---|---|---|
GET /apps | Every app, summary fields only | public, max-age=300, stale-while-revalidate=3600 | 300 per 5 minutes, shared with /apps/{slug} |
GET /apps/{slug} | One app with its triggers and actions | public, max-age=300, stale-while-revalidate=3600 | 300 per 5 minutes, shared with /apps |
GET /apps/{slug}/logo | The app icon bytes | public, max-age=86400, immutable | 1,000 per 5 minutes |
GET /bulk | Every app with its triggers and actions, built once a day | public, max-age=3600 | 10 per hour |
The rate limits are defaults and can change. IPv6 clients are counted per /64 network.
Authentication
None. The feed is public, read-only, and sends Access-Control-Allow-Origin: *, so a browser page on any site can read it directly.
Parameters
The routes take no query parameters and do not paginate. GET /apps returns the whole catalog in one response; count equals the length of apps. The only path parameter is {slug}.
GET routes also answer HEAD. Any other method returns 405 with Allow: GET, HEAD.
Caching and conditional requests
Every JSON response carries an ETag. Send it back in If-None-Match and the feed answers 304 Not Modified with no body when nothing changed.
/bulk is a stored artifact rebuilt daily at 04:00 UTC; its generated_at field shows when. It is sent gzip-compressed when your client sends Accept-Encoding: gzip, and uncompressed otherwise. Prefer /bulk over calling /apps/{slug} once per app.
Errors
| Status | When | Body |
|---|---|---|
304 | If-None-Match matched the current ETag | none |
404 | Unknown slug, a slug with uppercase or other invalid characters, an app that is not in the feed, or an app with no logo | none |
405 | A method other than GET or HEAD | method not allowed |
429 | You passed the rate limit for that route | rate limit exceeded, with a Retry-After header in seconds |
503 | The feed cannot produce a body it trusts, or the daily bulk artifact is not built yet or lists an app the feed no longer serves | {"error":"catalog feed temporarily unavailable"}, with Retry-After (60 or 300 seconds) |
The feed never returns 200 with an empty app list. If the catalog cannot be read it serves the last good response or a 503.
Examples
List every app
$ curl -s https://app.apiant.ai/catalog/v1/apps
Response, trimmed to one app (captured 2026-09-15; the count values are illustrative):
{
"generated_at": "2026-09-15T18:31:52Z",
"count": 1,
"apps": [
{
"slug": "slack",
"name": "Slack",
"description": "Slack is a messaging platform for teams. Post messages, manage channels, users, reminders, and react to events via the Slack Web API.",
"category": "Communication",
"auth_type": "oauth_v2",
"app_domain": "slack.com",
"logo_url": "https://app.apiant.ai/catalog/v1/apps/slack/logo",
"connect_url": "https://app.apiant.ai/signup?app=slack",
"last_updated": "2026-08-27T13:02:59Z",
"etag": "\"80515b2820c0614d\"",
"retired": false,
"tier": "A",
"sort_order": 3,
"trigger_count": 2,
"action_count": 2,
"last_op_modified": "2026-08-27T13:02:59Z"
}
]
}
Get one app with its triggers and actions
$ curl -s https://app.apiant.ai/catalog/v1/apps/slack
Response, trimmed to two triggers and two actions (captured 2026-09-15; the count values are illustrative):
{
"slug": "slack",
"name": "Slack",
"auth_type": "oauth_v2",
"trigger_count": 2,
"action_count": 2,
"triggers": [
{ "name": "New Channel", "description": "Triggers when a new channel is created in the workspace." },
{ "name": "New Channel (instant)", "description": "Triggers when a new channel is created. Events API event: channel_created." }
],
"actions": [
{ "name": "Add Bookmark", "description": "Add a bookmark to a channel." },
{ "name": "Add Reaction", "description": "Add an emoji reaction to a message." }
]
}
The detail response also carries every summary field shown in the list example; they are omitted here for length.
The same call from JavaScript in a browser or Node 18+:
// No API key: the feed is public and allows any origin.
const res = await fetch("https://app.apiant.ai/catalog/v1/apps/slack");
if (res.status === 404) throw new Error("slack is not in the catalog");
const app = await res.json();
console.log(app.name, app.triggers.length, "triggers,", app.actions.length, "actions");
Skip the download when nothing changed
$ curl -s -o /dev/null -w "%{http_code}\n" \
-H 'If-None-Match: "80515b2820c0614d"' \
https://app.apiant.ai/catalog/v1/apps/slack
304
Download the whole catalog once a day
$ curl -s --compressed https://app.apiant.ai/catalog/v1/bulk -o apiant-catalog.json
--compressed asks for gzip and decompresses it. The file has the shape {generated_at, count, apps}, where each app carries the summary fields plus triggers and actions.