CustomDomain Secure API

Edge-managed TLS certificates (SSL) for connected domains: issue, renew, import, deprovision.

GitHub OpenAPI

Operations 7

GET /connections/{id}/ssl Read the mirrored TLS certificate status for a connection's domain #
DELETE /connections/{id}/ssl Deprovision a connection's certificate (drop the mirror, stop managing) #
GET /connections/{id}/ssl:eligibility Whether a certificate can be issued for this connection yet #
POST /connections/{id}/ssl:provision Record intent to issue an edge-managed certificate #
POST /connections/{id}/ssl:renew Mark a connection's certificate for renewal #
POST /connections/{id}/ssl:import Record an operator-supplied (externally obtained) certificate's metadata #
GET /ssl List the certificates tracked for the caller's application #

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/customdomain-ai:customdomain-ai-secure-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

customdomain-ai-secure-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Customdomain Ai Secure API
  version: '1.0'
  license:
    name: Apache-2.0
    identifier: Apache-2.0
  description: 'Operations tagged Secure across 2 of this provider''s published API definitions: customdomain-ai-openapi-original.json, customdomain-ai-openapi.yml. Each path carries the servers of the definition it was published in.'
servers:
- url: https://api.customdomain.ai/v1
  description: Hosted control-plane
- url: http://localhost:8080/v1
  description: Local control-plane
security:
- apiKey: []
tags:
- name: Secure
  description: 'Edge-managed TLS certificates (SSL) for connected domains: issue, renew, import, deprovision.'
paths:
  /connections/{id}/ssl:
    get:
      operationId: getConnectionCertificate
      summary: Read the mirrored TLS certificate status for a connection's domain
      tags:
      - Secure
      description: 'The control-plane''s read-mirror of the edge certificate store for this connection''s domain. `404` when no certificate is tracked yet.


        A widget token must be the connection''s end user: a connection that names another end user than the token''s `end_user_ref`, or names one while the token names none, answers `403` `token_wrong_end_user` before anything is read or changed, and a connection that names none is any token''s. An API key, an app-scoped token and a delegated agent token are not limited by it.'
      security:
      - widgetJWT: []
      - apiKey: []
      parameters:
      - $ref: '#/components/parameters/Id'
      responses:
        '200':
          description: Certificate status
          content:
            application/json:
              schema:
                type: object
                properties:
                  certificate:
                    $ref: '#/components/schemas/Certificate'
        '401':
          $ref: '#/components/responses/Error'
        '403':
          $ref: '#/components/responses/ForbiddenOrWrongEndUser'
        '404':
          $ref: '#/components/responses/Error'
        '503':
          $ref: '#/components/responses/Error'
    delete:
      operationId: deprovisionConnectionCertificate
      summary: Deprovision a connection's certificate (drop the mirror, stop managing)
      tags:
      - Secure
      description: Drops the mirror row and clears `secure_root_domain`; the edge stops managing the certificate on its next reconcile. A row another application tracks for the same domain is left in place.
      security:
      - widgetJWT: []
      - apiKey: []
      parameters:
      - $ref: '#/components/parameters/Id'
      responses:
        '204':
          description: Deprovisioned
        '401':
          $ref: '#/components/responses/Error'
        '404':
          $ref: '#/components/responses/Error'
        '503':
          $ref: '#/components/responses/Error'
    servers:
    - url: https://api.customdomain.ai/v1
      description: Hosted control-plane
    - url: http://localhost:8080/v1
      description: Local control-plane
  /connections/{id}/ssl:eligibility:
    get:
      operationId: getConnectionCertificateEligibility
      summary: Whether a certificate can be issued for this connection yet
      tags:
      - Secure
      description: 'Advisory: a certificate is only issuable once the domain points at the edge (connection `live` or `propagating`). The widget/console uses this to gate the provision button.


        A widget token must be the connection''s end user: a connection that names another end user than the token''s `end_user_ref`, or names one while the token names none, answers `403` `token_wrong_end_user` before anything is read or changed, and a connection that names none is any token''s. An API key, an app-scoped token and a delegated agent token are not limited by it.'
      security:
      - widgetJWT: []
      - apiKey: []
      parameters:
      - $ref: '#/components/parameters/Id'
      responses:
        '200':
          description: Eligibility
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Eligibility'
        '401':
          $ref: '#/components/responses/Error'
        '403':
          $ref: '#/components/responses/ForbiddenOrWrongEndUser'
        '404':
          $ref: '#/components/responses/Error'
        '503':
          $ref: '#/components/responses/Error'
    servers:
    - url: https://api.customdomain.ai/v1
      description: Hosted control-plane
    - url: http://localhost:8080/v1
      description: Local control-plane
  /connections/{id}/ssl:provision:
    post:
      operationId: provisionConnectionCertificate
      summary: Record intent to issue an edge-managed certificate
      tags:
      - Secure
      description: Creates/updates the mirror row as `pending` + managed. The edge performs the actual ACME issuance on first handshake and reports back. Optionally sets `secure_root_domain` so the edge also secures the registrable apex. A domain has one certificate row. Returns 409 when another application tracks that row, unless this connection is the one the edge serves and the row's application serves nothing for the domain, in which case this connection takes the row over.
      security:
      - widgetJWT: []
      - apiKey: []
      parameters:
      - $ref: '#/components/parameters/Id'
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                secure_root_domain:
                  type: boolean
                  description: also secure the registrable apex.
      responses:
        '202':
          description: Provisioning requested
          content:
            application/json:
              schema:
                type: object
                properties:
                  certificate:
                    $ref: '#/components/schemas/Certificate'
        '401':
          $ref: '#/components/responses/Error'
        '404':
          $ref: '#/components/responses/Error'
        '409':
          $ref: '#/components/responses/Error'
        '503':
          $ref: '#/components/responses/Error'
    servers:
    - url: https://api.customdomain.ai/v1
      description: Hosted control-plane
    - url: http://localhost:8080/v1
      description: Local control-plane
  /connections/{id}/ssl:renew:
    post:
      operationId: renewConnectionCertificate
      summary: Mark a connection's certificate for renewal
      tags:
      - Secure
      description: Records the operator-requested renew and surfaces `renewing`. The edge's autocert manager performs the actual renewal ahead of expiry.
      security:
      - widgetJWT: []
      - apiKey: []
      parameters:
      - $ref: '#/components/parameters/Id'
      responses:
        '202':
          description: Renewal requested
          content:
            application/json:
              schema:
                type: object
                properties:
                  certificate:
                    $ref: '#/components/schemas/Certificate'
        '401':
          $ref: '#/components/responses/Error'
        '404':
          $ref: '#/components/responses/Error'
        '503':
          $ref: '#/components/responses/Error'
    servers:
    - url: https://api.customdomain.ai/v1
      description: Hosted control-plane
    - url: http://localhost:8080/v1
      description: Local control-plane
  /connections/{id}/ssl:import:
    post:
      operationId: importConnectionCertificate
      summary: Record an operator-supplied (externally obtained) certificate's metadata
      tags:
      - Secure
      description: Mirrors the status + validity window of an external certificate for display (`managed=false`, so the edge does not ACME-renew it). Private key material is an edge concern and is not handled here. Returns 409 when another application tracks the domain's certificate row, unless this connection is the one the edge serves and the row's application serves nothing for the domain, in which case this connection takes the row over.
      security:
      - widgetJWT: []
      - apiKey: []
      parameters:
      - $ref: '#/components/parameters/Id'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                issuer:
                  type: string
                not_before:
                  type: string
                  format: date-time
                  description: RFC3339.
                not_after:
                  type: string
                  format: date-time
                  description: RFC3339.
      responses:
        '200':
          description: Imported
          content:
            application/json:
              schema:
                type: object
                properties:
                  certificate:
                    $ref: '#/components/schemas/Certificate'
        '400':
          $ref: '#/components/responses/Error'
        '401':
          $ref: '#/components/responses/Error'
        '404':
          $ref: '#/components/responses/Error'
        '409':
          $ref: '#/components/responses/Error'
        '503':
          $ref: '#/components/responses/Error'
    servers:
    - url: https://api.customdomain.ai/v1
      description: Hosted control-plane
    - url: http://localhost:8080/v1
      description: Local control-plane
  /ssl:
    get:
      operationId: listCertificates
      summary: List the certificates tracked for the caller's application
      tags:
      - Secure
      security:
      - widgetJWT: []
      - apiKey: []
      responses:
        '200':
          description: Certificates
          content:
            application/json:
              schema:
                type: object
                properties:
                  certificates:
                    type: array
                    items:
                      $ref: '#/components/schemas/Certificate'
        '401':
          $ref: '#/components/responses/Error'
        '503':
          $ref: '#/components/responses/Error'
    servers:
    - url: https://api.customdomain.ai/v1
      description: Hosted control-plane
    - url: http://localhost:8080/v1
      description: Local control-plane
components:
  parameters:
    Id:
      name: id
      in: path
      required: true
      schema:
        type: string
  schemas:
    Eligibility:
      type: object
      required:
      - domain
      - eligible
      properties:
        domain:
          type: string
        eligible:
          type: boolean
        reason:
          type: string
          description: why not, when ineligible; empty when eligible.
    Certificate:
      type: object
      required:
      - domain
      - status
      - managed
      properties:
        id:
          type: string
        domain:
          type: string
        application_id:
          type: string
        status:
          $ref: '#/components/schemas/CertStatus'
        issuer:
          type: string
        not_before:
          type: string
          format: date-time
        not_after:
          type: string
          format: date-time
        last_error:
          type: string
          description: most recent issuance/renewal failure; empty when healthy.
        managed:
          type: boolean
          description: true = edge auto-manages (ACME); false = operator-imported.
        renew_after:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
    CertStatus:
      type: string
      enum:
      - pending
      - issued
      - renewing
      - failed
      - revoked
    Error:
      type: object
      required:
      - code
      - title
      properties:
        code:
          type: string
          description: stable machine code, e.g. invalid_request, unauthorized, not_found, service_unavailable, internal_error
        title:
          type: string
          description: human-readable summary
        details:
          type: string
          description: optional extra context
  responses:
    Error:
      description: 'Error envelope: {code, title, details}.'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    ForbiddenOrWrongEndUser:
      description: '`forbidden`: the credential may not do this. `token_wrong_end_user`: a widget token that is not this connection''s end user (the connection names another end user than the token''s `end_user_ref`, or names one while the token names none); nothing is read or changed, and the answer shows nothing of the connection. Mint the token with the end user''s `end_user_ref`.'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  securitySchemes:
    managementKey:
      type: http
      scheme: bearer
      description: Operator management key. Gates provisioning + reads across tenants.
    provisionSecret:
      type: apiKey
      in: header
      name: X-Provision-Secret
      description: Narrow secret held by the customer console's server, for signup provisioning and its other server to server calls (also accepted as a Bearer token, except on POST /audit, where a Bearer is always a tenant credential).
    apiKey:
      type: http
      scheme: bearer
      description: Long-lived tenant API key, cd_live_… (production) or cd_test_… (staging, development), stored hashed. Keys created before the switch to cd_ start with sk_live_… / sk_test_… and are still accepted. Scoped to the owning application's tenant.
    widgetJWT:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: Short-lived widget JWT minted server-side via POST /v1/tokens. Scoped to one application (and optionally one domain).
    browserSession:
      type: http
      scheme: bearer
      description: The session token of one cloud browser sign in, returned by `POST /browser-sessions:redeem`. It binds one session, one connection and one workspace, lives at most as long as the session, and stops working the moment the session ends. It lives in the popup's memory only.
    agentToken:
      type: oauth2
      description: 'A delegated agent access token: an ES256 JWT that lives 15 minutes, sent as a bearer token. A person approves an agent in the console and the agent exchanges its authorization code (with PKCE) at the token endpoint. The token carries the workspace, the one application the grant is bound to, the grant, the approved scopes and its audience, and is verified against `/.well-known/jwks.json`. A route that accepts it lists the scope it needs; a token without the scope is refused with `403`, and a connection or order of another application answers `404`.'
      flows:
        authorizationCode:
          authorizationUrl: https://api.customdomain.ai/oauth/agent/authorize
          tokenUrl: https://api.customdomain.ai/oauth/agent/token
          refreshUrl: https://api.customdomain.ai/oauth/agent/token
          scopes:
            domains:read: Look at availability, connections, records, certificates, diagnoses, orders and the billing standing.
            domains:connect: Connect a domain, recheck it, reapply its records and start a one click setup.
            domains:disconnect: Remove a connected domain. The call must name the domain.
            domains:purchase: Buy a domain, up to the grant's monthly spend cap.
x-refined-from:
- customdomain-ai-openapi-original.json
- customdomain-ai-openapi.yml