# Everest Partner Integration Playbook

This playbook is for businesses integrating Everest delivery into their own checkout, order, or dispatch workflows.

## Required Setup

Before going live, every partner should have:

- Approved partner account.
- Business and owner verification approved.
- Activated developer portal account using the one-time approval token.
- Finance, developer, and support teammates invited with the smallest role they need.
- Team role changes, access disablement, and activation-link recovery tested by an owner or admin.
- Each teammate has reviewed sign-in activity and tested the portal's sign-out-all-sessions control.
- Sandbox API key with `deliveries:create`, `deliveries:read`, `webhooks:manage`, `billing:read`, and `sandbox:simulate`.
- Sandbox reset tested from the developer portal if test credentials or deliveries need a clean slate.
- Webhook endpoint with signature verification.
- Delivery quote shown to the customer before payment.
- Idempotent delivery creation after order/payment confirmation.
- Ledger reconciliation workflow for delivery charges, top-ups, and invoices.
- Portal wallet top-up tested for prepaid partners.
- Live access activated from the developer portal after readiness checks pass.
- Live key issued once the portal reports live access as active.
- Support can open delivery details, record proof, cancel eligible deliveries, and retry deferred dispatch from the portal.

## Onboarding Flow

1. Business submits the partner application from the developer portal or `POST /applications/`.
2. Business adds legal name, registration type/number, tax reference, operating address, owner/admin identity reference, consent, and document availability.
3. Everest emails the application ID and a status link to the contact email. The business can also check review state with `GET /applications/{application_id}/status/?contact_email=...`; the response never returns raw keys or activation tokens.
4. Everest reviews the application, verifies business evidence, sets risk tier, approves the application, and configures sandbox services, cities, billing mode, and credit limit.
5. The partner receives an activation email. Sensitive credentials are shared only through secure one-time approval responses.
6. Partner activates their portal account with `POST /portal/auth/activate/`.
7. Partner signs in with `POST /portal/auth/login/` or the web developer portal.
8. Partner creates webhook endpoints and tests sandbox deliveries from the portal or API.
9. Partner checks `GET /portal/readiness/` and fixes any missing go-live evidence.
10. Partner activates live access when readiness checks are complete.
11. Verified standard-risk accounts activate immediately; accounts flagged during verification enter an additional review queue.
12. The partner issues a one-time live key from the portal and can create additional live keys as needed.

Public application submissions are limited by IP address and contact email. A `429 application_rate_limited` response includes `Retry-After`; clients should wait before retrying instead of submitting duplicates.

## Portal Account Security

Each teammate can review their own recent portal activity with `GET /portal/security/events/`. The history includes successful and failed sign-ins, password recovery, session revocation, and access changes, with request, IP, and browser details when available.

The Everest web developer portal keeps partner access and refresh tokens in secure, HTTP-only, same-site cookies. Browser scripts receive partner profile data but cannot read the credentials. Portal requests pass through the same-origin session proxy, which refreshes access server-side and clears the cookies after sign-out, session revocation, or failed authentication.

Use `POST /portal/security/sessions/revoke/` after a lost device, shared-session concern, or suspected account access. The call invalidates all of that user's partner-portal access tokens, including tokens created later from an older refresh token, and the user must sign in again. A password change, activation-link use, or team-member disablement applies the same protection automatically.

Owners and admins should disable a departing teammate instead of only rotating API credentials. Disabling the membership blocks new portal sessions and immediately invalidates existing ones. API credentials remain partner resources and should be reviewed separately on the Credentials page.

## Business Verification Model

Everest should keep onboarding fluid but still protect live fleet access:

- Public docs remain open.
- Initial application captures only business, use case, contact, cities, service type, and volume.
- Verification captures legal name, registration type, registration number, tax reference, addresses, owner/admin details, identity reference type, last four digits only, consent, and document availability.
- Sandbox access can be approved while non-critical verification items are pending.
- Live access requires `business_verification` to pass in portal readiness.
- Everest review can mark verification as `VERIFIED`, `PENDING`, `NEEDS_INFO`, or `REJECTED`, and assign `LOW`, `STANDARD`, or `HIGH` risk tier.

Do not collect full identity numbers in ordinary application payloads. Store provider references, document statuses, and last-four identity references unless a secure verification provider or approved verification flow is used.

## Ecommerce Checkout Flow

Use this when a store sells products and wants Everest to handle last-mile delivery.

1. Customer enters delivery address at checkout.
2. Store calls `POST /delivery-quotes/`.
3. Store displays the returned delivery fee beside the item subtotal.
4. Customer pays item total plus delivery fee to the merchant.
5. Store calls `POST /deliveries/` with `quote_id` and `Idempotency-Key`.
6. Everest dispatches or defers dispatch depending on environment and feature flags.
7. Store shows `tracking_url` on the customer order page.
8. Store listens for `partner.delivery.status_changed` and `partner.delivery.proof_recorded`.
9. Finance reconciles delivery charges through `GET /ledger-entries/` or CSV export.

Minimum webhooks:

```text
partner.delivery.status_changed
partner.delivery.proof_recorded
partner.billing.invoice.issued
partner.billing.invoice.paid
```

Sandbox test path:

```text
Quote -> Create delivery -> Simulate ASSIGN_DRIVER -> Simulate PICKUP -> Simulate COMPLETE -> Confirm ledger POSTED
```

## Restaurant Order Flow

Use this for hot food delivery where speed and handoff status matter.

1. Restaurant estimates prep time in its order system.
2. App calls `POST /delivery-quotes/` when the customer confirms address.
3. App collects food cost plus delivery fee.
4. App calls `POST /deliveries/` when the kitchen accepts the order.
5. Kitchen dashboard watches status and pickup proof.
6. Customer sees `tracking_url`.
7. Restaurant support uses webhook logs and API audit logs to investigate failed deliveries.

Recommended metadata:

```json
{
  "order_type": "restaurant",
  "prep_eta_minutes": 25,
  "branch_id": "lekki-01",
  "kitchen_ticket": "KT-1001"
}
```

Sandbox test path:

```text
Quote -> Create delivery -> Simulate ASSIGN_DRIVER -> Simulate PICKUP at handoff -> Simulate COMPLETE at customer
```

## Pharmacy Or Supermarket Flow

Use this for controlled items, substitutions, heavier baskets, or support-heavy delivery.

1. Store confirms item availability before quote acceptance.
2. Store calls `POST /delivery-quotes/` with package weight.
3. Customer pays merchant.
4. Store calls `POST /deliveries/` with delivery instructions and metadata.
5. Store records any extra compliance or picker metadata on its own system.
6. Everest status changes are mirrored into the store order page.
7. Finance exports ledger CSV daily or weekly.

Recommended metadata:

```json
{
  "order_type": "pharmacy_or_supermarket",
  "basket_id": "BASKET-1001",
  "picker_id": "PICKER-07",
  "requires_recipient_call": true
}
```

Sandbox test path:

```text
Quote -> Create delivery -> Simulate NO_DRIVER or FAIL -> Confirm pending charge is voided -> Retry a new delivery
```

## Webhook Verification Checklist

Partners must verify:

- `X-Everest-Webhook-Timestamp` is recent enough for their replay window.
- `X-Everest-Webhook-Signature` matches HMAC-SHA256 over `timestamp + "." + raw_body`.
- `X-Everest-Webhook-Delivery` is stored and deduplicated.
- Event handlers are idempotent.
- Unknown event types are logged but do not crash the webhook receiver.

To test a receiver without creating a real delivery:

```bash
curl -sS -X POST "$BASE_URL/api/partners/v1/webhook-endpoints/$ENDPOINT_ID/test/" \
  -H "Content-Type: application/json" \
  -H "X-Everest-Partner-Key: $SANDBOX_PARTNER_KEY" \
  -d '{
    "event_type": "partner.delivery.created",
    "payload": {
      "external_order_id": "TEST-WEBHOOK-ORDER"
    },
    "deliver_now": true
  }'
```

## Go-Live Checklist

- Sandbox quote and delivery creation tested.
- Portal test delivery creator completed at least one sandbox delivery lifecycle.
- `GET /portal/readiness/` returns `ready_for_go_live: true`.
- Business verification check returns `PASS`.
- Developer portal activation and login tested.
- Security activity reviewed and sign-out-all-sessions tested.
- Sandbox simulator tested for `ASSIGN_DRIVER`, `PICKUP`, `COMPLETE`, `FAIL`, and `NO_DRIVER`.
- Sandbox reset tested and the fresh one-time sandbox key stored outside source code.
- Webhook test event delivered successfully.
- Webhook signature verification implemented.
- Delivery creation uses idempotency keys.
- Checkout uses quote expiry correctly and does not charge expired quotes.
- Partner understands prepaid wallet or postpaid invoice model.
- Prepaid wallet top-up initialized and verified from the portal if applicable.
- Billing summary and ledger CSV tested by finance.
- Portal reports live access as `APPROVED`.
- Live-access confirmation email received by the partner.
- Production IP allowlist configured if required.
- Live key stored in secret manager, not source code.
- Support, technical, and finance contacts are set in partner profile.

## Failure Handling

If delivery creation returns `409`, do not retry with a changed body under the same `Idempotency-Key`. Create a new idempotency key after fixing the request.

If a webhook fails, Everest records the delivery attempt. Partners can inspect `GET /webhook-deliveries/` and requeue with `POST /webhook-deliveries/{webhook_delivery_id}/retry/`.

If a quote expires before checkout completes, call `POST /delivery-quotes/` again and show the updated fee to the customer before payment.

If sandbox data becomes noisy during implementation, use `POST /portal/sandbox/reset/` from an authenticated developer portal session. This cancels only non-terminal sandbox deliveries, expires sandbox quotes, revokes sandbox keys, voids pending sandbox delivery charges, and returns a fresh sandbox key once. It does not affect live credentials, live deliveries, or active Everest operations.
