# **Merchant Onboarding API**

Self-service configuration, catalogue uploads, and ongoing product updates

*Draft for discussion · 6 October 2026 · Proposed contracts, not deployed endpoints*

## **What this document explains**

The proposed merchant-facing HTTP API for onboarding to Agentic Commerce: configuring your checkout, uploading your product catalogue, and keeping products up to date.

Summary: One onboarding call saves your PSP credentials and checkout endpoint, and returns a signed URL for uploading your catalogue plus the MCP endpoint your agents connect to. Upload the catalogue file, call ingest, and poll until it completes. For smaller updates, upsert products directly. Your identity comes from your Airwallex credentials; secrets are never returned in responses.

# **1\. API surface**

All endpoints live on the standard API host under `/agentic-commerce`. Sandbox and production differ by host only; sandbox shown throughout.

| Endpoint | Purpose |
| :---- | :---- |
| `POST https://api.sandbox.airwallex.com/agentic-commerce/onboard` | Create or update your configuration. Returns a redacted view, a signed catalogue upload URL, and your MCP endpoint. |
| `GET https://api.sandbox.airwallex.com/agentic-commerce/config` | Read your configuration and credential-presence flags. No upload URL: reading is side-effect free. |
| `POST https://api.sandbox.airwallex.com/agentic-commerce/products` | Start ingesting your uploaded catalogue file. Returns `202` with an ingestion ID. |
| `GET https://api.sandbox.airwallex.com/agentic-commerce/products/{id}` | Ingestion progress, result counts, and error-report link, by ingestion ID. |
| `PUT https://api.sandbox.airwallex.com/agentic-commerce/products` | Synchronous batch update; at most 300 products. |

`POST /products` starts an ingestion job; `PUT /products` upserts the products in the request body. Both act on your catalogue, and the `PUT` is a batch upsert, not a replacement of everything not in the body.

Authentication: Use your standard Airwallex API credentials. Your merchant identity is derived from them — never send a merchant ID in request bodies. PSP API keys and checkout secrets are not credentials for this API; onboarding works before any Agentic Commerce configuration exists.

# **2\. Onboard: save your configuration**

`POST /agentic-commerce/onboard` saves your PSP credentials and checkout endpoint:

```
{
  "psp_config": {
    "psp_name": "AIRWALLEX",
    "authentication_type": "API_KEY",
    "api_key_data": {
      "client_id": "<psp-client-id>",
      "api_key": "<psp-api-key>"
    },
    "managed_payment": false
  },
  "apis": {
    "create_checkout": "https://merchant.example/checkout",
    "secret_key": "<checkout-hmac-secret>"
  }
}
```

* Both secrets are required the first time. On later calls, omit a secret to keep the stored value, or send a new value to rotate it. The non-secret configuration is required on every call.  
* `apis.secret_key` signs calls to your checkout API with HMAC-SHA256. It is separate from the PSP API key.  
* Responses never contain secrets — only `client_id`, the checkout URL, and `api_key_configured` / `secret_key_configured` flags.  
* Checkout URLs must be HTTPS. A successful call confirms the configuration is valid, not that checkout is end-to-end ready.

## **Response: upload URL and MCP endpoint**

```
// POST /agentic-commerce/onboard → 200
{
  "merchant_id": "ac-dummy-merchant",
  "psp_config": {
    "psp_name": "AIRWALLEX",
    "client_id": "<psp-client-id>",
    "api_key_configured": true,
    "managed_payment": false
  },
  "apis": {
    "create_checkout": "https://merchant.example/checkout",
    "secret_key_configured": true
  },
  "mcp_endpoints": {
    "acp": "https://api.sandbox.airwallex.com/pa/ai/ac-dummy-merchant/acp/mcp",
    "ucp": "https://api.sandbox.airwallex.com/pa/ai/ac-dummy-merchant/ucp/mcp"
  },
  "product_upload": {
    "url": "<signed upload URL>",
    "method": "PUT",
    "headers": {
      "Content-Type": "application/octet-stream"
    },
    "expires_at": "2026-10-13T12:00:00Z"
  }
}
```

The MCP endpoints are where AI agents connect to browse your catalogue and check out (see section 6). The upload URL is for one catalogue slot per merchant; propose a 7-day expiry, and call onboard again with secrets omitted to refresh it.

# **3\. Upload, then ingest explicitly**

1. **Onboard:** `POST /agentic-commerce/onboard` returns a signed upload URL for your catalogue slot.  
2. **Upload:** `PUT` the file to that URL using exactly the returned headers. No Airwallex credentials go to the upload URL.  
3. **Ingest:** Call `POST /agentic-commerce/products` once the upload succeeds. This tells the platform the file is complete.  
4. **Poll:** `GET /agentic-commerce/products/{id}` with the ingestion ID until the job finishes.

Nothing is processed until you call ingest, so a half-finished or bad file can be replaced before it affects your catalogue. Re-uploading to the same URL replaces the previous file; ingestion always processes the file as it was when you called ingest.

Supported formats: [unified\_jsonl](https://ai-documentation-4050f4.pages.awx.im/agentic-commerce-documents/product-feed-unified-jsonl.html) and [gmc\_tsv](https://ai-documentation-4050f4.pages.awx.im/agentic-commerce-documents/product-feed-gmc-tsv.html). Upload encoding stays uncompressed in V1.

## **Ingest request and response**

```
// POST /agentic-commerce/products
{
  "file_format": "unified_jsonl",
  "ingestion_mode": "upsert",
  "size_bytes": 1048576
}

// 202 response
{
  "ingestion_id": "ing_example",
  "status": "processing"
}
```

The platform checks the uploaded file before processing:

* Nothing uploaded yet → `409 UPLOAD_NOT_READY`  
* Over the size limit → `422 INVALID_UPLOAD`  
* Ingesting a file that was already processed → `409 FILE_ALREADY_PROCESSED` (upload a new version and call ingest again)

*Proposed limit: 100 MiB per file.*

## **Ingestion status**

```
// GET /agentic-commerce/products/ing_example
{
  "ingestion_id": "ing_example",
  "status": "completed",
  "progress": 100,
  "records_added": 1200,
  "records_updated": 80,
  "records_failed": 0,
  "error_report_url": null,
  "error_report_expires_at": null
}
```

**Statuses:** `processing`, `completed`, `failed`. A failed upsert can still have written many products successfully; the counts and the error report (a short-lived download link when present) explain partial results.

V1 supports `ingestion_mode: "upsert"` only: products missing from the file stay in your catalogue. Full catalogue replacement may come later.

# **4\. Direct product upserts**

`PUT /agentic-commerce/products` updates up to 300 products in one synchronous call; use file ingestion for larger updates. Send type (UNIFIED\_PRODUCT or GMC) with exactly one matching array, unified\_products or gmc\_products.

Products are matched by `merchant_product_id`. Each submitted product replaces that product’s stored representation, including its variant list — this is not a field-level patch. Products absent from the batch remain unchanged.

```
// PUT /agentic-commerce/products → 200; individual row failures do not roll back successful rows
{
  "records_added": 8,
  "records_updated": 2,
  "records_failed": 1,
  "error_report_url": "<short-lived download link>",
  "error_report_expires_at": "2026-10-06T12:15:00Z"
}
```

# **5\. Shared behaviour**

* **Retries:** Send an `Idempotency-Key` header on `POST` calls. Replaying the same key and payload returns the original result; reusing a key with a different payload returns `409`. Keys are retained for 24 hours. `PUT /products` needs no key because it is idempotent by definition.  
* **Errors:** HTTP status plus `{"code":"…","message":"…","request_id":"…"}`.  
  * `400`: Malformed request  
  * `401` / `403`: Authentication failure  
  * `404`: Missing resource  
  * `409`: Conflict  
  * `422`: Invalid data  
  * `429`: Rate limit

# **6\. Connecting an MCP client**

Once onboarded, point an MCP client at your `acp` endpoint from the onboard response, for example in Claude Code.

The simplest way is the built-in command:

```
claude mcp add --transport http agentic-commerce https://api.sandbox.airwallex.com/pa/ai/<merchantId>/acp/mcp
```

Or edit the config file directly. Claude Code (CLI and desktop app) reads .mcp.json in the project root and \~/.claude.json; clients that only support local servers use the mcp-remote bridge:

```
// .mcp.json (project root) or ~/.claude.json
{
  "mcpServers": {
    "agentic-commerce": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-remote",
        "https://api.sandbox.airwallex.com/pa/ai/<merchantId>/acp/mcp"
      ]
    }
  }
}
```

If your endpoint requires a bearer token, pass it as a header — directly, or via an environment variable so the token stays out of version control:

```
{
  "mcpServers": {
    "agentic-commerce": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-remote",
        "https://api.sandbox.airwallex.com/pa/ai/<merchantId>/acp/mcp",
        "--header",
        "Authorization: Bearer ${AGENTIC_COMMERCE_TOKEN}"
      ]
    }
  }
}
```

Restart the client after editing the config; the agent can then call `explore_products` against your catalogue.

## **Related Documentation**

[Product feed format](https://docs.google.com/document/d/1TSbO6glxmy0SnrZDZCL3gfFvweG-prtVYRNOn8Rp9CE/edit?tab=t.0)  

