Skip to main content

Push API specs from CI

If the files that describe your APIs already live in your repository — an OpenAPI spec, your gateway configuration, a Postman collection — your pipeline can send them to Levo on every merge. Levo stays current without anyone uploading anything by hand.

The script reads files your CI has already checked out. It never connects to your gateway, and it needs no credentials beyond a Levo key.

What you need

  • A repository with at least one of: an OpenAPI spec, a Kong file, a Postman collection
  • Python 3.8 or newer on the runner — GitHub's ubuntu-latest already has it
  • A Levo authorization key and organization id

Set it up

Get your Levo credentials.

In Levo, open Settings → Keys and create an authorization key. Your organization id is in Settings → Organization.

Add them as repository secrets.

In GitHub, go to Settings → Secrets and variables → Actions and add two secrets:

SecretValue
LEVO_AUTH_KEYthe authorization key you just created
LEVO_ORG_IDyour organization id

Add the script to your repository.

Download levo_push.py and commit it — .levo/levo_push.py is a good home. It is one file and its only dependency is requests.

Create the workflow.

Add .github/workflows/levo-push.yml:

name: Push API specs to Levo

on:
push:
branches: [main]
paths:
- 'kong/**'
- 'specs/**'
workflow_dispatch:

jobs:
push:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- run: pip install requests

- name: Push API specs to Levo
run: |
python .levo/levo_push.py \
--file "kong/*.json" \
--file "specs/*.yaml" \
--app payments-api
env:
LEVO_AUTH_KEY: ${{ secrets.LEVO_AUTH_KEY }}
LEVO_ORG_ID: ${{ secrets.LEVO_ORG_ID }}
LEVO_BASE_URL: https://api.levo.ai
LEVO_ENV_NAME: default

Change the --file paths to match your repository, and set LEVO_BASE_URL to the Levo API address for your account. The paths: filter keeps the workflow from running on commits that change nothing Levo cares about.

Merge, and watch the step.

INFO pushing kong/kong-services.json
INFO kong-services.json: gateway kong-prod: 25 labels applied to 39 endpoints;
40/42 routes usable; 3 endpoints created in New Kong Endpoints (kong-prod)
INFO pushing specs/openapi.yaml
INFO openapi.yaml: spec imported into payments-api (schema 41c9…)
INFO 2 of 2 file(s) pushed

The step fails if any file does not land, so a broken push shows up as a red build rather than a quietly stale inventory.

What the script sends

Each file is identified by what is inside it, not by its name — so it does not matter what your files are called.

The file containsTreated asWhat happens in Levo
format_version and source.kind: KONGKong fileIts tags become labels on your discovered endpoints
openapi: or swagger:OpenAPI specEndpoints are added to the application you name
info._postman_idPostman collectionEndpoints are added to the application you name
anything elseReported and skipped, never sent

Options

Every option can be given as a flag or as an environment variable, so credentials stay in your CI's secret store while the readable settings stay in the workflow file.

OptionEnvironment variableNotes
--fileRepeatable, and accepts globs. A pattern that matches no file fails the step
--appLEVO_APP_NAMEThe application to import a spec or Postman collection into. Not needed for a Kong file
--env-nameLEVO_ENV_NAMEThe environment to import into. It must already exist in Levo
--typekong, openapi or postman, to push only files of one kind
--auth-keyLEVO_AUTH_KEYPrefer the environment variable, so the key stays out of logs
--org-idLEVO_ORG_IDOptional when your key can see exactly one organization
--workspace-idLEVO_WORKSPACE_IDDefaults to your organization's default workspace
--saas-urlLEVO_BASE_URLThe Levo API address for your account
--timeoutPer-request timeout in seconds. Defaults to 60
--verboseLogs each request. Never logs your key or token

Good to know

Re-running is safe. A Kong file is authoritative for the labels it created, so a tag you remove at the gateway is removed in Levo on the next push. Labels you applied by hand in Levo are never touched, and pushing an unchanged file writes nothing.

One application per run. If a repository holds specs for two applications, add two steps, one per --app. Being explicit reads better in a workflow than an implicit mapping.

One repository per workflow. A workflow only ever sees its own repository. If your API specs live in several repositories, add the workflow to each of them.

If a step fails

What you seeWhat it means
no Levo authorization keyLEVO_AUTH_KEY is not reaching the step. Check the secret name
Levo rejected the authorization keyThe key is wrong, or belongs to a different Levo address than LEVO_BASE_URL
no file matched 'kong/*.json'The path is wrong for this repository. The step fails on purpose — a typo must not look like a successful run
no environment named 'NonProd'Create the environment in Levo first, or point --env-name at one that exists
not a file Levo can ingest; skippedThe file is not a spec, Kong file or Postman collection. Nothing was sent
--app is requiredA spec or Postman collection was matched without --app

Still stuck? support@levo.ai with the workflow step's output. The script never prints your key or token, so the log is safe to share.

Was this page helpful?