Keploy Apps API

The Apps API from Keploy — 3 operation(s) for apps.

Operations 6

GET /apps List apps #
POST /apps Create an app #
GET /apps/{appId} Get an app #
PUT /apps/{appId} Update an app #
DELETE /apps/{appId} Delete an app #
GET /apps/{appId}/schema-coverage Get schema coverage #

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/keploy-apps-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

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

keploy-apps-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Keploy Public Apps API
  version: 1.0.0
  description: 'Programmatic access to the Keploy platform for CI/CD pipelines, scripts,

    and AI agents. See the full guide at

    .


    **Scopes and 403 errors:** Every endpoint requires a minimum scope (`read`,

    `write`, or `admin`). If the API key lacks the required scope the server

    returns `403 Forbidden` with error code `INSUFFICIENT_SCOPE`.'
  contact:
    email: support@keploy.io
  termsOfService: https://keploy.io/terms
servers:
- url: https://api.keploy.io/client/v1
  description: Production
- url: https://api.staging.keploy.io/client/v1
  description: Staging
security:
- apiKeyAuth: []
tags:
- name: Apps
paths:
  /apps:
    get:
      operationId: listApps
      x-required-scope: read
      summary: List apps
      description: 'Returns the tenant''s apps. Use the optional `q` query parameter to name-filter (case-insensitive substring, e.g. `?q=orderflow` → apps whose name contains ''orderflow''); without it the full paginated list is returned. Callers that know the app''s folder / repo name should pass it as `q` to avoid paginating through hundreds of apps. Requires scope: `read`.'
      tags:
      - Apps
      parameters:
      - $ref: '#/components/parameters/offset'
      - $ref: '#/components/parameters/limit'
      - in: query
        name: q
        description: Case-insensitive substring to filter app names by. Omit to list all apps.
        required: false
        schema:
          type: string
      responses:
        '200':
          description: App list
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EnvelopeAppList'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/InternalError'
    post:
      operationId: createApp
      x-required-scope: write
      summary: Create an app
      description: 'Requires scope: `write`.'
      tags:
      - Apps
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateAppRequest'
      responses:
        '201':
          description: App created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EnvelopeApp'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '409':
          description: App already exists
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EnvelopeError'
        '429':
          $ref: '#/components/responses/RateLimited'
        '413':
          $ref: '#/components/responses/PayloadTooLarge'
        '500':
          $ref: '#/components/responses/InternalError'
  /apps/{appId}:
    parameters:
    - $ref: '#/components/parameters/appId'
    get:
      operationId: getApp
      x-required-scope: read
      summary: Get an app
      description: 'Requires scope: `read`.


        Optional `fields` query parameter projects the response to a subset

        of properties — useful for MCP / AI callers that only need a few

        identity fields (e.g. `["name","namespace","deployment","origin.clusterName"]`)

        and don''t want the full ~16k-token embedded schema in their context.

        Supports dotted paths for nested objects. Omitting `fields` returns

        the full envelope as before.'
      tags:
      - Apps
      parameters:
      - name: fields
        in: query
        required: false
        description: 'Optional comma-separated list of response field paths to keep.

          Each path is dotted (e.g. `origin.clusterName`). When set, the

          response is projected to just those paths inside `data`; the

          envelope shape (`{data, meta?}`) is preserved.

          '
        schema:
          type: array
          items:
            type: string
        style: form
        explode: false
      responses:
        '200':
          description: App detail
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EnvelopeApp'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/InternalError'
    put:
      operationId: updateApp
      x-required-scope: write
      summary: Update an app
      description: 'Requires scope: `write`.'
      tags:
      - Apps
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateAppRequest'
      responses:
        '200':
          description: App updated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EnvelopeApp'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/RateLimited'
        '413':
          $ref: '#/components/responses/PayloadTooLarge'
        '500':
          $ref: '#/components/responses/InternalError'
    delete:
      operationId: deleteApp
      x-required-scope: admin
      summary: Delete an app
      description: 'Requires scope: `admin`.'
      tags:
      - Apps
      responses:
        '200':
          description: App deleted
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EnvelopeDeleted'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/InternalError'
  /apps/{appId}/schema-coverage:
    parameters:
    - $ref: '#/components/parameters/appId'
    get:
      operationId: getSchemaCoverage
      x-required-scope: read
      summary: Get schema coverage
      description: 'Requires scope: `read`.'
      tags:
      - Apps
      responses:
        '200':
          description: Schema coverage data
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Envelope'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/InternalError'
components:
  parameters:
    limit:
      name: limit
      in: query
      description: 'Page size. Defaults to 20 when omitted; `limit=0` is also treated

        as "use default" (so existing clients sending an explicit zero

        keep the prior behaviour). Capped at 100 — the spec rejects

        higher values with 400 so callers fail loudly instead of being

        silently clamped, and the handler enforces the same cap as a

        defence-in-depth fallback.

        '
      schema:
        type: integer
        default: 20
        minimum: 0
        maximum: 100
    appId:
      name: appId
      in: path
      required: true
      schema:
        type: string
    offset:
      name: offset
      in: query
      description: 'Zero-based pagination offset. Negative values are rejected — the

        handler also clamps to 0 as a defence-in-depth fallback.

        '
      schema:
        type: integer
        default: 0
        minimum: 0
  schemas:
    Envelope:
      type: object
      properties:
        data: {}
        error:
          $ref: '#/components/schemas/APIError'
        meta:
          $ref: '#/components/schemas/Meta'
    EnvelopeAppList:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/AppResponse'
        error:
          $ref: '#/components/schemas/APIError'
        meta:
          $ref: '#/components/schemas/Meta'
    APIError:
      type: object
      properties:
        code:
          type: string
        message:
          type: string
        details:
          type: array
          items:
            $ref: '#/components/schemas/ErrorDetail'
    EnvelopeDeleted:
      type: object
      properties:
        data:
          type: object
          properties:
            deleted:
              type: boolean
        error:
          $ref: '#/components/schemas/APIError'
        meta:
          $ref: '#/components/schemas/Meta'
    App:
      type: object
      additionalProperties: true
      properties:
        id:
          type: string
        name:
          type: string
        endpoint:
          type: string
        cid:
          type: string
        auth:
          $ref: '#/components/schemas/Auth'
        appLevelCustomVariables:
          type: array
          description: Global key→value pairs shared across every suite. Reference in step bodies/urls/headers/asserts as `{{key}}`. Patch one variable at a time via updateApp.app_level_custom_variables (singular ExtractInput with Action add/update/delete).
          items:
            type: object
            properties:
              key:
                type: string
              value:
                type: string
        ignoreEndpoints:
          type: array
          items:
            type: string
        timeout:
          type: integer
          description: Per-request timeout in seconds (0 = use default 30)
        rateLimit:
          type: integer
          description: Max requests/sec the runner will fire (0 = unlimited)
        disableSchemaAssertion:
          type: boolean
        webhookUrl:
          type: string
        created_at:
          type: integer
          format: int64
        updated_at:
          type: integer
          format: int64
    AppResponse:
      type: object
      description: Lightweight app shape returned by listApps. Single-app reads (getApp/updateApp/createApp) return the full `App` schema below instead.
      properties:
        id:
          type: string
        name:
          type: string
        endpoint:
          type: string
        cid:
          type: string
        created_at:
          type: integer
          format: int64
        updated_at:
          type: integer
          format: int64
    EnvelopeError:
      type: object
      properties:
        error:
          $ref: '#/components/schemas/APIError'
        meta:
          $ref: '#/components/schemas/Meta'
    EnvelopeApp:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/App'
        error:
          $ref: '#/components/schemas/APIError'
        meta:
          $ref: '#/components/schemas/Meta'
    ErrorDetail:
      type: object
      properties:
        field:
          type: string
        message:
          type: string
    UpdateAppRequest:
      type: object
      description: 'RENAMING APPS IS PROHIBITED. The app name is the immutable

        identifier devs and CI scripts type into commands; the API

        rejects every attempt to change it. Do not try to work around

        this with raw curl, GraphQL, or any other path — they all

        fail. If a different name is required, create a new app and

        migrate the test suites manually.


        Other than that: PATCH-style update — only the fields you set

        get written. Use this to fix app-level config when a test

        suite run fails on a recoverable misconfiguration:

        wrong/expired bearer token (auth), missing global variable

        (app_level_custom_variables), wrong rate limit, etc. After

        updating, re-run `keploy create-test-suite` (or call

        create_test_suite again); the CLI re-fetches the app each

        invocation so it picks up the patched config without any extra

        plumbing.


        Concrete behavior on rename attempts: `name` is not part of

        this request schema, so a top-level `name` field is rejected

        during JSON decoding (unknown fields are disallowed) before

        any other validation runs. The same prohibition is enforced

        independently in the validation layer for non-HTTP callers.

        '
      properties:
        endpoint:
          type: string
        schema:
          type: string
        docs:
          type: string
          description: Free-form developer docs. Used by AI as additional context when authoring suites.
        api_examples:
          type: string
          description: Sample request/response pairs the AI consults when authoring suites.
        brd:
          type: string
          description: Business requirements document content the AI uses for context.
        prd:
          type: string
          description: Product requirements document content the AI uses for context.
        postman:
          type: string
          description: Postman collection JSON the AI parses for endpoint shapes / examples.
        code_snippet:
          type: string
          description: Server code snippet the AI uses for endpoint context.
        main_curl:
          type: string
          description: Reference curl that drives generation when no schema is available.
        graphql_schema:
          type: string
          description: GraphQL schema (SDL) the AI uses when generating GraphQL suites.
        country:
          type: string
          description: Two-letter country code controlling data-residency-affected behavior. Rarely set.
        webhook_url:
          type: string
        auth:
          $ref: '#/components/schemas/Auth'
          description: Replaces the app's full auth config. To clear auth, set { authtype "None" }.
        app_level_custom_variables:
          type: object
          description: Add / update / delete a SINGLE global variable. The Action enum on the embedded ExtractInput controls the operation. To set multiple variables, call updateApp once per variable.
          properties:
            key:
              type: string
            value:
              type: string
            type:
              type: string
            level:
              type: string
            action:
              type: string
              enum:
              - add
              - update
              - delete
        app_level_custom_function:
          type: object
          description: Register a JS function devs can reference from suite step templates. Key uniquely identifies the function; CustomFunction is the JS source.
          properties:
            Key:
              type: string
            CustomFunction:
              type: string
        labels:
          type: array
          description: 'Add or update labels on the app. New labels (no `id`)

            require both `name` and `color`; updates to existing

            labels (with `id`) require at least one of `name`/`color`.

            '
          items:
            type: object
            properties:
              id:
                type: string
                description: Existing label ID. Omit to add a new label.
              name:
                type: string
              color:
                type: string
        ignore_endpoints:
          type: array
          description: Endpoint patterns the runner skips when generating / running suites.
          items:
            type: string
        max_test_suites:
          type: integer
          description: Cap on how many suites generate-tests will mint at once. Server default applies if omitted.
        rate_limit:
          type: integer
          description: Requests-per-second cap the runner applies to outbound calls during runs.
        enable_pre_hook:
          type: boolean
          description: Run the pre-step hook before each test step.
        enable_post_hook:
          type: boolean
          description: Run the post-step hook after each test step.
        private_mode:
          type: boolean
          description: Restrict app visibility to the authenticated user only.
        disable_schema_assertion:
          type: boolean
    Meta:
      type: object
      properties:
        request_id:
          type: string
        trace_id:
          type: string
        timestamp:
          type: string
          format: date-time
        pagination:
          $ref: '#/components/schemas/Pagination'
    Pagination:
      type: object
      properties:
        has_next_page:
          type: boolean
        has_previous_page:
          type: boolean
        next_cursor:
          type:
          - string
          - 'null'
        previous_cursor:
          type:
          - string
          - 'null'
        total_count:
          type:
          - integer
          - 'null'
    CreateAppRequest:
      type: object
      required:
      - name
      description: 'Body for POST /apps. Name is required and immutable — pick it

        carefully because updateApp deliberately rejects renames (the

        app name is the stable identifier devs and CI scripts type

        into commands; renaming would silently break references).

        Auth and the runtime-config fields can be set at creation so

        you don''t have to follow up with an updateApp.

        '
      properties:
        name:
          type: string
          description: App name. IMMUTABLE — cannot be changed via updateApp.
        endpoint:
          type: string
        schema:
          type: string
          description: OpenAPI/Swagger doc the validators use to suggest test cases.
        docs:
          type: string
          description: Free-form developer docs the AI uses as additional context.
        api_examples:
          type: string
          description: Sample request/response pairs the AI consults when authoring suites.
        webhook_url:
          type: string
          description: Optional webhook URL invoked at run lifecycle events.
        max_test_suites:
          type: integer
          description: Cap on how many suites generate-tests will mint at once. Server default applies if omitted.
        disable_schema_assertion:
          type: boolean
        auth:
          $ref: '#/components/schemas/Auth'
          description: 'Authentication config the runner injects on every step

            request. Validation matches the GraphQL CreateApp resolver

            (and atg.Test''s runtime check) — set authtype="None" for

            no auth, or supply the type-specific fields (BasicAuth

            needs Username+Password, BearerToken needs Token, etc.).

            '
    Auth:
      type: object
      description: Authentication configuration for test execution. The runner injects the matching headers on every step request.
      properties:
        AuthType:
          type: string
          enum:
          - BearerToken
          - BasicAuth
          - APIKeyAuth
          - CookieAuth
          - LoginCurl
          - None
        BearerToken:
          type: object
          properties:
            Token:
              type: string
        BasicAuth:
          type: object
          properties:
            Username:
              type: string
            Password:
              type: string
        APIKeyAuth:
          type: object
          properties:
            Key:
              type: string
            Value:
              type: string
        Cookie:
          type: object
          properties:
            Cookie:
              type: string
        LoginCurl:
          type: object
          properties:
            Curl:
              type: string
              description: Raw curl command that performs the login. Runner executes once at session start and parses the response.
            CurlResponseType:
              type: string
              description: How to interpret the response (jwt | cookie).
            JwtPath:
              type: string
              description: JSONPath into the response that yields the bearer token.
  responses:
    Unauthorized:
      description: Authentication required
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/EnvelopeError'
    PayloadTooLarge:
      description: 'Request body exceeded the 5 MB cap enforced by the validation

        middleware (and decodeJSONBody as defence-in-depth). Returned

        for any body-accepting operation when the wrapped reader trips

        MaxBytesReader. The body is the standard error envelope with

        code `VALIDATION_ERROR`.

        '
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/EnvelopeError'
    RateLimited:
      description: Too many requests
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/EnvelopeError'
    BadRequest:
      description: Validation error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/EnvelopeError'
    InternalError:
      description: Internal server error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/EnvelopeError'
    Forbidden:
      description: 'Insufficient scope or role (error code: INSUFFICIENT_SCOPE)'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/EnvelopeError'
    NotFound:
      description: Resource not found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/EnvelopeError'
  securitySchemes:
    apiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
      description: Personal Access Token (`kep_`-prefixed). Generate from Settings > API Keys.