BotFriendly Submissions API

The Submissions API from BotFriendly — 1 operation(s) for submissions.

Operations 1

POST /submissions Submit a new service #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/botfriendly-xyz:botfriendly-xyz-submissions-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

botfriendly-xyz-submissions-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: BotFriendly Submissions API
  description: A directory of services AI agents can actually use. Query, filter, and discover bot-friendly APIs, tools, and merchants by category, interface (MCP, OpenAPI, llms.txt) and agent payment/commerce protocol.
  version: 1.0.0
  contact:
    url: https://botfriendly.xyz
servers:
- url: https://botfriendly.xyz/api/v1
tags:
- name: Submissions
paths:
  /submissions:
    post:
      operationId: submitService
      summary: Submit a new service
      description: 'Submit a service to the directory. No auth required, and no review queue: each claimed interface URL must sit on the service''s own domain or be linked from the service''s own site (the listed page or its llms.txt), and we fetch it during the request. If the MCP server, OpenAPI spec or API completes a handshake (MCP initialize succeeds or answers 401 with the MCP OAuth challenge; the spec parses; an API host — api.example.com, or a path under /api or /v1 — answers in JSON), the listing is published immediately and the response carries its slug; otherwise the submission is rejected with 422 and the probe results explaining why. Other claimed badges whose endpoint did not answer are dropped from the published listing rather than blocking it. Listing URLs that look like articles (/blog/, /news/, dated or article-title paths) are rejected, and a domain can add at most 2 listings per 24 hours and 3 in total.'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              description: has_mcp_server, has_openapi_spec or has_api must be true — an interface an agent can call. has_skill_file, has_llms_txt and has_structured_feed add badges but don't qualify a listing on their own.
              required:
              - name
              - url
              - category
              - description
              properties:
                name:
                  type: string
                url:
                  type: string
                  format: uri
                docs_url:
                  type: string
                  format: uri
                category:
                  type: string
                  enum:
                  - think
                  - see
                  - hear-speak
                  - create
                  - remember
                  - search
                  - browse
                  - communicate
                  - execute
                  - pay
                  - shop
                  - markets
                  - platforms
                  - identify
                  - monitor
                  - other
                  - locate
                  - book
                  - hire
                  - sign
                  - trade
                  - bet
                  - connect
                  - automate
                  description: Category id from /categories (a merged category's old slugs are accepted too)
                description:
                  type: string
                  maxLength: 120
                icon_url:
                  type: string
                  format: uri
                  description: Link to the service's icon. Fetched, downscaled to fit 512px, converted to PNG and re-hosted. Max 1MB. If neither icon_url nor icon_base64 is given, the service's own site is checked for a declared icon or a favicon; a listing with no icon at all is rejected.
                icon_base64:
                  type: string
                  description: 'The icon inline instead of by URL — a data: URI or a bare base64 payload, max 1MB decoded. Takes precedence over icon_url.'
                auth_method:
                  type: string
                  enum:
                  - api-key
                  - m2m-oauth
                  - bot-token
                  - wallet
                  - x402-none
                  - none
                has_mcp_server:
                  type: boolean
                mcp_server_url:
                  type: string
                has_openapi_spec:
                  type: boolean
                openapi_spec_url:
                  type: string
                has_api:
                  type: boolean
                api_url:
                  type: string
                  description: A live API base URL (api.example.com, or a path under /api or /v1) that answers in JSON
                accepts_mpp:
                  type: boolean
                accepts_x402:
                  type: boolean
                payment_protocols:
                  type: array
                  items:
                    type: string
                    enum:
                    - x402
                    - mpp
                    - l402
                    - ap2
                    - tap
                    - agent-pay
                    - ace
                    - acp
                    - ucp
                    - actp
                    - icc
                has_skill_file:
                  type: boolean
                skill_file_url:
                  type: string
                has_llms_txt:
                  type: boolean
                llms_txt_url:
                  type: string
                has_structured_feed:
                  type: boolean
                structured_feed_url:
                  type: string
                billing_model:
                  type: string
                  enum:
                  - pay-per-request
                  - pay-per-token
                  - pay-per-second
                  - subscription
                  - per-transaction
                  - free
                has_free_tier:
                  type: boolean
                tags:
                  type: array
                  items:
                    type: string
                contact_email:
                  type: string
                  format: email
      responses:
        '200':
          description: Accepted. status is 'approved' when the listing published (slug and url are set) or 'pending' in the rare case it was held for a look.
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok:
                    type: boolean
                  data:
                    type: object
                    properties:
                      id:
                        type: string
                      name:
                        type: string
                      status:
                        type: string
                        enum:
                        - approved
                        - pending
                      created_at:
                        type: string
                        format: date-time
                      slug:
                        type:
                        - string
                        - 'null'
                        description: Set when the listing published.
                      url:
                        type:
                        - string
                        - 'null'
                        description: Canonical listing URL when published.
                      probes:
                        type: array
                        description: What we fetched for each claimed interface, and what came back.
                        items:
                          $ref: '#/components/schemas/Probe'
                      dropped_flags:
                        type: array
                        description: Badges that were claimed but whose endpoint did not answer, so they are not on the listing.
                        items:
                          type: string
                      icon:
                        type: object
                        description: The stored icon and where it came from.
                        properties:
                          source:
                            type: string
                            enum:
                            - icon_url
                            - icon_base64
                            - discovered
                          found_at:
                            type:
                            - string
                            - 'null'
                            description: Set when the icon was found on the service's own site.
                          width:
                            type: integer
                          height:
                            type: integer
                  meta:
                    type: object
                    properties:
                      message:
                        type: string
        '400':
          description: Validation error — missing fields, bad category, neither has_mcp_server nor has_openapi_spec set (code no_callable_interface), a ticked badge with no URL, an interface URL on a different domain from the service, or no usable icon (icon_url unreachable, icon_base64 undecodable, and nothing found on the site)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '422':
          description: 'Not published. `error.code` names the rule: content_url (the URL is an article, not a product), domain_daily_limit (2 listings from this domain in the last 24h), domain_listing_limit (the domain already has 3 listings), no_callable_interface (no MCP server, OpenAPI spec or API completed a handshake), nothing_answered, interface_url_invalid, or admission_unavailable (try again shortly). The message says what was tried.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          description: Submission rate limit exceeded
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
      tags:
      - Submissions
components:
  schemas:
    Error:
      type: object
      description: Standard error envelope returned by every non-2xx response
      properties:
        ok:
          type: boolean
          enum:
          - false
        error:
          type: object
          properties:
            message:
              type: string
            code:
              type: string
            hint:
              type: string
          required:
          - message
    Probe:
      type: object
      description: The result of fetching one claimed interface URL.
      properties:
        flag:
          type: string
          description: Which badge was checked.
        url:
          type:
          - string
          - 'null'
          description: What we fetched.
        verdict:
          type: string
          enum:
          - pass
          - responded
          - fail
          description: 'pass: the artifact was fetched and is what it claims to be. responded: a server answered but would not show it (401). fail: nothing there, or provably not the artifact.'
        detail:
          type: string
        status:
          type: integer
        checkedAt:
          type: string
          format: date-time