> ## Documentation Index
> Fetch the complete documentation index at: https://docs.busha.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Quick Start

> Walk through a full pledge lifecycle end to end, and every error you might hit along the way.

## Before you start

A pledge is created on the customer's behalf, so you need a customer scoped OAuth2 access token before you touch any pledge endpoint. If you already have one and it still carries the pledge scopes you need, skip to [step 1](#1-create-a-pledge-quote).

Getting that token means walking through the OAuth2 authorization code flow once. Here's the brief version of what you're doing and where to go for each part:

**1. Generate PKCE values.** Your backend creates a fresh `code_verifier`, its derived `code_challenge`, and a CSRF `state` value for this specific authorization attempt. Never reuse these across attempts.

```bash theme={null}
CODE_VERIFIER=$(openssl rand -base64 32 | tr '+/' '-_' | tr -d '=')
CODE_CHALLENGE=$(printf '%s' "$CODE_VERIFIER" | openssl dgst -sha256 -binary | openssl base64 | tr '+/' '-_' | tr -d '=')
STATE=$(openssl rand -hex 16)
```

Full detail on why PKCE matters is in [Security best practices](/guides/oauth/security#pkce-is-mandatory).

**2. Send the customer to authorize your app.** Build the authorization URL with your `client_id`, `redirect_uri`, the pledge scopes you need, and the `code_challenge` and `state` from step 1. The customer logs in and consents on Busha's own screen, then gets redirected back to you with a `code`. See [Quick start: Step 2](/guides/oauth/quick-start#step-2-redirect-the-user-to-busha) for the exact URL shape.

**3. Exchange the code for tokens.** Your backend swaps the `code` for an `access_token` and `refresh_token`, using the `code_verifier` from step 1. See [Quick start: Step 4](/guides/oauth/quick-start#step-4-exchange-the-code-for-tokens).

**4. Check the token has the pledge scopes you need.** The response's `scope` field lists what was actually granted. If `pledges:liquidate` isn't there and you'll need it later, request it now rather than re running this whole flow later, see [Scopes](/guides/oauth/scopes#pledges).

Don't have an OAuth2 app yet, or need your `client_id`/`client_secret`? Start at [Get access](/guides/oauth/get-access).

<Note>
  Codes are single use and expire in 10 minutes. Access tokens expire in about
  an hour, refresh tokens rotate on every use. If a pledge request suddenly
  returns `401`, refresh rather than restarting the whole flow, see [Token
  handling](/guides/oauth/tokens).
</Note>

## 1. Create a pledge quote

Before locking anything, preflight the request. This confirms the customer's assets are available to lock without moving funds.

<Accordion title="Request and response">
  ```bash theme={null}
  curl -X POST https://api.busha.io/v1/pledges/quotes \
    -H "Authorization: Bearer $CUSTOMER_ACCESS_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
      "reference": "credit_agreement_93b7",
      "items": [
        { "asset": "USDT", "amount": "100" }
      ]
    }'
  ```

  ```json theme={null}
  {
    "status": "success",
    "message": "Pledge quote created successfully",
    "data": {
      "id": "PLQ_iF6AVNpqi71h",
      "status": "quoted",
      "expires_at": "2026-07-16T15:34:03.681633Z",
      "reference": "credit_agreement_93b7",
      "can_create": true,
      "items": [{ "asset": "USDT", "amount": "100", "can_lock": true }]
    }
  }
  ```
</Accordion>

Check `can_create` and each item's `can_lock` before proceeding. A `false` value means that asset can't currently be locked for this customer.

## 2. Create the pledge

Using the quote's `id`, lock the assets.

<Accordion title="Request and response">
  ```bash theme={null}
  curl -X POST https://api.busha.io/v1/pledges \
    -H "Authorization: Bearer $CUSTOMER_ACCESS_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
      "quote_id": "PLQ_iF6AVNpqi71h"
    }'
  ```

  ```json theme={null}
  {
    "status": "success",
    "message": "Pledge created successfully",
    "data": {
      "id": "PLG_zyGKA90DLjiA",
      "status": "authorized",
      "reference": "credit_agreement_93b7",
      "customer_profile_id": "a8002eb5-e170-4a33-9ab1-43f53532676e",
      "beneficiary_profile_id": "BUS_CQr0jPzGGzmn1uW5W7OVs",
      "mandate_hash": "sha256:9969916fb37d5cb275fea31b2bae3982781cc7c59ce0ac89456dd14c8ca840ed",
      "expires_at": "2026-07-16T15:34:03.681633Z",
      "items": [
        {
          "id": "PLI_OdfLCpvbqTU3",
          "asset": "USDT",
          "locked_amount": "100",
          "released_amount": "0",
          "liquidated_amount": "0",
          "available_to_release": "100",
          "status": "locked"
        }
      ],
      "events": [
        {
          "id": "PLE_jssHLw5HgjdC",
          "type": "pledge.created",
          "actor_type": "customer",
          "reference": "credit_agreement_93b7",
          "created_at": "2026-07-16T15:33:06.419377Z"
        }
      ]
    }
  }
  ```
</Accordion>

The customer's USDT is now locked. Save the pledge `id`, you'll need it for every subsequent call.

<Warning>
  Activate the pledge immediately after creating it. The pledge inherits its
  quote's `expires_at`, and `activate` will reject once that window closes.
</Warning>

## 3. Activate the pledge

Once you've disbursed the credit to the customer, confirm the agreement is live.

<Accordion title="Request and response">
  ```bash theme={null}
  curl -X POST https://api.busha.io/v1/pledges/PLG_zyGKA90DLjiA/activate \
    -H "Authorization: Bearer $CUSTOMER_ACCESS_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
      "reference": "activation_disb_9f1"
    }'
  ```

  ```json theme={null}
  {
    "status": "success",
    "message": "Pledge activated successfully",
    "data": {
      "id": "PLG_zyGKA90DLjiA",
      "status": "active",
      "activated_at": "2026-07-16T16:26:31.273764Z",
      "event_id": "PLE_v1zivzYjJQZW"
    }
  }
  ```
</Accordion>

## 4. Add pledge items

Grow a pledge into a multi asset pledge, or add more of an asset already on the pledge.

<Accordion title="Request and response">
  ```bash theme={null}
  curl -X POST https://api.busha.io/v1/pledges/PLG_zyGKA90DLjiA/items \
    -H "Authorization: Bearer $CUSTOMER_ACCESS_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
      "reference": "topup_7af2",
      "items": [
        { "asset": "NGN", "amount": "25000" }
      ],
      "reason": "beneficiary_requested_top_up"
    }'
  ```

  ```json theme={null}
  {
    "status": "success",
    "message": "Pledge items added successfully",
    "data": {
      "id": "PLG_zyGKA90DLjiA",
      "status": "active",
      "items": [
        {
          "id": "PLI_OdfLCpvbqTU3",
          "asset": "USDT",
          "locked_amount": "100",
          "released_amount": "0",
          "liquidated_amount": "0",
          "available_to_release": "100",
          "status": "locked"
        },
        {
          "id": "PLI_pu1OE5fOsvCz",
          "asset": "NGN",
          "locked_amount": "25000",
          "released_amount": "0",
          "liquidated_amount": "0",
          "available_to_release": "25000",
          "status": "locked"
        }
      ],
      "event_id": "PLE_fotEJyQDJnRi"
    }
  }
  ```
</Accordion>

## 5. Release collateral as the customer repays

Each time the customer makes a repayment, release the corresponding share of collateral. Set `full_release: true` once the agreement is fully repaid.

<Accordion title="Request and response">
  ```bash theme={null}
  curl -X POST https://api.busha.io/v1/pledges/PLG_zyGKA90DLjiA/release \
    -H "Authorization: Bearer $CUSTOMER_ACCESS_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
      "reference": "release_rel_901",
      "full_release": false,
      "reason": "partial_repayment",
      "items": [
        { "pledge_item_id": "PLI_OdfLCpvbqTU3", "amount": "20" }
      ]
    }'
  ```

  ```json theme={null}
  {
    "status": "success",
    "message": "Pledge released successfully",
    "data": {
      "id": "PLG_zyGKA90DLjiA",
      "status": "active",
      "released_items": [
        {
          "pledge_item_id": "PLI_OdfLCpvbqTU3",
          "asset": "USDT",
          "released_amount": "20",
          "remaining_locked_amount": "80"
        }
      ],
      "event_id": "PLE_ei7aPWLHp0zi"
    }
  }
  ```
</Accordion>

## 6. List and get pledges

<Accordion title="List pledges: request and response">
  ```bash theme={null}
  curl -X GET https://api.busha.io/v1/pledges \
    -H "Authorization: Bearer $CUSTOMER_ACCESS_TOKEN"
  ```

  ```json theme={null}
  {
    "status": "success",
    "message": "Pledges retrieved successfully",
    "data": [
      {
        "id": "PLG_zyGKA90DLjiA",
        "status": "active",
        "reference": "credit_agreement_93b7",
        "customer_profile_id": "a8002eb5-e170-4a33-9ab1-43f53532676e",
        "beneficiary_profile_id": "BUS_CQr0jPzGGzmn1uW5W7OVs",
        "activated_at": "2026-07-16T16:26:31.273764Z",
        "expires_at": "2026-07-16T15:34:03.681633Z"
      }
    ],
    "pagination": { "current_entries_size": 1 }
  }
  ```
</Accordion>

<Accordion title="Get pledge: request and response">
  ```bash theme={null}
  curl -X GET https://api.busha.io/v1/pledges/PLG_zyGKA90DLjiA \
    -H "Authorization: Bearer $CUSTOMER_ACCESS_TOKEN"
  ```

  ```json theme={null}
  {
    "status": "success",
    "message": "Pledge retrieved successfully",
    "data": {
      "id": "PLG_zyGKA90DLjiA",
      "status": "active",
      "reference": "credit_agreement_93b7",
      "customer_profile_id": "a8002eb5-e170-4a33-9ab1-43f53532676e",
      "beneficiary_profile_id": "BUS_CQr0jPzGGzmn1uW5W7OVs",
      "mandate_hash": "sha256:e86ce63cf627eb1f7759cbd7474a24066697261027e3b41d1e89c9ec9f52d7a3",
      "items": [
        {
          "id": "PLI_5VXlrc4dT34U",
          "asset": "USDT",
          "locked_amount": "80",
          "released_amount": "20",
          "liquidated_amount": "0",
          "available_to_release": "80",
          "status": "locked"
        }
      ],
      "events": []
    }
  }
  ```

  Use `GET /v1/pledges/{id}` when you need the full items array. `GET /v1/pledges` (list) is best for browsing and filtering across many pledges.
</Accordion>

## 7. Request and cancel liquidation

If the customer defaults, request liquidation. This requires the `pledges:liquidate` scope, requested separately from `pledges:write` and `pledges:read` at authorization time.

<Accordion title="Request liquidation: request and response">
  ```bash theme={null}
  curl -X POST https://api.busha.io/v1/pledges/PLG_zyGKA90DLjiA/liquidations \
    -H "Authorization: Bearer $CUSTOMER_ACCESS_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
      "reference": "default_case_348",
      "reason": "default_under_beneficiary_terms",
      "beneficiary_due": { "amount": "30", "currency": "USDT" },
      "items": [
        { "pledge_item_id": "PLI_5VXlrc4dT34U", "amount": "30" }
      ],
      "evidence": {
        "missed_payments": 2,
        "notes": "customer missed two consecutive repayments"
      }
    }'
  ```

  ```json theme={null}
  {
    "status": "success",
    "message": "Pledge liquidation requested successfully",
    "data": {
      "id": "PLR_kO8ErlYYALPO",
      "pledge_id": "PLG_btRodtIrderK",
      "status": "pending_execution",
      "notice_period_seconds": 86400,
      "execute_after": "2026-07-18T09:53:23.943401Z",
      "beneficiary_due": { "amount": "30", "currency": "USDT" },
      "created_at": "2026-07-17T09:53:23.947377Z"
    }
  }
  ```
</Accordion>

The liquidation does not execute immediately. It sits in `pending_execution` until `execute_after`, giving the customer time to resolve the default.

<Accordion title="Cancel liquidation: request and response">
  ```bash theme={null}
  curl -X POST https://api.busha.io/v1/pledges/PLG_btRodtIrderK/liquidations/PLR_kO8ErlYYALPO/cancel \
    -H "Authorization: Bearer $CUSTOMER_ACCESS_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
      "reference": "cancel_default_case_348",
      "reason": "customer_repaid"
    }'
  ```

  ```json theme={null}
  {
    "status": "success",
    "message": "Pledge liquidation cancelled successfully",
    "data": {
      "id": "PLR_kO8ErlYYALPO",
      "pledge_id": "PLG_btRodtIrderK",
      "status": "cancelled",
      "cancelled_at": "2026-07-17T09:54:17.108889Z",
      "event_id": "PLE_9MnJOklrhaF5"
    }
  }
  ```
</Accordion>

## Errors

Pledge endpoints return the standard Busha error envelope. See [OAuth2 Errors](/guides/oauth/errors) for authorization layer failures like `invalid_grant` or `insufficient_scope`.

| Error                                                                            | Cause                                                                                                                                                                                | Fix                                                                                                                             |
| -------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------- |
| `request_validation`, "Invalid pledge identity"                                  | The request used a business Secret Key, or an OAuth2 token without a valid customer identity attached.                                                                               | Authenticate with a customer scoped OAuth2 access token. See [Before you begin](/guides/pledges/introduction#before-you-begin). |
| `resource_state_conflict`, "Pledge is not in the required state"                 | Most commonly, the pledge's `expires_at` window closed before you called activate. Can also occur when an action is attempted against a pledge in an incompatible status.            | Activate the pledge immediately after creating it. Check the pledge's current `status` via Get pledge before retrying.          |
| `Forbidden`, "oauth2: missing required scope"                                    | The access token doesn't carry the scope the endpoint requires, most often `pledges:liquidate` on the liquidation endpoints.                                                         | Re-run the OAuth2 authorization flow requesting the missing scope. See [Scopes](/guides/oauth/scopes#pledges).                  |
| `request_validation`, schema errors on `items`, `beneficiary_due`, or `evidence` | A required field is missing from a multi-part body, common on Request pledge liquidation, which requires `reference`, `reason`, `beneficiary_due`, `items`, and `evidence` together. | Check the `fields` object in the error response against the endpoint's required body parameters.                                |
