# Onboard merchants through Statira partner APIs

These APIs let an authorized platform onboard and track its own merchants. Partner credentials are separate from merchant API keys and e-commerce keys. They do not authorize spending from merchant wallets.

## Credentials and environments

Statira issues an expiring partner invitation. Redeem it and save the partner API key immediately; only its hash is retained. Use credentials issued for the target environment:

- LIVE: `https://api.paywithstatira.com`
- TEST: `https://api.dev.paywithstatira.com`

Every partner API request uses:

```http
X-Partner-Id: <your-partner-id>
X-Partner-Key: <your-partner-api-key>
```

Keep these headers server-side. Paths containing `{externalUserId}` refer to your platform's stable identifier, URL-encoded as a path segment. A partner can retrieve only its own links.

## 1. Create a merchant

```http
POST /api/v1/partners/merchants
Content-Type: application/json
X-Partner-Id: marketvillage
X-Partner-Key: <partner-api-key>

{
  "externalUserId": "seller-123",
  "ownerEmail": "owner@example.com",
  "ownerFirstName": "Ada",
  "ownerLastName": "Example",
  "businessName": "Example Trading Limited",
  "displayName": "Example Store",
  "businessEmail": "business@example.com",
  "businessPhone": "+2348000000000",
  "businessType": "LIMITED_LIABILITY_COMPANY",
  "countryCode": "NG",
  "currencyCode": "NGN"
}
```

All fields except `businessPhone` are required. Supported business types: `SOLE_PROPRIETORSHIP`, `LIMITED_LIABILITY_COMPANY`, `PARTNERSHIP`, `NON_PROFIT`, `GOVERNMENT`, `OTHER`. Country/currency currently supported here: `NG` / `NGN`.

The response envelope's `data` includes `partnerId`, `externalUserId`, `statiraUserId`, `ownerEmail`, `merchant`, `kycStatus`, `kycDocuments`, and `created`. Store `merchant.id` alongside your external user ID. Creation does not mean approval or activation; display the returned statuses.

Retry using the same externalUserId and owner email after an uncertain response. If the link already exists, Statira returns it with `created: false`. An external ID already linked to a different owner is rejected. Do not generate a new external ID for each retry.

## 2. Handle an owner who already exists

If the owner email already belongs to an existing Statira merchant, new onboarding returns a conflict. The same owner email is not treated as a new user just because a new business name was submitted. A mismatched business must be resolved with Statira; do not change identity details to bypass the check.

To link the owner's existing merchant with consent:

```http
POST /api/v1/partners/merchants/link-requests
Content-Type: application/json

{
  "externalUserId": "seller-123",
  "ownerEmail": "owner@example.com",
  "businessName": "Example Trading Limited",
  "businessEmail": "business@example.com"
}
```

Include the partner headers. The owner receives an OTP. Use the returned request reference:

```http
POST /api/v1/partners/merchants/link-requests/{requestReference}/verify
Content-Type: application/json

{"otp":"123456"}
```

The owner must provide their actual OTP. `GET /api/v1/partners/merchants/link-requests/{requestReference}` retrieves request status. Successful verification returns the linked merchant. Linking an already approved merchant does not generate a fresh merchant-approval notification.

## 3. Upload KYC documents

```bash
curl -X POST 'https://api.paywithstatira.com/api/v1/partners/merchants/seller-123/kyc/documents' \
  -H 'X-Partner-Id: marketvillage' \
  -H 'X-Partner-Key: <partner-api-key>' \
  -F 'documentType=CAC_CERTIFICATE' \
  -F 'file=@cac-certificate.pdf'
```

Upload representative identity using one of `DIRECTOR_ID`, `AUTHORIZED_SIGNATORY_ID`, or `BENEFICIAL_OWNER_ID`. Let the HTTP client set the multipart content type and boundary.

Current minimum documents for administrator approval:

- CAC certificate: **APPROVED**
- Representative identity: **APPROVED**

Proof of business address is optional for now. Uploading a document does not approve it. Statira reviews it; partners cannot approve their own merchants.

Read documents with `GET /api/v1/partners/merchants/{externalUserId}/kyc/documents`.

## 4. Complete and submit the KYC case

`GET /api/v1/partners/merchants/{externalUserId}/kyc` returns the profile, related parties, documents, and missing requirements. The document minimum above does not remove required business-profile and related-party fields for submitting a complete case.

Save the business profile:

```http
PUT /api/v1/partners/merchants/seller-123/kyc/profile
Content-Type: application/json

{
  "registrationNumber": "RC123456",
  "taxIdentificationNumber": "<business-TIN>",
  "registeredAddress": "<registered-address>",
  "businessAddress": "<business-address>",
  "websiteUrl": "https://shop.example.com",
  "natureOfBusiness": "Retail",
  "accountPurpose": "Receive customer payments",
  "sourceOfFunds": "Sales revenue",
  "expectedMonthlyTurnoverMinor": 50000000,
  "expectedMonthlyTransactionCount": 100,
  "actsForThirdParty": false
}
```

Registration number, TIN, both addresses, nature of business, purpose, source of funds, positive turnover, and positive transaction count are required. Supply `thirdPartyDetails` when acting for a third party. `websiteUrl` and `socialMediaHandle` are optional.

Add each required related party:

```http
POST /api/v1/partners/merchants/seller-123/kyc/related-parties
Content-Type: application/json

{
  "partyRole": "AUTHORIZED_SIGNATORY",
  "firstName": "Ada",
  "lastName": "Example",
  "dateOfBirth": "1990-01-01",
  "nationality": "Nigerian",
  "residentialAddress": "<residential-address>",
  "email": "owner@example.com",
  "phone": "+2348000000000",
  "ownershipBasisPoints": 10000,
  "politicallyExposed": false,
  "nationalIdentifierType": "NIN",
  "nationalIdentifier": "<actual-identifier>"
}
```

Use genuine owner-provided information. Every business needs an authorized signatory. Companies, partnerships, non-profits, and government entities also need a director or senior manager, and a beneficial owner. Allowed roles: `AUTHORIZED_SIGNATORY`, `DIRECTOR`, `SENIOR_MANAGER`, `BENEFICIAL_OWNER`. Allowed identifier types: `BVN`, `NIN`, `PASSPORT`. Include `pepDetails` when politically exposed. Ownership is in basis points (10000 = 100%).

Then call:

```http
POST /api/v1/partners/merchants/seller-123/kyc/submit
```

Include partner headers on every request. An incomplete case is rejected with its missing requirements. A complete submission enters review; it does not immediately activate the merchant.

## 5. Receive approval and retrieve current status

Configure your email and signed webhook through `PUT /api/v1/partners/notifications`. Follow the [approval notification contract](partner-approval-notifications.md) for the request, `merchant.approved` payload, signature checks, and retries.

Map notifications to the seller using `data.externalUserId`, and deduplicate by event ID. Approval sets merchant approval and KYC to `APPROVED` and account status to `ACTIVE`. New approval events wait in the queue until destinations are configured; historical approvals are not automatically replayed.

Retrieve the authoritative current merchant state at any time:

```http
GET /api/v1/partners/merchants/seller-123
X-Partner-Id: marketvillage
X-Partner-Key: <partner-api-key>
```

Do not use partner credentials as merchant payment or wallet credentials. Merchants create scoped API keys and authorize store connections separately; see [e-commerce keys](ecommerce-keys.md).
