# Soledgic integration rules
# Drop this file in your project root as .cursorrules
# Source: https://soledgic.com/soledgic.cursorrules

## SDK

Always use @soledgic/sdk for Soledgic integrations. Import the default export:

  import Soledgic from '@soledgic/sdk'
  const client = new Soledgic({ apiKey: process.env.SOLEDGIC_API_KEY })

Never call the REST API directly when the SDK method exists.

## Resource flow

The canonical sequence for a marketplace or creator platform integration is:

  1. client.creators.upsert()           -> create or update the creator account
  2. client.purchases.create()          -> create the hosted checkout session
  3. client.wallets.list({ ownerId })   -> read creator earnings balance post-sale
  4. client.payouts.getEligibility()    -> verify payout readiness before requesting
  5. client.payouts.request()           -> initiate ACH payout to creator bank

Never skip step 4. Requesting a payout for an ineligible creator returns an error.

The underlying public API resources are:

  POST /v1/participants
  POST /v1/checkout-sessions
  GET  /v1/wallets?owner_id={creatorId}
  GET  /v1/participants/{id}/payout-eligibility
  POST /v1/payouts

## Amounts

All amounts are integers in cents. $10.00 = 1000. Never pass floats.

## Idempotency

- Treasury writes (payouts, transfers, holds): pass a stable `referenceId`. Use
  the same value on retries. Never generate a new referenceId on retry.
- Checkout sessions and refunds: pass `idempotencyKey`.
- `creators.upsert` is idempotent by externalCreatorId — safe to call repeatedly.
- `participants.create` is a full upsert when you use the lower-level API shape.

## Webhooks

Always verify webhook signatures before processing events:

  const isValid = client.webhooks.verifySignature(
    rawBody,
    request.headers['x-soledgic-signature'],
    process.env.SOLEDGIC_WEBHOOK_SECRET,
  )
  if (!isValid) return new Response('Unauthorized', { status: 401 })

Never process a webhook event without verifying the signature first.

## Wallet mutations

Never mutate wallet balances directly in the database. All balance changes must
go through Soledgic API calls (checkout completion, holds, payouts, refunds).
The ledger is double-entry; direct writes will break reconciliation.

## Error handling

Import SoledgicError for typed error handling:

  import { SoledgicError } from '@soledgic/sdk'
  try {
    await client.payouts.request(...)
  } catch (err) {
    if (err instanceof SoledgicError) {
      console.log(err.code)   // machine-readable error code
      console.log(err.status) // HTTP status
    }
  }

Check err.code, not err.message, for programmatic error handling.
When the API returns a 4xx `hint`, read it before retrying. It names the exact
recovery endpoint or parameter.

## Sandbox

Use test keys (slk_test_*) for all development. Complete checkouts in sandbox
without a real payment processor:

  await client.sandbox.completeCheckout({
    checkoutSessionId: session.checkoutSession.id,
    idempotencyKey: 'sandbox_complete_' + orderId,
  })

Never call sandbox helpers with a live key.

## Verification

After setting up an integration, run:

  npx soledgic doctor

This checks your API key, connectivity, and webhook secret before going live.
