curl --request GET \
--url https://api.sumvin.com/v0/ucp/merchants \
--header 'x-sumvin-ucp-token: <api-key>'import requests
url = "https://api.sumvin.com/v0/ucp/merchants"
headers = {"x-sumvin-ucp-token": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'x-sumvin-ucp-token': '<api-key>'}};
fetch('https://api.sumvin.com/v0/ucp/merchants', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.sumvin.com/v0/ucp/merchants",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"x-sumvin-ucp-token: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.sumvin.com/v0/ucp/merchants"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("x-sumvin-ucp-token", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.sumvin.com/v0/ucp/merchants")
.header("x-sumvin-ucp-token", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.sumvin.com/v0/ucp/merchants")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["x-sumvin-ucp-token"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"_links": {
"self": {
"href": "/v0/ucp/merchants?q=sneakers&country=US"
}
},
"limit": 25,
"offset": 0,
"queried_at": 1706745600000,
"query": {
"country": [
"US"
],
"q": "sneakers"
},
"results": [
{
"_links": {
"describedby": {
"href": "https://shop.example.com/.well-known/ucp"
},
"self": {
"href": "/v0/ucp/merchants/shop.example.com"
}
},
"_score": 8.42,
"domain": "shop.example.com",
"merchant": {
"brands": [
"ExampleBrand"
],
"categories": [
"apparel",
"footwear"
],
"locale": {
"country": "US",
"language": "en"
},
"name": "Example Shop",
"products": [
"sneakers",
"jackets"
],
"provenance": {
"confidence": 0.92
}
},
"merchant_id": "k3jf7q2xmn4pz",
"meta": {
"first_hit_at": 1704067200000,
"last_hit_at": 1706745600000
},
"ucp": {
"a2a": {
"enabled": true
},
"capabilities": [
"dev.ucp.shopping.checkout"
],
"oauth": {
"enabled": false
},
"payment_handlers": [
"com.google.pay"
],
"services": [
{
"endpoint": "https://example-shop.myshopify.com/api/ucp/mcp",
"namespace": "dev.ucp.shopping",
"transport": "mcp"
}
],
"transports": [
"mcp",
"embedded"
],
"version": "2026-04-08"
}
}
],
"total": 1
}{
"detail": "No wallet found with ID 12345 for this user.",
"error_code": "WAL-404-001",
"instance": "/v0/wallets/12345",
"status": 404,
"title": "Wallet Not Found",
"trace_id": "abc123-def456-ghi789",
"type": "https://api.sumvin.com/errors/wal-404-001"
}{
"detail": "No wallet found with ID 12345 for this user.",
"error_code": "WAL-404-001",
"instance": "/v0/wallets/12345",
"status": 404,
"title": "Wallet Not Found",
"trace_id": "abc123-def456-ghi789",
"type": "https://api.sumvin.com/errors/wal-404-001"
}{
"detail": "No wallet found with ID 12345 for this user.",
"error_code": "WAL-404-001",
"instance": "/v0/wallets/12345",
"status": 404,
"title": "Wallet Not Found",
"trace_id": "abc123-def456-ghi789",
"type": "https://api.sumvin.com/errors/wal-404-001"
}{
"detail": "No wallet found with ID 12345 for this user.",
"error_code": "WAL-404-001",
"instance": "/v0/wallets/12345",
"status": 404,
"title": "Wallet Not Found",
"trace_id": "abc123-def456-ghi789",
"type": "https://api.sumvin.com/errors/wal-404-001"
}{
"detail": "No wallet found with ID 12345 for this user.",
"error_code": "WAL-404-001",
"instance": "/v0/wallets/12345",
"status": 404,
"title": "Wallet Not Found",
"trace_id": "abc123-def456-ghi789",
"type": "https://api.sumvin.com/errors/wal-404-001"
}Search UCP merchants
Search the catalogue of discovered UCP merchants with full-text and structured filters.
What is searched:
q runs a full-text search over merchant name, categories, products, and brands.
Filter semantics:
Repeatable filters (category, country, language, brand, capability, payment,
transport) combine as OR within a single dimension and AND across dimensions. For
example, country=US&country=CA&capability=checkout matches merchants in the US or
Canada that also support checkout.
Category values are open-ended descriptive labels rather than a fixed vocabulary, so
filtering by category is approximate.
Sorting: by relevance (default), popularity, or last_hit.
Pagination: offset-based via offset and limit (max 100 per page). Responses
report the real total match count. The live search endpoint caps how deep results
can be paged and rejects requests past that depth with a 400 (MRC-400-001).
Every result carries its own _links, including one to the merchant’s UCP discovery
document. queried_at records when the search ran.
curl --request GET \
--url https://api.sumvin.com/v0/ucp/merchants \
--header 'x-sumvin-ucp-token: <api-key>'import requests
url = "https://api.sumvin.com/v0/ucp/merchants"
headers = {"x-sumvin-ucp-token": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'x-sumvin-ucp-token': '<api-key>'}};
fetch('https://api.sumvin.com/v0/ucp/merchants', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.sumvin.com/v0/ucp/merchants",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"x-sumvin-ucp-token: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.sumvin.com/v0/ucp/merchants"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("x-sumvin-ucp-token", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.sumvin.com/v0/ucp/merchants")
.header("x-sumvin-ucp-token", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.sumvin.com/v0/ucp/merchants")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["x-sumvin-ucp-token"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"_links": {
"self": {
"href": "/v0/ucp/merchants?q=sneakers&country=US"
}
},
"limit": 25,
"offset": 0,
"queried_at": 1706745600000,
"query": {
"country": [
"US"
],
"q": "sneakers"
},
"results": [
{
"_links": {
"describedby": {
"href": "https://shop.example.com/.well-known/ucp"
},
"self": {
"href": "/v0/ucp/merchants/shop.example.com"
}
},
"_score": 8.42,
"domain": "shop.example.com",
"merchant": {
"brands": [
"ExampleBrand"
],
"categories": [
"apparel",
"footwear"
],
"locale": {
"country": "US",
"language": "en"
},
"name": "Example Shop",
"products": [
"sneakers",
"jackets"
],
"provenance": {
"confidence": 0.92
}
},
"merchant_id": "k3jf7q2xmn4pz",
"meta": {
"first_hit_at": 1704067200000,
"last_hit_at": 1706745600000
},
"ucp": {
"a2a": {
"enabled": true
},
"capabilities": [
"dev.ucp.shopping.checkout"
],
"oauth": {
"enabled": false
},
"payment_handlers": [
"com.google.pay"
],
"services": [
{
"endpoint": "https://example-shop.myshopify.com/api/ucp/mcp",
"namespace": "dev.ucp.shopping",
"transport": "mcp"
}
],
"transports": [
"mcp",
"embedded"
],
"version": "2026-04-08"
}
}
],
"total": 1
}{
"detail": "No wallet found with ID 12345 for this user.",
"error_code": "WAL-404-001",
"instance": "/v0/wallets/12345",
"status": 404,
"title": "Wallet Not Found",
"trace_id": "abc123-def456-ghi789",
"type": "https://api.sumvin.com/errors/wal-404-001"
}{
"detail": "No wallet found with ID 12345 for this user.",
"error_code": "WAL-404-001",
"instance": "/v0/wallets/12345",
"status": 404,
"title": "Wallet Not Found",
"trace_id": "abc123-def456-ghi789",
"type": "https://api.sumvin.com/errors/wal-404-001"
}{
"detail": "No wallet found with ID 12345 for this user.",
"error_code": "WAL-404-001",
"instance": "/v0/wallets/12345",
"status": 404,
"title": "Wallet Not Found",
"trace_id": "abc123-def456-ghi789",
"type": "https://api.sumvin.com/errors/wal-404-001"
}{
"detail": "No wallet found with ID 12345 for this user.",
"error_code": "WAL-404-001",
"instance": "/v0/wallets/12345",
"status": 404,
"title": "Wallet Not Found",
"trace_id": "abc123-def456-ghi789",
"type": "https://api.sumvin.com/errors/wal-404-001"
}{
"detail": "No wallet found with ID 12345 for this user.",
"error_code": "WAL-404-001",
"instance": "/v0/wallets/12345",
"status": 404,
"title": "Wallet Not Found",
"trace_id": "abc123-def456-ghi789",
"type": "https://api.sumvin.com/errors/wal-404-001"
}Authorizations
Org-scoped key for the UCP Merchant Search endpoints. Sent in the x-sumvin-ucp-token header.
Headers
Controls how timestamp fields are serialized in JSON response bodies.
Default (header omitted or any other value): epoch milliseconds as integers.
iso8601: UTC ISO 8601 strings of the form YYYY-MM-DDTHH:MM:SSZ.
Example: with X-Timestamp-Format: iso8601, the field value 1704067200000 becomes "2024-01-01T00:00:00Z".
Affected fields (recursively, in dicts and arrays): any field whose name ends in _at, plus the literal field names timestamp, period_start, and period_end. All other fields are passed through unchanged.
Only iso8601 is recognized. Any other value (or omitting the header) yields the default epoch-ms representation; the server does not reject unknown values, so this is documented as an example rather than an enum to keep generated clients permissive.
"iso8601"
Query Parameters
Full-text search over merchant name, categories, products, and brands.
512Filter by category. Repeatable; OR within, AND across dimensions.
50128["apparel", "electronics"]
Filter by country. Repeatable; OR within, AND across dimensions.
50^[A-Za-z]{2}$Filter by language. Repeatable; OR within, AND across dimensions.
50^[A-Za-z]{2,3}$Filter by brand. Repeatable; OR within, AND across dimensions.
50128["Nike", "Apple"]
Filter by UCP capability. Repeatable; OR within, AND across dimensions.
50128["checkout", "catalog", "com.acme.custom"]
Filter by payment handler. Repeatable; OR within, AND across dimensions.
50128["card", "paypal"]
Filter by the transport a merchant's UCP service is reachable over. Repeatable; OR within, AND across dimensions.
50rest, mcp, a2a, embedded ["mcp", "rest"]
Filter by whether agent-to-agent is enabled.
Filter by whether OAuth is enabled.
Only include merchants last seen on or after this date. Accepts epoch ms or YYYY-MM-DD.
Only include merchants last seen on or before this date. Accepts epoch ms or YYYY-MM-DD.
Filter to merchants that have (true) or lack (false) enrichment. A merchant counts as enriched when it carries any enrichment field: name, categories, products, brands, country, language or confidence. Because q and the category, brand, country and language filters all match on those same fields, combining any of them with enriched=false selects nothing. A merchant excluded by enriched=true may still carry a merchant block built from enrichment provenance the index does not make searchable.
Sort order for results.
relevance, popularity, last_hit Facet fields to compute value counts for. Repeatable.
category, brand, country, language, capability, payment, transport, a2a, oauth Include matched snippets on each result.
Pagination offset
x >= 0Pagination limit
1 <= x <= 100Response
Merchants retrieved successfully
Paginated list of UCP merchants matching a search.
HAL-style hypermedia links for navigation and available actions.
Show child attributes
Show child attributes
Merchants matching the search.
Show child attributes
Show child attributes
Number of merchants matching the search, capped at 10,000. A value of 10,000 means at least that many match; results cannot be paged beyond that depth.
Number of items skipped from the beginning of the result set.
Maximum number of items returned per page (1-100).
The effective query parameters applied.
Unix timestamp in epoch milliseconds when the search was executed. Results reflect the index as of this moment.
Value counts per requested facet field. Present only when facets are requested.
Show child attributes
Show child attributes