agentleFS
MartinOliveroMartinOlivero/saas-builder/skills/integrations/SKILL.md

integrations

Skill4 starsChanged 32 days agoMITView on GitHub

This skill should be used when the product talks to a platform you do not control — receiving webhooks, syncing with a CRM, ERP, e-commerce or calendar API, connecting a user's Google or Meta account over OAuth, sending through WhatsApp or another messaging API, or sending transactional email. Trigger phrases (English) include "integrate with", "connect to the X API", "receive a webhook", "the webhook isn't firing", "sync with", "import from their API", "OAuth with Google", "refresh token", "send transactional email", "their API returns", "pagination". Trigger phrases (Spanish) include "integrar con", "conectar con la API de", "recibir un webhook", "el webhook no llega", "sincronizar con", "importar desde su API", "conectar la cuenta de Google", "mandar mails transaccionales". It designs the integration so that a third party being late, wrong, duplicated or down does not corrupt your data or fail silently. For Stripe and payment webhooks specifically, use `payments`.

15 other projects use a version of this.

Adopted by

Most recently taken up by

Used with

Projects with it also use learn.

Other files people use alongside this one.

Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
  • genomewalkerSkill

    learn

    Learn from web sources, generate SKILL.md, and store key patterns in soul memory. Trigger keywords: learn, skill-gen, web-learn, documentation, tutorial.

    Also in 3 projects that use this

The file

We split this skill into the rules it gives an agent

2 rules. 0 are common, 2 are distinctive, and 0 are very specific to this project.

  • 0

    Common

    Most of the 15 edited versions we read keep these.

  • 2

    Distinctive

    This author's own choices. Worth a look.

  • 0

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Do they push events (webhooks), or do you pull?

    line 15
  2. Distinctive:

    Verify your sending domain: before you need to email anyone but yourself.

    line 85

“Common” is measured: kept by at least 6 in 10 of the 15 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Integrations

Your own code does what you wrote. A third party does what it does today, which may differ from its documentation, from yesterday, and from its sandbox. This skill designs for that.

Analogy: an integration is a business partner in another time zone who answers by post. Letters arrive twice, out of order, or not at all, and sometimes the letter says "done" when nothing was done. You don't run the business on the letters — you keep your own books and reconcile.

Discovery (max 3 questions, only if unknown)

  1. Direction — do you read from them, write to them, or both?
  2. Do they push events (webhooks), or do you pull?
  3. Is the connection per-product (one key of yours) or per-customer (each user connects their own account)?

Step 1 — Inbound: treat the webhook as a doorbell

Take only the id from the webhook, then fetch the object from their API with your own credentials. Never write the webhook body into your tables.

This one decision removes a family of problems: forged payloads, bodies re-serialized by a gateway (which breaks signature checks), events arriving out of order, and fields that are empty in the event but present in the API.

Around it:

  • Verify the signature — and reject when it is missing. A handler that skips verification if no signature header arrives has no verification.
  • Deduplicate by their event or message id, stored with a unique constraint. Deliveries repeat.
  • Batched webhooks: one bad item must not stop the rest. try/catch per item, persist before you enqueue, and never return out of the loop when one entry belongs to an unknown account — the other tenants in the same request go silent.
  • Expect your own writes to come back. Change something through their API and the webhook reports it to you; without a guard it overwrites the state you just set.
  • Never depend on the webhook alone. Build the pull path too — a "sync now" action that rings the same doorbell by hand, or a reconciliation job. Webhooks get registered and then never fire, and you find out from a customer.

Step 2 — Outbound: "they said no" is not "I don't know"

Classify every response from a write:

What came backMeaningTell the user
2xxDoneDone
4xxThey refused. Nothing changedTheir reason
5xx, timeout, connection droppedUnknown. It may have gone through"We couldn't confirm — check before trying again"

Showing "nothing was changed" on a gateway error invites a retry, and the end customer receives the notification twice.

  • The user's main action never waits on the third party. Save first, sync after; a failed sync is a visible state on the record, not a failed save.
  • Send dates as ISO-8601 with an explicit offset. A timestamp without a zone moved a real appointment by three hours — and notified the customer.
  • Find out in the sandbox what each omitted field does. Leaving a field out of an update is not always "keep it": one provider re-ran its own assignment logic and gave the appointment to a different person.
  • Trust the response you receive, not the one documented. Field names differ.

Step 3 — Reading: don't believe the pagination

  • Stop on an empty page, not on has_more: false. One API reported no more pages with 33 customers still pending.
  • Reconcile against an independent total — a report, an invoice sum, a count from their UI. Coming up short is otherwise invisible.
  • Compare ids, not counts. A date-range filter that returns the right number of the wrong records looks fine.
  • Batch id lists. A hundred ids in a query string produced a gateway error; so did sixty parallel requests. Chunk both.
  • Paginate your own reads too: auto-generated APIs cap rows per request (commonly 1000) and return a truncated list without an error.

Step 4 — Credentials that expire

  • Long-lived tokens still expire. Schedule the renewal and alert when it fails; the alternative is discovering it when the integration stops.
  • Single-use refresh tokens need a lock. Two processes refreshing at once invalidate each other; take a database lock so only one renews.
  • Adding a scope does not update existing installations. They fail with 401 until each customer reconnects — plan the migration.
  • Per-user OAuth (Google and similar):
    • Validate the scopes actually granted in the token response. Consent screens let the user untick one; the integration then shows "connected" and fails later.
    • To request an extra scope from a signed-in user, link the identity rather than starting a new sign-in — a new sign-in with a different account switches users and their data "disappears".
    • "Disconnect" must revoke at the provider, not just delete your row — especially if your privacy policy says so.
    • The provider validates the full redirect URL, not the origin.
    • Sign-up metadata (a chosen role, a plan) does not survive the OAuth round trip; carry it in the return URL.

Step 5 — Test what you think you are testing

  • A 403 alone proves nothing. Test both ends: rejected without the secret and accepted with it. A misspelled header name returns the same 403 as a working guard.
  • A 200 is not success until you have read the body. A wrong path can return an HTML page with status 200.
  • Simulated events answer simulated questions. "Does the real event carry the email?" is answered only by a real event.
  • Never test against contacts that might be real people. Sandbox data with a plausible email address is someone's inbox. Use addresses you own, and put guards in test tooling so a missing argument cannot write to a live record.
  • Check the credential's prefix before storing it. A live key saved under a variable named "test" charges real money.
  • Write down what you could not measure, as "no evidence", instead of assuming.

Step 6 — When a hop is added, the failure mode is added too

Moving logic to another service inserts a network hop. Each hop needs: a retry, an emergency branch that still records that the user wrote, and an alert that is separate from the run status — because a handled failure finishes green.

Step 7 — Transactional email

  • Best-effort, but logged. A failed email must not break the action that triggered it; a rejected one must be distinguishable from a sent one. Check the SDK's returned error.
  • One-click unsubscribe is a POST. Link scanners follow every GET in a message; a GET that unsubscribes will be triggered by security software. Link to a page with a button and set the List-Unsubscribe and List-Unsubscribe-Post headers.
  • Verify your sending domain before you need to email anyone but yourself.
  • Escape user-supplied values in HTML bodies, and restrict what a visitor's name can contain when it ends up in an invitation sent to a third party.
  • Provider templates default to English — translate them before launch.
  • Respect the provider's rate limit in loops; add a delay.

Output

Deliver: the direction and trust model, the webhook handler (signature, dedupe, doorbell fetch, per-item isolation), the reconciliation path, the response classification for writes with the user-facing message for each, the credential-renewal plan, and the both-ends test. List anything the sandbox could not confirm.

Field notes

references/field-notes.md — what each rule cost before it was a rule.

Reference

The provider's own API reference and changelog (read the current version, then verify against real responses), RFC 8058 (one-click unsubscribe), Stripe's webhook best practices (general guidance that applies to any provider). Pairs with payments, api-design (idempotency), secure-coding (secrets, signatures) and ai-features (chat platforms).

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.