Back to skills
SKILL.md
Navan Ci Integration
BSecurityUse when setting up CI/CD pipelines that validate Navan API integrations, run booking data health checks, or generate automated compliance reports. Trigger with "navan ci integration" or "navan pipeline" or "navan github actions".
- 4 stars
- 0 votes
- 0 copies
- 2 views
- Added September 12, 2026
Works with
Security analysis
75/100- Exfiltrates credentials via HTTP — exact pattern from Snyk ToxicSkills study
- Sends environment variables or credentials to an external URL
Pro scans all 2 files and shows the line behind each finding
npx -y skills add aibot88/sec_skill_store --skill navan-ci-integration --agent claude-codeAre you the author of Navan Ci Integration?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/aibot88-navan-ci-integration)---
name: navan-ci-integration
description: |
Use when setting up CI/CD pipelines that validate Navan API integrations, run booking data health checks, or generate automated compliance reports.
Trigger with "navan ci integration" or "navan pipeline" or "navan github actions".
allowed-tools: Read, Write, Edit, Bash(git:*), Bash(gh:*), Grep, Glob
version: 1.0.0
license: MIT
author: Jeremy Longshore <jeremy@intentsolutions.io>
tags: [saas, navan, travel]
compatible-with: claude-code
---
# 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
```yaml
# .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
```bash
#!/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:**
```yaml
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
- [Navan Help Center](https://app.navan.com/app/helpcenter) — API documentation and guides
- [Navan Integrations](https://navan.com/integrations) — Supported third-party connectors
- [GitHub Actions Encrypted Secrets](https://docs.github.com/en/actions/security-for-github-actions/security-guides/using-secrets-in-github-actions)
## 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
Files in this skill
- SKILL.md
- source.json
Attribution
Comments
Loading comments…
Newsletter
Get the weekly list of safe new skills, and the ones we pulled.