agentsclimarketplace

Integration validator

Skill merge-api/merge-unified-skills/skills/integration-validator

Claude Code skills for the Merge Unified API

Install
npx -y skills add merge-api/merge-unified-skills --skill integration-validator

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Validate a Merge Unified API integration end-to-end. Use when a developer says "validate my Merge integration", "test my Merge setup", "is my Merge connection working", "debug my Merge API call", "verify my Linked Account", "check my Merge scopes", "my Merge API returns empty", "Merge sync not working", "check my account_token", or after completing /merge-unified:onboarding. Runs diagnostic checks against the Merge API and outputs a pass/fail checklist with actionable fixes.

The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.

SKILL.md

9.2 KB, as published. Nobody here has run it

Merge Integration Validator

Run diagnostic checks against a developer's Merge integration and output a pass/fail report. This skill chains naturally after onboarding — once a developer has set up their Linked Account, this skill confirms everything actually works.

When to use this skill

Activate when:

  • Developer just finished the onboarding flow and wants to confirm it works
  • Developer says "validate", "test", "check", "verify", or "debug" in relation to their Merge setup
  • Developer reports empty API responses, auth errors, or sync issues
  • After /merge-unified:onboarding completes, proactively suggest this skill

Do NOT activate for:

  • Initial setup (route to onboarding)
  • Questions about Merge pricing, plans, or non-technical topics

First activation: self-introduce

When this skill activates for the first time in a conversation, say:

I'm the Merge Integration Validator (v0.1.0). I'll run a series of checks against your Merge API to confirm your integration is healthy. I'll need your API key, account_token, and the category you're integrating.

Step 0: Gather inputs

Ask the developer for (skip anything already known from context):

  1. API keytest_xxx or production_xxx
  2. Account token — the account_token for the Linked Account to validate
  3. Category — which Merge category: hris, ats, crm, accounting, ticketing, filestorage, knowledgebase, or mktg
  4. SDK language — to generate diagnostic code in their language

Warn: "I'll generate code that makes real API calls. If you're using a production key, these are read-only (GET) calls — no data will be modified."

Step 1: Generate and run the diagnostic script

Generate a diagnostic script in the developer's language that runs all checks from references/diagnostic-endpoints.md. The script should:

  1. Print each check name as it runs
  2. Print PASS / FAIL with a short explanation
  3. On failure, print the exact fix (not just "check your config")
  4. Exit with code 0 if all pass, 1 if any fail

Python example structure

import os
import requests

API_KEY = os.environ.get("MERGE_API_KEY", "YOUR_API_KEY")
ACCOUNT_TOKEN = os.environ.get("MERGE_ACCOUNT_TOKEN", "YOUR_ACCOUNT_TOKEN")
CATEGORY = "hris"  # replace with actual category
BASE = "https://api.merge.dev/api"

headers = {
    "Authorization": f"Bearer {API_KEY}",
    "X-Account-Token": ACCOUNT_TOKEN,
}

results = []

# Check 1: API key + account_token valid (combined auth check)
def check_auth():
    r = requests.get(f"{BASE}/{CATEGORY}/v1/account-details", headers=headers)
    if r.status_code == 200:
        data = r.json()
        return "PASS", f"Auth valid — integration: {data.get('integration_name', 'unknown')}, status: {data.get('status', 'unknown')}"
    elif r.status_code == 401:
        # Try without account_token to isolate which credential is wrong
        r2 = requests.get(f"{BASE}/{CATEGORY}/v1/account-details", headers={"Authorization": f"Bearer {API_KEY}"})
        if r2.status_code == 401:
            return "FAIL", "API key rejected (401). Verify at https://app.merge.dev/keys. Check env: test_ vs production_"
        else:
            return "FAIL", "API key is valid but account_token is rejected. Exchange a fresh public_token or check the stored token."
    else:
        return "FAIL", f"Unexpected status {r.status_code}: {r.text[:200]}"

# Check 3: Sync status
def check_sync_status():
    r = requests.get(f"{BASE}/{CATEGORY}/v1/sync-status", headers=headers)
    if r.status_code == 200:
        data = r.json()
        models = data.get("results", [])
        synced = [m for m in models if m.get("status") == "DONE"]
        syncing = [m for m in models if m.get("status") in ("SYNCING", "PARTIALLY_SYNCED")]
        failed = [m for m in models if m.get("status") == "FAILED"]
        if failed:
            names = ", ".join(m.get("model_name", "?") for m in failed)
            return "FAIL", f"Sync failed for: {names}. Check Linked Account page in dashboard."
        elif syncing:
            names = ", ".join(m.get("model_name", "?") for m in syncing)
            return "WARN", f"Still syncing: {names}. Wait and re-run."
        else:
            return "PASS", f"{len(synced)} models synced successfully"
    else:
        return "FAIL", f"Could not fetch sync status: {r.status_code}"

# Check 4: Data exists (primary model)
def check_data_exists():
    primary_models = {
        "hris": "employees", "ats": "candidates", "crm": "contacts",
        "accounting": "invoices", "ticketing": "tickets",
        "filestorage": "files", "knowledgebase": "articles", "mktg": "campaigns",
    }
    model = primary_models.get(CATEGORY, "")
    r = requests.get(f"{BASE}/{CATEGORY}/v1/{model}?page_size=1", headers=headers)
    if r.status_code == 200:
        data = r.json()
        count = len(data.get("results", []))
        if count > 0:
            return "PASS", f"Data found — {model} endpoint returned results"
        else:
            return "WARN", "Empty results. Check: (1) scopes enabled at /configuration/common-model-scopes, (2) initial sync completed, (3) source provider has data for this model"
    else:
        return "FAIL", f"{model} endpoint returned {r.status_code}: {r.text[:200]}"

# Check 5: Pagination works
def check_pagination():
    primary_models = {
        "hris": "employees", "ats": "candidates", "crm": "contacts",
        "accounting": "invoices", "ticketing": "tickets",
        "filestorage": "files", "knowledgebase": "articles", "mktg": "campaigns",
    }
    model = primary_models.get(CATEGORY, "")
    r = requests.get(f"{BASE}/{CATEGORY}/v1/{model}?page_size=1", headers=headers)
    if r.status_code != 200:
        return "SKIP", "Skipped (primary model check failed)"
    data = r.json()
    cursor = data.get("next")
    if cursor is None:
        return "PASS", "Only one page of data (or empty) — pagination not needed yet"
    r2 = requests.get(f"{BASE}/{CATEGORY}/v1/{model}?page_size=1&cursor={cursor}", headers=headers)
    if r2.status_code == 200:
        return "PASS", "Pagination works — fetched page 2 successfully"
    else:
        return "FAIL", f"Page 2 failed: {r2.status_code}"

# Run all checks
checks = [
    ("Auth (API key + account_token)", check_auth),
    ("Sync Status", check_sync_status),
    ("Data Exists", check_data_exists),
    ("Pagination", check_pagination),
]

print("=" * 50)
print("Merge Integration Validator")
print("=" * 50)

all_pass = True
for name, fn in checks:
    status, msg = fn()
    icon = {"PASS": "✅", "FAIL": "❌", "WARN": "⚠️", "SKIP": "⏭️"}.get(status, "?")
    print(f"\n{icon} {status}: {name}")
    print(f"   {msg}")
    if status == "FAIL":
        all_pass = False

print("\n" + "=" * 50)
if all_pass:
    print("All checks passed. Your Merge integration is healthy.")
else:
    print("Some checks failed. Fix the issues above and re-run.")
exit(0 if all_pass else 1)

Step 2: Interpret results

After the script runs, explain each result:

  • PASS — no action needed, confirm what it means
  • FAIL — explain the fix step-by-step, with links to the relevant dashboard page
  • WARN — explain what to watch for and when to re-check
  • SKIP — explain why it was skipped (usually a dependency failed)

Step 3: Optional deep checks

If all basic checks pass, offer these additional validations:

  1. Webhook verification — if they have a webhook URL configured, generate a test payload and verify their signature check works
  2. Field mapping check — list which Common Model fields have data vs null for a sample record
  3. Rate limit headroom — hit the API a few times rapidly to confirm they're not near the 429 threshold

Troubleshooting

SYMPTOM: All checks fail with 401. CAUSE: API key environment mismatch (test key against production data or vice versa). FIX: Verify key at https://app.merge.dev/keys. Test keys start with test_, production with production_.


SYMPTOM: API key passes but account_token fails. CAUSE: Token was for a different key environment, or the Linked Account was deleted. FIX: Check the Linked Account in the dashboard. If it's gone, re-trigger the onboarding flow.


SYMPTOM: Sync status shows DONE but data is empty. CAUSE: Common Model scopes not enabled for this model. FIX: Go to https://app.merge.dev/configuration/common-model-scopes and enable the relevant model.


SYMPTOM: Pagination cursor returns 400. CAUSE: Cursor expired or malformed. FIX: Cursors are ephemeral. Always fetch a fresh first page, then paginate from there.

Reference docs

  • Diagnostic endpoint details and expected responses: references/diagnostic-endpoints.md

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.