# Partner API Integration Guide

This guide walks you through integrating with Resolve's Partner API. It covers authentication, core concepts, common workflows, webhooks, and error handling. For full endpoint details, see the [Partner API Reference](https://api-docs.resolvepay.com/partners-api/openapi).

## Before You Start

To use the Partner API, you need:

1. A **Partner Merchant account** provisioned by Resolve
2. **OAuth 2.0 client credentials** (client ID and client secret) issued by Resolve
3. At least one **sub-merchant** onboarded and active under your partner account


Contact your Resolve account manager to get set up.

## Authentication

The Partner API uses **OAuth 2.0 Client Credentials** for authentication. This is a machine-to-machine flow — no user interaction required.

### Getting an Access Token

Exchange your client credentials for an access token:


```
POST /oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials
&client_id=YOUR_CLIENT_ID
&client_secret=YOUR_CLIENT_SECRET
```

The response includes an access token:


```json
{
  "access_token": "eyJhbGciOiJSUzI1NiIs...",
  "token_type": "Bearer",
  "expires_in": 3600
}
```

### Using the Token

Include the token in the `Authorization` header on all subsequent requests:


```
Authorization: Bearer eyJhbGciOiJSUzI1NiIs...
```

Tokens expire after the duration specified in `expires_in` (in seconds). Your integration should handle token refresh automatically — request a new token before the current one expires.

> **Note:** Partner API credentials are separate from Merchant API credentials. Partner credentials only work with `partner-v1` endpoints.


## Core Concepts

### Partner and Sub-Merchant Model

As a partner, your account is a **partner merchant** with one or more **sub-merchants** underneath it. Each sub-merchant is a business that sells to buyers through your platform. You manage all sub-merchants through a single API integration.

How credit lines and buyer relationships work depends on whether your partner account is configured as a **marketplace** or a **non-marketplace** partner.

### Marketplace Partners

Marketplace partners operate platforms where buyers purchase from multiple sub-merchants in a single ecosystem (e.g., a wholesale marketplace connecting retailers to many brands).

**Credit lines are shared across sub-merchants.** When a buyer is approved for credit with a marketplace partner, that credit line is usable for purchases from *any* sub-merchant under the partner. The buyer applies once, gets one credit line, and can use it across the entire marketplace.

This means:

- Buyers apply for credit at the **partner level**, not with individual sub-merchants
- A single credit decision covers all sub-merchants
- Available credit is drawn down across purchases regardless of which sub-merchant the buyer is purchasing from
- Invoices are created against a specific sub-merchant, but the credit relationship lives at the partner level


**Example:** A retailer approved for $50K on your marketplace can place a $20K order with Sub-Merchant A and a $30K order with Sub-Merchant B, both drawing from the same $50K line.

### Non-Marketplace Partners

Non-marketplace partners operate platforms where buyers have distinct, independent relationships with each sub-merchant (e.g., a SaaS platform that provides invoicing tools to independent distributors).

**Credit lines are dedicated to individual sub-merchants.** When a buyer is approved, their credit line is specific to a single sub-merchant. Purchasing from a different sub-merchant under the same partner requires a separate credit application and approval.

This means:

- Buyers apply for credit **per sub-merchant**
- Each sub-merchant relationship has its own credit line and limit
- Available credit with one sub-merchant has no bearing on credit with another
- Invoices and credit are scoped entirely to the sub-merchant level


**Example:** A buyer approved for $50K with Sub-Merchant A and $30K with Sub-Merchant B has two independent credit lines. Using $40K with Sub-Merchant A leaves $10K available there, but the full $30K is still available with Sub-Merchant B.

### Which Model Am I On?

Your marketplace/non-marketplace configuration is set during onboarding with Resolve. If you're unsure which model applies to your integration, check with your Resolve account manager. This setting affects how you should think about credit checks, customer lookups, and invoice creation in your integration.

### API Versioning

The Partner API uses version `partner-v1`. This is a separate version from Resolve's Merchant API (v3/v4/v5) and has its own request/response schemas.

### Pagination

All top-level API resources have support for bulk fetches via "list" API methods.

These list API methods share a common structure, taking at least two parameters: `limit` and `page`.

- `count` - represents total amount of records satisfying the request query.
- `page` - a multiplier value, which gets applied to the `limit` and shows what position records are being returned from. For example, if `limit = 20` and `page = 5`, then maximum `20` records will be returned from position `5 * 20 = 100`.
- `limit` - maximum amount of records which can be returned.
- `results` - array of records being returned. If no records satisfy request condition, the array will be empty.


### Filtering

List endpoints support filtering via query parameters. Filters vary by resource — see the [API Reference](https://api-docs.resolvepay.com/partners-api/openapi) for available filters on each endpoint.

## Common Workflows

### 1. Creating an Invoice

The most common workflow is creating an invoice for a buyer purchasing from one of your sub-merchants.

**Prerequisites:**

- The buyer (customer) exists and has an approved credit line
- The sub-merchant is active under your partner account


**Steps:**

1. **Look up the customer** to confirm they have available credit:

```
GET /customers?filter[email][eq]=buyer@example.com
```
2. **Create the invoice** against the appropriate sub-merchant:

```json
POST /invoices
{
  "merchant_id": "sub_merchant_id",
  "customer_id": "customer_id",
  "amount": 5000.00,
  "terms": "net30",
  "number": "INV-001"
}
```
3. **Track the invoice** as it moves through its lifecycle:

```
GET /invoices/{invoice_id}
```


### 2. Managing Customers (Buyers)

Customers are buyers who have been approved for credit through Resolve.

- **List customers** across all your sub-merchants:

```
GET /customers
```
- **Get a specific customer** with their credit details:

```
GET /customers/{customer_id}
```


How credit lines work depends on your partner configuration. **Marketplace partners:** credit is at the partner level — a buyer's approval covers all sub-merchants. **Non-marketplace partners:** credit is per sub-merchant — check that the buyer has a credit line with the specific sub-merchant before creating an invoice.

### 3. Tracking Payments

Monitor payment activity on invoices:


```
GET /payments
```

Payments are tracked automatically as buyers pay their invoices through Resolve. You can filter by customer_id, status, or amount.

### 4. Tracking Payouts

Payouts represent the funds Resolve sends to you (or directly to your sub-merchants, depending on your configuration).

- **List payouts** to see settlement summaries:

```
GET /payouts
```
- **Get payout transactions** to see the line-item breakdown of a payout:

```
GET /payout_transactions
```


> **Payout configuration:** Depending on your setup, payouts may be batched to your partner account or sent directly to individual sub-merchants. This is configured during onboarding.


### 5. Issuing Credit Notes

If a buyer needs a refund or credit adjustment:


```json
POST /credit_notes
{
  "invoice_id": "invoice_id",
  "amount": 500.00,
  "reason": "Partial return"
}
```

### 6. Recording Shipments

Track shipment information against invoices:


```json
POST /shipments
{
  "merchant_invoice_id": "invoice_id",
  "shipment_tracking_number": "1Z999AA10123456784",
  "shipment_courier": "UPS"
}
```

### 7. Submitting a Merchant for Underwriting

Partners can programmatically submit new merchants (sub-merchants) for Resolve underwriting via the Merchant Underwriting API. This replaces the manual process of having Resolve create merchant accounts through the admin dashboard.

**Create a merchant and submit for underwriting:**


```json
POST /merchants
{
  "legal_business_name": "Acme Wholesale LLC",
  "business_address": {
    "line1": "123 Commerce St",
    "city": "Los Angeles",
    "state": "CA",
    "postal_code": "90001",
    "country": "US"
  },
  "business_email": "ap@acmewholesale.com",
  "business_phone": "310-555-0100",
  "entity_type": "llc",
  "formation_state": "CA",
  "ein": "12-3456789"
}
```

This single call creates a merchant record, auto-submits a merchant application, and triggers the underwriting workflow. The response returns the merchant ID and an initial underwriting status.

**Required fields:** `legal_business_name`, `business_address`, `business_email`, `business_phone`, `entity_type`, `formation_state`, `ein`

**Optional fields that strengthen underwriting:** `dba_name`, `annual_revenue`, `years_in_business`, `industry`, `website`, `beneficial_owners`, `authorized_signer`, `bank_account_number`, `bank_routing_number`, `estimated_monthly_net_terms_volume`, `existing_net_terms_info`, `metadata`, `bank_statements`, `financial_statements`, `credit_references`, `personal_guarantee`, `other_documents`

**Check underwriting status:**


```
GET /merchants/{merchant_id}
```

Returns the merchant profile including the current underwriting status and, when available, the Merchant Approved Limit (MAL).

**Update merchant information after submission:**


```
PUT /merchants/{merchant_id}
```

Use this to add supplemental data after initial creation — for example, adding optional business details, submitting follow-up documents, or responding when additional information is requested.

### Document Uploads

Merchants may need to provide supporting documents such as bank statements, financial statements, credit references, personal guarantee documents, or other underwriting materials. The API supports two document ingestion flows through the same endpoint:

- **Direct upload**: Request upload instructions from Resolve, then upload the file directly to the returned S3 URL.
- **Resolve-downloaded file**: Provide a remote file URL, and Resolve fetches the file asynchronously.


The flow is determined by whether `download_url` is included in the request.

**Direct upload example:**


```json
POST /merchants/{merchant_id}/documents
{
  "document_type": "bank_statements",
  "filename": "bank_statement_2026_01.pdf",
  "filetype": "application/pdf"
}
```

In this flow, Resolve returns upload instructions including an `upload_url`, expiration time, any required `upload_headers`, and metadata describing the document request.

**Resolve-downloaded file example:**


```json
POST /merchants/{merchant_id}/documents
{
  "document_type": "bank_statements",
  "filename": "bank_statement_2026_01.pdf",
  "filetype": "application/pdf",
  "download_url": "https://partner-files.example.com/bank_statement_2026_01.pdf"
}
```

In this flow, Resolve accepts the document request and queues the file for asynchronous retrieval and validation.

**Including documents during merchant creation:**

You can also include document ingestion requests directly in `POST /merchants` using document arrays such as `bank_statements`, `financial_statements`, `credit_references`, `personal_guarantee`, and `other_documents`. Each document entry uses the same per-document shape shown above: `filename`, `filetype`, and `download_url`.

Documents are validated asynchronously. Use the relevant merchant and webhook flows to track when underwriting progresses and when supporting information is needed.

### Underwriting Decision Flow

1. Partner calls `POST /merchants` with the required merchant details.
2. Resolve creates the merchant record and application, and begins the underwriting workflow.
3. Resolve's Risk team reviews the submission:
  - **Public data only** (Experian + revenue signals): Conservative MAL
  - **Bank statements provided**: Higher MAL possible
  - **Plaid connected**: Strongest underwriting with real-time financial data
4. Risk makes a decision such as approval, decline, or request for additional information.
5. Webhook fires: `merchant.underwriting_completed`
6. Partner retrieves the latest merchant state via `GET /merchants/{merchant_id}`.


### Underwriting Webhook Events

- `merchant.created` — Merchant record created
- `merchant.underwriting_completed` — Decision made (approved or declined)
- `merchant.more_info_needed` — Additional information required
- `merchant.mal_updated` — Merchant Approved Limit changed


> **Tip:** Providing optional fields like `annual_revenue`, `beneficial_owners`, and supporting documents upfront can speed up the underwriting process and improve underwriting outcomes.


## Webhooks

Webhooks let you receive real-time notifications when events happen in Resolve — like a payment being received, an invoice status changing, or a credit decision being made.

### Setting Up Webhooks

1. **Create or update a webhook subscription:**

```json
POST /webhooks
{
  "endpoint_url": "https://example.com/webhooks/resolve",
  "events": {
    "invoice.created": true,
    "invoice.balance_updated": true,
    "customer.created": true,
    "customer.credit_decision_created": true
  }
}
```
2. **List your subscriptions:**

```
GET /webhooks
```
3. **Delete a subscription:**

```
PUT /webhooks/{webhook_id}
DELETE /webhooks
```


### Webhook Delivery

Webhook events are delivered as `POST` requests to your registered URL. Events are sent for activity across all your sub-merchants — you don't need a separate subscription per sub-merchant.

Each webhook payload includes the event type, the resource that changed, and relevant IDs so you can look up full details via the API.

### Best Practices

- **Respond quickly**: Return a `200` status within 5 seconds. Do heavy processing asynchronously.
- **Handle duplicates**: Webhook deliveries may be retried. Use the event ID to deduplicate.
- **Verify payloads**: Validate that webhook requests are genuinely from Resolve.


## Error Handling

The Partner API returns standard HTTP status codes:

| Status | Meaning |
|  --- | --- |
| `200` | Success |
| `201` | Created |
| `400` | Bad request — check your request body or parameters |
| `401` | Unauthorized — your token is missing, expired, or invalid |
| `403` | Forbidden — you don't have access to this resource |
| `404` | Not found — the resource doesn't exist or isn't under your partner account |
| `422` | Unprocessable — the request is well-formed but can't be completed (e.g., insufficient credit) |
| `429` | Rate limited — slow down and retry with backoff |
| `500` | Server error — retry with exponential backoff |


Error responses include a structured body:


```json
{
  "error": {
    "message": "Validation error",
    "type": "validation_error",
    "details": [
      {
        "path": "path.to.field",
        "message": "`[field]` is required"
      }
    ]
  }
}
```

### Rate Limits

The Partner API enforces rate limits to ensure platform stability. If you receive a `429` response, implement exponential backoff before retrying.

## Testing

Resolve provides a sandbox environment for testing your integration. Contact your Resolve account manager for sandbox credentials and endpoint URLs.

In the sandbox:

- Create test customers with instant approval
- Simulate invoice creation and payment flows
- Test webhook delivery to your staging endpoints
- Verify error handling and edge cases


## Next Steps

- [**Partner API Reference**](https://api-docs.resolvepay.com/partners-api/openapi) — Full endpoint documentation with request/response schemas
- **Contact Support** — Reach out to your Resolve account manager or email [support@resolvepay.com](mailto:support@resolvepay.com)