Detect API schema drift before your integrations break.
SchemaPing monitors HTTP JSON endpoints, compares response structures over time, and alerts you when something changes — in the terminal and via webhooks.
- Added or removed fields
- Type changes (
string→number, etc.) - Nullability changes
- Unexpected HTTP status codes
- Request failures and timeouts
Array diffing limitation: arrays are compared using only their first element as a schema representative. Heterogeneous arrays, nested arrays, and length changes are not reported.
- Added or removed paths
- Added or removed operations (HTTP methods)
- Added or removed parameters (query, path, header, cookie)
- Parameter required/type changes
- Added or removed response codes
- Inline schema property additions, removals, and type changes
- Request body additions/removals and content type changes
- Spec version (
info.version) changes
$reflimitation: references ($ref) are NOT resolved. Only inline schema definitions are compared. If your spec uses$refextensively, changes inside referenced components will not be detected.
Prerequisites: Go 1.25+
git clone https://github.com/rubensantoniorosa2704/schemaping-worker.git
cd schemaping-worker
go build -o schemaping ./cmd/schemaping# run a single check for all monitors and exit
schemaping check --config ./examples/config.yaml
# run continuously, checking on each monitor's interval
schemaping run --config ./examples/config.yaml
# override the interval for all monitors
schemaping run --config ./examples/config.yaml --interval 30s
# verify that all configured webhooks are reachable
schemaping test-webhooks --config ./examples/config.yamlmonitors:
- name: payments-api
url: https://api.example.com/v1/payments
method: GET
interval: 5m
timeout: 10s
expected_status: 200
retries: 3 # retry up to 3 times on transient failures (5xx, 429, timeouts)
retry_backoff: 2s # base interval for exponential backoff (2s → 4s → 8s…, capped at 30s)
headers:
Authorization: Bearer ${API_TOKEN}
- name: payments-spec
url: https://api.example.com/v1/openapi.yaml
type: openapi
interval: 10m
raw: true
webhooks:
- type: discord
url: ${DISCORD_WEBHOOK_URL}| Field | Default | Description |
|---|---|---|
name |
required | Unique monitor identifier |
url |
required | Endpoint to monitor |
type |
http |
Monitor type: http (JSON API diff) or openapi (OpenAPI 3.0 spec diff) |
method |
GET |
HTTP method |
interval |
1m |
How often to check |
timeout |
10s |
Request timeout |
expected_status |
200 |
Expected HTTP status code |
retries |
3 |
Additional attempts after a transient failure (5xx, 429, timeout). Set to 0 to disable. |
retry_backoff |
2s |
Base duration for exponential backoff between retries (capped at 30s). |
headers |
— | Optional request headers |
webhooks |
— | Per-monitor webhook override (see below) |
raw |
false |
Save the raw response body to disk after each successful check (see Raw snapshot storage) |
SchemaPing can send notifications to external platforms when a schema change is detected.
| Platform | type |
Required fields |
|---|---|---|
| Discord | discord |
url |
| Telegram | telegram |
url, chat_id |
Defined once at the top level, they fire for every monitor that detects a change:
webhooks:
- type: discord
url: ${DISCORD_WEBHOOK_URL}
- type: telegram
url: https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage
chat_id: ${TELEGRAM_CHAT_ID}
monitors:
- name: payments-api
url: https://api.example.com/v1/payments
- name: users-api
url: https://api.example.com/v1/usersA monitor can define its own webhooks list, which replaces the global list for that monitor only:
webhooks:
- type: discord
url: ${DISCORD_WEBHOOK_URL} # default channel
monitors:
- name: payments-api
url: https://api.example.com/v1/payments
# no webhooks field → uses global
- name: critical-api
url: https://api.example.com/critical
webhooks: # override → different channel
- type: discord
url: ${DISCORD_CRITICAL_WEBHOOK_URL}
- name: noisy-api
url: https://api.example.com/noisy
webhooks: [] # silenced → no notificationsTokens and webhook URLs should never be hardcoded in the config file. Use ${ENV_VAR} references — they are expanded at startup before the YAML is parsed, so they work in any field.
export DISCORD_WEBHOOK_URL="https://discord.com/api/webhooks/..."
export TELEGRAM_BOT_TOKEN="your-bot-token"
export TELEGRAM_CHAT_ID="your-chat-id"
schemaping run --config ./config.yaml- Open the target channel → Edit Channel → Integrations → Webhooks → New Webhook
- Give it a name and copy the webhook URL
- Export the URL:
export DISCORD_WEBHOOK_URL="https://discord.com/api/webhooks/..."
- Create a bot via @BotFather and copy the token
- Get your chat ID (send a message to the bot and call
getUpdates) - Export both:
export TELEGRAM_BOT_TOKEN="..."andexport TELEGRAM_CHAT_ID="..."
schemaping test-webhooks --config ./config.yamlTesting 2 webhook(s)...
[1] OK
[2] OK
Exits with code 1 if any webhook fails, making it safe to use in CI/CD pipelines.
[payments-api] change detected
+ customer.phone added (string)
- customer.document removed (string)
~ amount changed: string -> number
~ status changed: 200 -> 404
Snapshots are saved to ~/.schemaping/snapshots/ after each check.
By default, SchemaPing reports drift to the terminal and via webhooks — what you do with that information is up to you.
If you want to keep the raw response for each check (for auditing, debugging, or feeding into your own pipeline), enable raw on a per-monitor basis:
monitors:
- name: payments-api
url: https://api.example.com/v1/payments
raw: trueWhen enabled, SchemaPing saves the raw response body to ~/.schemaping/raw/<monitor-name>/ after each successful check. The filename includes the capture timestamp (e.g. payments-api-2026-08-19T08-45-00Z.json), and the previous file is always replaced — there is no unbounded growth.
SchemaPing does not ship adapters for external storage targets (S3, Postgres, message brokers). The raw files are yours to consume however you like — sync them to S3, tail them into a log shipper, or ignore them entirely. The raw flag is opt-in and has no effect on drift detection or notifications.
- Webhook alerts (Discord, Telegram)
- Retry with exponential backoff
- Raw response storage (opt-in, per-monitor)
- OpenAPI diff support (3.0)
- Snapshot history
Apache License 2.0 — see LICENSE.