Skip to documentation
PayIt homePayIt
Open PayIt app

AI agent skill

payit-integration

Instructions an AI coding agent follows when adding Pay-IT to an existing website, backend, mobile app, ERP, or billing platform. The agent interviews you, defaults to hosted checkout, waits for an approved plan, then implements and verifies the payment flow.

Install

  1. Download the guides archive. It contains the skill and every document the skill reads, including the API guide and OpenAPI spec.
  2. Unpack it and keep the guides/ folder as it is. Point the agent at guides/skills/integration/SKILL.md.
  3. Ask the agent to use payit-integration and point it at the application to change.

The agent must start with the integration interview. Do not paste live API keys, webhook secrets, or customer credentials into the chat. Put them in the target application's secret store.

When to use this skill

  • Accept instant mobile-money payments through the direct API.
  • Create or consume Payment Links.
  • Add hosted checkout to a website or application.
  • Receive and verify webhook events.
  • Combine initiation, status polling, and webhooks.
  • Move an existing integration from test mode to live mode.
  • Finish or diagnose an incomplete integration.

Do not use it only to explain an endpoint. For an explanation, answer from the API reference and leave the codebase unchanged.

Sources of truth

Before editing, the agent reads the relevant guide completely. It never invents an endpoint, field, enum, scope, response, or retry rule. If a guide and the machine-readable contract disagree, it stops and reports the conflict.

  • guides/README.md — shared conventions
  • guides/api-credentials.md — keys, scopes, rotation, revocation
  • guides/direct-api-integration.md — server-to-server payments and polling
  • guides/developer-api.md and developer-api.openapi.yaml — exact schemas
  • guides/webhooks.md — signatures, retries, replay
  • guides/payment-links.md — links, guest checkout, logged-in checkout

In this repository the contract authority is Backend/api/core-engine/api-docs/spec.yaml.

Integration interview

Before inspecting or changing code, the agent asks these as one short questionnaire. It does not ask for secret values.

  1. Business purpose and what a successful payment should accomplish.
  2. Test mode, live mode, or a test-to-live migration.
  3. Features: hosted checkout (default), direct initiation only when required, webhooks, polling, or a combination.
  4. Which repository to change, and whether the owner is backend, frontend, mobile, or several.
  5. Who pays, and whether a website opens a modal, inline region, or full-page redirect.
  6. Networks, currency, amount rules, merchant references, payer purpose, and custom metadata.
  7. Public HTTPS callback URL and event types. If the URL is not ready, implement the receiver and leave configuration as a deployment step.
  8. Where credentials already live. Never the secret itself.
  9. The observable result that means the integration is done.

Modal and inline checkout need the exact test and live website origins, such as https://shop.example.com. A path, wildcard, or guessed origin is not accepted. If the initiation method is missing, the agent states that hosted checkout will be used.

Safety rules

  • Never put a merchant API key, webhook secret, or checkout token in frontend or mobile source.
  • The browser or app calls your backend. Only that backend calls Pay-IT for the direct API.
  • Commit variable names and safe examples. Store secrets in the project's existing mechanism.
  • Never log full keys, secrets, checkout tokens, challenges, unmasked mobile numbers, or raw sensitive payloads.
  • Do not create a live charge unless the amount, payer, and timing are explicitly authorized.
  • Use one stable idempotency key per payment and keep it across safe retries.
  • An accepted request is not proof of payment. SUCCEEDED is the successful terminal state.
  • Verify webhook signatures on the exact raw body before parsing the event.
  • Process event ids once. Deliveries can repeat or arrive out of order.
  • Keep a rotated webhook secret until pre-rotation deliveries finish their retries, not only for 24 hours.
  • A 200 counts as delivery only when it came from the receiver route itself.
  • Follow the target repository's own agent rules and approval gates. Leave unrelated changes alone.

Assess the codebase

After the interview, the agent reads the target instructions, language, framework, and existing HTTP, secret, persistence, and test patterns. It reuses that architecture, looks for an existing Pay-IT integration, and decides what must be stored: merchant reference, payment id, idempotency key, status, processed event ids, and timestamps. It summarizes files, risks, assumptions, and how it will verify before asking to proceed.

Choose a method

New website integrations use Payment Links through the hosted checkout JavaScript SDK. Modal is the default. Inline is used when checkout must sit in a named page region. Redirect is used when framing is unsuitable or a full-page handoff is requested.

The direct API is selected only when you explicitly require initiation from your trusted server, including a clear instruction to call POST /api/integrations/v1/mobile-money-payments. A backend, a custom interface, webhooks, or polling do not by themselves justify the direct API. Webhooks can be added to either approach.

Hosted checkout

Load https://payit.co.tz/sdk/checkout-v1.js with defer and call window.PayIt.checkout. The customer pays in Pay-IT's hosted UI. The website does not hold a merchant API key just to open checkout.

JavaScript
const checkout = window.PayIt.checkout({
  slug: 'duka-store',
  mode: 'modal',
  onSuccess: () => showPending(),
  onFailure: () => showRetry(),
  onClose: () => {}
});
checkout.open();
  • Confirm the Payment Link is published and record its slug.
  • For modal or inline, configure the exact origin and send the link's current Version.
  • Inline mode needs a real CSS selector or DOM element in container.
  • Call open() from the user action. Callbacks only update the interface.
  • Fulfill the order from a verified webhook or an authenticated server status read.
  • Do not build /embed/pay/{slug} by hand or add a separate postMessage listener. The SDK owns the iframe, origin checks, and duplicate terminal events.
  • Redirect mode goes to /pay/{slug}, uses no iframe, and emits no completion callbacks.
  • An unavailable embed is a generic checkout-unavailable state. Do not probe whether the link or origin exists.

Direct instant payment

Only after an explicit requirement. The plan records that requirement. The server client posts to /api/integrations/v1/mobile-money-payments with a stable Idempotency-Key, stores payment_id and status, and polls GET /api/integrations/v1/checkout-sessions/{sessionPublicId}. Publishing is required for hosted checkout. An archived link cannot start a new payment. Typical scopes are mobile_money_payments:create and checkout_sessions:read.

Signed webhooks

  • Public HTTPS POST route with access to the exact raw bytes.
  • Verify the signature, timestamp, and secret rotation before acting.
  • Store event id uniqueness, acknowledge with 2xx after safe persistence, and do heavier work asynchronously.
  • Do not let an older event move a payment backward out of a terminal state.
  • Configure the full receiver URL, including the path. A bare origin can return 200 from an unrelated handler.
  • Send the link Version. A successful configure increments it. Stale version is HTTP 409, response code 1124. Refetch and retry. Only 1124 is retryable.
  • There is no webhook details endpoint. Persist what you configured.
  • 1125 malformed URL, 1126 host is not public, 1127 bad events, 1101 link missing, 901 missing capability.
  • webhook/test needs an ACTIVE endpoint and at least one existing checkout session.
  • A delivery keeps the secret it was queued with for the whole retry life, about 80 hours. Keep the previous secret for that horizon. PreviousSecretValidUntilUtc is not the moment to drop it.
  • The host must keep resolving to public addresses. A successful configure is not a permanent delivery guarantee.

Plan and approval

The agent presents purpose, method, checkout mode, slug, origins, base URL, scopes, files, state model, idempotency, webhook strategy, tests, deployment, and risks. For live mode it names any step that could charge a customer or change a live webhook, and it does not run that step without separate permission.

It then stops. Approval is an unambiguous instruction such as approved or proceed with this plan. Silence, or an earlier general request to integrate Pay-IT, is not permission. Before approval it may only read, research the contract, and run non-mutating checks. It must not edit files, install dependencies, migrate data, change secrets, create payments, configure webhooks, or deploy.

Implement

After approval, follow the target project's conventions: typed configuration, one Pay-IT client, exact field casing, decimal-safe money, phone normalization without logging the full number, idempotency before retries, mocked tests, and a .env.example with placeholders only. A hosted SDK integration does not add a server Pay-IT client merely to open checkout. Callbacks update the screen. Fulfillment stays on the server.

Verify

Run formatting, static checks, unit tests, the build, and a contract check. For modal or inline, confirm the configured origin opens and an unknown origin fails closed. Signature fixtures prove the verifier. They do not prove Pay-IT can reach the receiver. A real check uses the full receiver path, confirms the route itself logged the request, returns 2xx for a valid signature and 401 for a tampered body, and records the event once on replay.

Two silent failures are common: a webhook URL set to a bare origin, and an empty environment value in a higher-precedence file overriding the correct one. Check the value the process actually loaded. Live mode stays on mocked and read-only checks until you authorize a real charge with the amount, payer, and rollback stated again.

Handoff

The report lists what was integrated, test or live mode, files changed, secret names without values, scopes, webhook URL and events, commands run, live actions not taken, deployment order, smoke test, and rollback. It distinguishes implemented, verified locally, verified in test mode, and verified live. It does not call the work complete while credentials, a public webhook URL, a migration, deployment, or an end-to-end payment is still outstanding.

Custom merchant metadata

metadata is optional and only on POST /api/integrations/v1/mobile-money-payments. There is no browser SDK metadata field. After acceptance it is immutable and stored for audit. Limits are 8192 bytes of normalized UTF-8 JSON, eight container levels including the root, and a 65536 byte raw payment body. Root arrays or scalars, duplicate properties, and numeric exponents outside -1000 to 1000 are rejected. Do not trim values or stringify the whole object.

Metadata is part of idempotency. Key order and whitespace are ignored. Array order and numeric spelling matter. Changed metadata returns 409. Omitted and explicit null share one hash. An empty object is different. New pending, succeeded, failed, expired, and test webhooks may include data.metadata. Older events may omit it. Accept a missing value. Never mark an order paid from webhook.test. Fulfillment still requires a verified succeeded state plus the normal amount, currency, reference, and payment reconciliation.

For support, capture the X-PayIT-Request-Id response header. It is safe to share and it is not a credential.