Skills Development Navan API CI/CD Integration Health Checks

Navan API CI/CD Integration Health Checks

v20260423
navan-ci-integration
This skill automates the validation of Navan API integrations within CI/CD pipelines. It generates robust GitHub Actions workflows to perform comprehensive tests, including token health checks, booking data schema validation, and automated compliance report generation. By integrating these checks into your push/pull request process, it ensures the stability and adherence of your Navan connection without requiring a dedicated SDK.
Get Skill
253 downloads
Overview

Navan CI Integration

Overview

Navan has no SDK — all CI integration uses raw REST calls against https://api.navan.com with OAuth 2.0 client_credentials authentication. This skill generates GitHub Actions workflows that validate your Navan integration on every push: token health checks, booking data schema validation, and travel policy compliance reports. Secrets (client_id, client_secret) are stored in GitHub Actions secrets, never in code.

Prerequisites

  • Navan Admin access to create OAuth 2.0 application credentials (Admin > API Settings)
  • GitHub repo with Actions enabled
  • GitHub Secrets configured: NAVAN_CLIENT_ID, NAVAN_CLIENT_SECRET
  • Navan API base URL: https://api.navan.com

Instructions

Step 1 — Store OAuth Credentials in GitHub Secrets

Navigate to your GitHub repo > Settings > Secrets and variables > Actions. Add:

  • NAVAN_CLIENT_ID — from Navan Admin > API Settings
  • NAVAN_CLIENT_SECRET — from Navan Admin > API Settings

Step 2 — Create the CI Workflow

# .github/workflows/navan-integration-check.yml
name: Navan Integration Health Check
on:
  push:
    branches: [main]
  pull_request:
  schedule:
    - cron: '0 6 * * 1'  # Weekly Monday 6am UTC

jobs:
  navan-health:
    runs-on: ubuntu-latest
    env:
      NAVAN_BASE_URL: https://api.navan.com
    steps:
      - uses: actions/checkout@v4

      - name: Authenticate with Navan OAuth 2.0
        id: auth
        run: |
          TOKEN_RESPONSE=$(curl -s -X POST \
            https://api.navan.com/ta-auth/oauth/token \
            -H "Content-Type: application/x-www-form-urlencoded" \
            -d "grant_type=client_credentials" \
            -d "client_id=${{ secrets.NAVAN_CLIENT_ID }}" \
            -d "client_secret=${{ secrets.NAVAN_CLIENT_SECRET }}")

          ACCESS_TOKEN=$(echo "$TOKEN_RESPONSE" | jq -r '.access_token')
          if [ "$ACCESS_TOKEN" = "null" ] || [ -z "$ACCESS_TOKEN" ]; then
            echo "::error::OAuth authentication failed"
            echo "$TOKEN_RESPONSE" | jq .
            exit 1
          fi
          echo "::add-mask::$ACCESS_TOKEN"
          echo "token=$ACCESS_TOKEN" >> "$GITHUB_OUTPUT"

      - name: API Health Check — Fetch Bookings
        run: |
          HTTP_CODE=$(curl -s -o /tmp/bookings.json -w "%{http_code}" \
            "$NAVAN_BASE_URL/v1/bookings?page=0&size=5" \
            -H "Authorization: Bearer ${{ steps.auth.outputs.token }}")
          echo "Health check status: $HTTP_CODE"
          if [ "$HTTP_CODE" != "200" ]; then
            echo "::error::API health check failed with HTTP $HTTP_CODE"
            cat /tmp/bookings.json
            exit 1
          fi

      - name: Validate Booking Data Schema
        run: |
          # Response structure: records in .data array, primary key uuid
          REQUIRED_FIELDS='["uuid","traveler","status","created_at"]'
          echo "$REQUIRED_FIELDS" | jq -r '.[]' | while read field; do
            if ! jq -e ".data[0].$field" /tmp/bookings.json > /dev/null 2>&1; then
              echo "::warning::Missing expected field: $field"
            fi
          done

      - name: Generate Compliance Report
        run: |
          curl -s "$NAVAN_BASE_URL/v1/bookings?page=0&size=50" \
            -H "Authorization: Bearer ${{ steps.auth.outputs.token }}" \
            -o /tmp/compliance.json
          echo "## Navan Compliance Report" >> "$GITHUB_STEP_SUMMARY"
          jq -r '"| Metric | Value |\n|--------|-------|\n| Total Bookings | \(.total_bookings) |\n| In Policy | \(.in_policy) |\n| Out of Policy | \(.out_of_policy) |"' \
            /tmp/compliance.json >> "$GITHUB_STEP_SUMMARY" 2>/dev/null || echo "Report data unavailable" >> "$GITHUB_STEP_SUMMARY"

Step 3 — Add Integration Test Script

#!/usr/bin/env bash
# scripts/navan-smoke-test.sh — Run locally or in CI
set -euo pipefail

BASE_URL="${NAVAN_BASE_URL:-https://api.navan.com}"

# Obtain token
TOKEN=$(curl -sf -X POST https://api.navan.com/ta-auth/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials&client_id=${NAVAN_CLIENT_ID}&client_secret=${NAVAN_CLIENT_SECRET}" \
  | jq -r '.access_token')

# Test endpoints (records returned in .data array)
ENDPOINTS=("v1/bookings?page=0&size=1")
FAILED=0
for ep in "${ENDPOINTS[@]}"; do
  CODE=$(curl -s -o /dev/null -w "%{http_code}" \
    "$BASE_URL/$ep" -H "Authorization: Bearer $TOKEN")
  if [ "$CODE" = "200" ]; then
    echo "PASS: $ep ($CODE)"
  else
    echo "FAIL: $ep ($CODE)"
    FAILED=$((FAILED + 1))
  fi
done

exit $FAILED

Output

The CI workflow produces:

  • Pass/fail status on each PR for Navan API connectivity
  • GitHub Step Summary with a compliance report table
  • Annotations warning about missing booking data fields
  • Weekly scheduled runs catching credential expiration before it causes outages

Error Handling

HTTP Code Meaning CI Action
200 Success Continue
401 Invalid or expired OAuth token Fail build, alert on credential rotation
403 Insufficient API scopes Fail build, check OAuth app permissions
404 Endpoint not found (API version change) Fail build, review API changelog
429 Rate limit exceeded Retry with exponential backoff (max 3 attempts)
500-503 Navan server error Warn but do not fail (transient)

Examples

Parallel endpoint validation with matrix strategy:

jobs:
  validate-endpoints:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        endpoint: [bookings, expenses, users, invoices]
    steps:
      - name: Check ${{ matrix.endpoint }}
        run: |
          CODE=$(curl -s -o /dev/null -w "%{http_code}" \
            "https://api.navan.com/v1/${{ matrix.endpoint }}?page=0&size=1" \
            -H "Authorization: Bearer $TOKEN")
          [ "$CODE" = "200" ] || exit 1

Resources

Next Steps

  • Add navan-deploy-integration for production deployment patterns
  • Add navan-observability for runtime monitoring of the endpoints validated here
  • See navan-rate-limits to configure retry policies in CI
Info
Category Development
Name navan-ci-integration
Version v20260423
Size 3.93KB
Updated At 2026-04-28
Language