# Payments & Credits

Pay for lease signatures using the FairePlace credit system, powered by Stripe.

## How credits work

- **1 credit = 1 lease signature** (includes all signers on that lease)
- Credits are purchased via Stripe Checkout
- Credits never expire
- Credits are scoped to your organization (tenant)

## Check your balance

```bash
curl https://api.faireplace.com/api/credits/balance \
  -H "Authorization: Bearer $API_KEY"
```

```json
{
  "credits_available": 12,
  "credits_used": 38,
  "credits_total": 50
}
```

## Purchase credits

### 1. Create a checkout session

```bash
curl -X POST https://api.faireplace.com/api/credits/purchase \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "package": "10_credits",
    "success_url": "https://your-app.com/credits/success",
    "cancel_url": "https://your-app.com/credits/cancel"
  }'
```

```json
{
  "checkout_url": "https://checkout.stripe.com/c/pay/cs_live_a1b2c3...",
  "session_id": "cs_live_a1b2c3d4e5f6g7h8",
  "package": "10_credits",
  "amount": 49.00,
  "currency": "EUR"
}
```

### 2. Redirect to Stripe

Open the `checkout_url` in the user's browser. Stripe handles the payment form, card validation, and 3D Secure if required.

### 3. Credits are added automatically

After successful payment, credits are added to your balance immediately. The user is redirected to your `success_url`.

## Pricing

One credit equals one lease signature, and the per-signature price depends on your plan. The authoritative, always-current grid lives at [faireplace.com/tarifs](https://faireplace.com/tarifs/).

| Plan | Included signatures / month | Additional signature |
|------|-----------------------------|----------------------|
| Gratuit | 0 (pay-as-you-go) | 4.90 EUR |
| Starter | 5 | 4.90 EUR |
| Pro | 20 | 3.90 EUR |
| Business | Unlimited | — |

Pay-as-you-go signatures are 4.90 EUR incl. VAT (TTC) per unit. Credits never expire. For billing outside France, VAT is finalized at checkout based on your billing country.

## Credit history

View your transaction history:

```bash
curl https://api.faireplace.com/api/credits/history \
  -H "Authorization: Bearer $API_KEY"
```

```json
{
  "transactions": [
    {
      "id": "txn-aabb1122-3344-5566-7788-99aabbccddee",
      "type": "purchase",
      "credits": 10,
      "amount": 49.00,
      "currency": "EUR",
      "stripe_payment_id": "pi_3abc123def456",
      "created_at": "2026-02-15T09:00:00Z"
    },
    {
      "id": "txn-ccdd3344-5566-7788-99aa-bbccddeeff00",
      "type": "usage",
      "credits": -1,
      "lease_id": "lease-4d5e6f78-90ab-cdef-1234-567890abcdef",
      "description": "Signature for BAIL-2026-001",
      "created_at": "2026-02-19T10:08:00Z"
    }
  ],
  "meta": {
    "pagination": {
      "current_page": 1,
      "per_page": 20,
      "total": 48
    }
  }
}
```

## Stripe webhooks

FairePlace uses Stripe webhooks to process payments reliably. If you need to track payment events in your own system, you can listen for these webhook events.

### Webhook endpoint

Configure your webhook endpoint in Stripe Dashboard to receive events at your URL.

### Key events

| Event | Description |
|-------|-------------|
| `checkout.session.completed` | Payment successful, credits added to balance |
| `charge.succeeded` | Charge confirmed by the payment provider |
| `charge.refunded` | Refund processed (credits will be deducted) |

### Webhook payload example

```json
{
  "type": "checkout.session.completed",
  "data": {
    "object": {
      "id": "cs_live_a1b2c3d4e5f6g7h8",
      "payment_status": "paid",
      "amount_total": 4900,
      "currency": "eur",
      "metadata": {
        "tenant_id": "550e8400-e29b-41d4-a716-446655440000",
        "package": "10_credits",
        "credits": "10"
      }
    }
  }
}
```

### Verifying webhook signatures

Always verify the Stripe webhook signature to ensure the event is authentic:

```javascript
const stripe = require("stripe")(process.env.STRIPE_SECRET_KEY);

app.post("/webhooks/stripe", (req, res) => {
  const sig = req.headers["stripe-signature"];
  const event = stripe.webhooks.constructEvent(
    req.body,
    sig,
    process.env.STRIPE_WEBHOOK_SECRET
  );

  if (event.type === "checkout.session.completed") {
    const session = event.data.object;
    console.log(
      `Payment confirmed: ${session.metadata.credits} credits for tenant ${session.metadata.tenant_id}`
    );
  }

  res.json({ received: true });
});
```

## Error handling

### Insufficient credits when signing

If you try to initiate a signature without credits:

```json
{
  "error": {
    "code": 402,
    "type": "PAYMENT_REQUIRED",
    "message": "Insufficient signature credits",
    "details": {
      "credits_required": 1,
      "credits_available": 0,
      "purchase_url": "/api/credits/purchase"
    }
  }
}
```

### Payment failed

If the Stripe checkout fails, no credits are added. The user can retry by creating a new checkout session.

---

## Related

- **[Electronic Signatures](/signatures/overview)** — How signatures use credits
- **[Create a Lease End-to-End](/signatures/lease-workflow)** — Full workflow including payment
- **[Error Handling](/core/errors)** — All error codes and troubleshooting
