Apiable

Automation

CI/CD documentation sync

Publish your OpenAPI specification to Apiable from your CI/CD pipeline through the Platform API. Catalog-led portals publish to the API's catalog entry; other portals update a plan's Continuous Delivery documentation entry.

Keep your API Portal documentation in step with your code. Instead of uploading a new OpenAPI specification by hand after each release, your pipeline publishes it through the Platform API, so the reference your developers read matches what you deployed.

What does CI/CD documentation sync do?

It publishes your current OpenAPI specification to Apiable on each deploy. Apiable reads the specification from a URL and shows it in your API Portal, so the reference stays in step with your code.

The flow is the same whichever CI/CD system you use:

  1. Your pipeline builds or fetches the specification.
  2. It exchanges your client ID and secret for an access token.
  3. It uploads the specification to Apiable, unless it is already at a URL Apiable can read.
  4. It tells Apiable where the new specification is.

Which flow does your portal use?

It depends on where your portal's documentation comes from. Portals whose documentation follows the API Catalog publish to the API's catalog entry. Other portals update a documentation entry on a plan. A plan's Documentation tab tells you which you have.

What a plan's Documentation tab offersYour portal isPublish with
Continuous Delivery as a source for an entryPlan-ledPATCH /api/docs/{docId} on the plan's Continuous Delivery entry.
Generated at plan level, or Follow the catalog for an APICatalog-ledPATCH /api/catalogue-apis/stacks/{stackId} on the API's catalog entry.

On a catalog-led portal, a write to a plan's documentation for a catalog API is refused with a message that names the catalog endpoint to use instead.

How do you upload the specification?

If the specification is not already at a URL Apiable can read, upload it with POST /api/files/upload as a multipart form field named file. Apiable returns 202 with the url to publish.

POST /api/files/upload
curl -X POST "https://your-portal.api.apiable.io/api/files/upload" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -F "file=@openapi.json;type=application/json"

The file must be under 1 MB. For YAML, send it with the type application/x-yaml.

You can skip the upload and send a URL where you host the specification yourself. That URL must be publicly readable, both by Apiable and by developers' browsers when they open the reference in your API Portal.

How do you publish to the API Catalog from CI?

Find the API's stack id once, then send documentationUrl to PATCH /api/catalogue-apis/stacks/{stackId} on every run. Apiable re-reads the specification and records a new version only when its content changed. The stack id stays the same across publishes.

PATCH /api/catalogue-apis/stacks/{stackId}
  1. List the catalog with GET /api/catalogue-apis. Add ?integrationId= with the API's id on your gateway to find one entry.
  2. Copy the entry's ancestorCatalogueApiId. That is the stack id to use in your pipeline.
  3. On each run, upload the specification or build its URL, then send it as documentationUrl:
curl -X PATCH "https://your-portal.api.apiable.io/api/catalogue-apis/stacks/$STACK_ID" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d "{\"documentationUrl\": \"$SPEC_URL\"}"

APIs on a connected gateway appear in the catalog on their own. For an API that no gateway reports, create its entry once with POST /api/catalogue-apis, giving a name and, optionally, an integrationId to look it up by later.

How do you update a plan's Continuous Delivery entry?

Point the entry at the new specification with PATCH /api/docs/{docId}, using a JSON Patch that replaces its url. You get the id from the entry on the plan's Documentation tab.

PATCH /api/docs/{docId}
  1. On the plan's Documentation tab, add a documentation entry and set its source to Continuous Delivery. Save the plan.
  2. Copy the entry's id. The entry shows it as ID: with a copy button.
  3. On each run, upload the specification or build its URL, then patch the entry:
curl -X PATCH "https://your-portal.api.apiable.io/api/docs/$DOC_ID" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -H "X-API-Version: 2024-09-25" \
  -d "[{\"op\": \"replace\", \"path\": \"/url\", \"value\": \"$SPEC_URL\"}]"

See Plan documentation for the other documentation sources.

How do you run it in GitHub Actions?

Add a job step that gets a token, uploads the specification, and publishes it with curl. The example below publishes to an API Catalog entry. For a plan-led portal, swap the last call for the PATCH /api/docs/{docId} call above.

- name: Publish the OpenAPI specification to Apiable
  env:
    APIABLE_CLIENT_ID: ${{ secrets.APIABLE_CLIENT_ID }}
    APIABLE_CLIENT_SECRET: ${{ secrets.APIABLE_CLIENT_SECRET }}
    APIABLE_URL: https://your-portal.api.apiable.io
    STACK_ID: your-catalog-stack-id
  run: |
    ACCESS_TOKEN=$(curl -sf -X POST "https://developer.apiable.io/api/oauth2/token" \
      -H "Content-Type: application/x-www-form-urlencoded" \
      -d grant_type=client_credentials \
      -d client_id="$APIABLE_CLIENT_ID" \
      -d client_secret="$APIABLE_CLIENT_SECRET" | jq -r .access_token)
    SPEC_URL=$(curl -sf -X POST "$APIABLE_URL/api/files/upload" \
      -H "Authorization: Bearer $ACCESS_TOKEN" \
      -F "file=@openapi.json;type=application/json" | jq -r .url)
    curl -sf -X PATCH "$APIABLE_URL/api/catalogue-apis/stacks/$STACK_ID" \
      -H "Authorization: Bearer $ACCESS_TOKEN" \
      -H "Content-Type: application/json" \
      -d "{\"documentationUrl\": \"$SPEC_URL\"}"

Store the client ID and secret as repository or organization secrets, never in the workflow file. The step assumes the specification is at openapi.json in the working directory.

How does the pipeline authenticate?

With your Platform API credentials. The pipeline exchanges the client ID and secret for an access token at https://developer.apiable.io/api/oauth2/token and sends it as a Bearer token. Tokens expire, so request one per run.

The same credentials work for every Platform API call. See Automation for the token request and the rest of the Platform API.

Troubleshooting

Match the response to the fix.

What you getWhat to do
401 with "error": "invalid_token"Send the access_token from the token response as the Bearer value, not the client secret. Request a fresh token if it expired.
403 with "error": "subscription_key_unavailable"Your Platform API subscription on developer.apiable.io is inactive or its key was revoked. Contact Apiable.
"File size exceeds the limit: 1MB"Upload a file under 1 MB, or host the specification yourself and send its URL.
The upload call fails with a server errorHost the specification at a public URL and send that URL instead, and tell Apiable support.
400 saying the API "takes its documentation from the API Catalogue on this portal"Your portal is catalog-led. Publish to the catalog entry the message names, with PATCH /api/catalogue-apis/stacks/{stackId}.
409 saying a catalogue API with that integrationId already existsThe entry exists already. Patch it instead of creating a second one.
The publish succeeds but the portal shows the old specificationCheck that documentationUrl or the patched url points at the new file, and that Apiable can read that URL.

Where to next