curl --request POST \
--url https://api.unif.dev/v1/enrich \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"currency": "USD",
"period": {
"preset": "last_30d"
},
"fields": [
"name",
"categories",
"metrics.revenue",
"metrics.units_sold",
"metrics.revenue_growth_rate"
],
"inputs": [
{
"type": "shop",
"url": "https://www.tiktok.com/shop/glowlab"
},
{
"type": "shop",
"url": "https://www.tiktok.com/shop/northpeak"
}
]
}
'import requests
url = "https://api.unif.dev/v1/enrich"
payload = {
"currency": "USD",
"period": { "preset": "last_30d" },
"fields": ["name", "categories", "metrics.revenue", "metrics.units_sold", "metrics.revenue_growth_rate"],
"inputs": [
{
"type": "shop",
"url": "https://www.tiktok.com/shop/glowlab"
},
{
"type": "shop",
"url": "https://www.tiktok.com/shop/northpeak"
}
]
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
currency: 'USD',
period: {preset: 'last_30d'},
fields: [
'name',
'categories',
'metrics.revenue',
'metrics.units_sold',
'metrics.revenue_growth_rate'
],
inputs: [
{type: 'shop', url: 'https://www.tiktok.com/shop/glowlab'},
{type: 'shop', url: 'https://www.tiktok.com/shop/northpeak'}
]
})
};
fetch('https://api.unif.dev/v1/enrich', 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.unif.dev/v1/enrich",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'currency' => 'USD',
'period' => [
'preset' => 'last_30d'
],
'fields' => [
'name',
'categories',
'metrics.revenue',
'metrics.units_sold',
'metrics.revenue_growth_rate'
],
'inputs' => [
[
'type' => 'shop',
'url' => 'https://www.tiktok.com/shop/glowlab'
],
[
'type' => 'shop',
'url' => 'https://www.tiktok.com/shop/northpeak'
]
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.unif.dev/v1/enrich"
payload := strings.NewReader("{\n \"currency\": \"USD\",\n \"period\": {\n \"preset\": \"last_30d\"\n },\n \"fields\": [\n \"name\",\n \"categories\",\n \"metrics.revenue\",\n \"metrics.units_sold\",\n \"metrics.revenue_growth_rate\"\n ],\n \"inputs\": [\n {\n \"type\": \"shop\",\n \"url\": \"https://www.tiktok.com/shop/glowlab\"\n },\n {\n \"type\": \"shop\",\n \"url\": \"https://www.tiktok.com/shop/northpeak\"\n }\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.unif.dev/v1/enrich")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"currency\": \"USD\",\n \"period\": {\n \"preset\": \"last_30d\"\n },\n \"fields\": [\n \"name\",\n \"categories\",\n \"metrics.revenue\",\n \"metrics.units_sold\",\n \"metrics.revenue_growth_rate\"\n ],\n \"inputs\": [\n {\n \"type\": \"shop\",\n \"url\": \"https://www.tiktok.com/shop/glowlab\"\n },\n {\n \"type\": \"shop\",\n \"url\": \"https://www.tiktok.com/shop/northpeak\"\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.unif.dev/v1/enrich")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"currency\": \"USD\",\n \"period\": {\n \"preset\": \"last_30d\"\n },\n \"fields\": [\n \"name\",\n \"categories\",\n \"metrics.revenue\",\n \"metrics.units_sold\",\n \"metrics.revenue_growth_rate\"\n ],\n \"inputs\": [\n {\n \"type\": \"shop\",\n \"url\": \"https://www.tiktok.com/shop/glowlab\"\n },\n {\n \"type\": \"shop\",\n \"url\": \"https://www.tiktok.com/shop/northpeak\"\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"object": "enrich_response",
"data": [
{
"ref": "<string>",
"status": "enriched",
"type": "shop",
"data": {
"id": "shp_01k3m9x7v2q8r4t6y0b1n5d7fa",
"object": "shop",
"channel": "tiktok_shop",
"market": "US",
"name": "GlowLab",
"handle": "glowlab",
"url": "<string>",
"logo_url": "<string>",
"seller_type": "brand",
"categories": [
{
"id": "cat_beauty_personal_care",
"name": "Beauty & Personal Care",
"path": [
"<string>"
]
}
],
"rating": 2.5,
"reviews_count": 123,
"products_count": 123,
"opened_at": "2023-12-25",
"metrics": {
"revenue": 123,
"units_sold": 123,
"avg_unit_price": 123,
"revenue_growth_rate": 123,
"revenue_by_source": {
"video": 123,
"live": 123,
"mall": 123,
"search": 123
},
"products_sold_count": 123,
"creators_count": 123,
"videos_count": 123,
"livestreams_count": 123
},
"period": {
"start": "2023-12-25",
"end": "2023-12-25",
"granularity": "day",
"adjusted": true
},
"currency": "<string>",
"meta": {
"refreshed_at": "2023-11-07T05:31:56Z",
"completeness": 0.5,
"missing_fields": [
"<string>"
]
}
},
"meta": {
"refreshed_at": "2023-11-07T05:31:56Z",
"completeness": 0.5,
"missing_fields": [
"<string>"
]
}
}
],
"period": {
"start": "2023-12-25",
"end": "2023-12-25",
"granularity": "day",
"adjusted": true
},
"currency": "<string>",
"credits_charged": 123
}{
"error": {
"type": "invalid_request_error",
"code": "parameter_invalid",
"message": "filters.revenue.gte must be a non-negative number.",
"param": "filters.revenue.gte",
"doc_url": "https://unif.dev/docs/platform/errors#parameter_invalid",
"request_id": "req_01k3m9x7v2q8r4t6y0b1n5d7fa"
}
}{
"error": {
"type": "billing_error",
"code": "insufficient_credits",
"message": "This request costs 25 credits and 4 remain in the current period.",
"doc_url": "https://unif.dev/docs/platform/credits",
"request_id": "req_01k3m9x7v2q8r4t6y0b1n5d7fa"
}
}{
"error": {
"type": "invalid_request_error",
"code": "parameter_invalid",
"message": "<string>",
"param": "<string>",
"doc_url": "<string>",
"request_id": "<string>"
}
}Enrich known entities
Given identifiers, returns the full normalized record for each one — resolution and
retrieval in a single call. Request only the fields you need to spend fewer credits.
Handles up to 100 inputs synchronously. For more, create an enrichment job.
curl --request POST \
--url https://api.unif.dev/v1/enrich \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"currency": "USD",
"period": {
"preset": "last_30d"
},
"fields": [
"name",
"categories",
"metrics.revenue",
"metrics.units_sold",
"metrics.revenue_growth_rate"
],
"inputs": [
{
"type": "shop",
"url": "https://www.tiktok.com/shop/glowlab"
},
{
"type": "shop",
"url": "https://www.tiktok.com/shop/northpeak"
}
]
}
'import requests
url = "https://api.unif.dev/v1/enrich"
payload = {
"currency": "USD",
"period": { "preset": "last_30d" },
"fields": ["name", "categories", "metrics.revenue", "metrics.units_sold", "metrics.revenue_growth_rate"],
"inputs": [
{
"type": "shop",
"url": "https://www.tiktok.com/shop/glowlab"
},
{
"type": "shop",
"url": "https://www.tiktok.com/shop/northpeak"
}
]
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
currency: 'USD',
period: {preset: 'last_30d'},
fields: [
'name',
'categories',
'metrics.revenue',
'metrics.units_sold',
'metrics.revenue_growth_rate'
],
inputs: [
{type: 'shop', url: 'https://www.tiktok.com/shop/glowlab'},
{type: 'shop', url: 'https://www.tiktok.com/shop/northpeak'}
]
})
};
fetch('https://api.unif.dev/v1/enrich', 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.unif.dev/v1/enrich",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'currency' => 'USD',
'period' => [
'preset' => 'last_30d'
],
'fields' => [
'name',
'categories',
'metrics.revenue',
'metrics.units_sold',
'metrics.revenue_growth_rate'
],
'inputs' => [
[
'type' => 'shop',
'url' => 'https://www.tiktok.com/shop/glowlab'
],
[
'type' => 'shop',
'url' => 'https://www.tiktok.com/shop/northpeak'
]
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.unif.dev/v1/enrich"
payload := strings.NewReader("{\n \"currency\": \"USD\",\n \"period\": {\n \"preset\": \"last_30d\"\n },\n \"fields\": [\n \"name\",\n \"categories\",\n \"metrics.revenue\",\n \"metrics.units_sold\",\n \"metrics.revenue_growth_rate\"\n ],\n \"inputs\": [\n {\n \"type\": \"shop\",\n \"url\": \"https://www.tiktok.com/shop/glowlab\"\n },\n {\n \"type\": \"shop\",\n \"url\": \"https://www.tiktok.com/shop/northpeak\"\n }\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.unif.dev/v1/enrich")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"currency\": \"USD\",\n \"period\": {\n \"preset\": \"last_30d\"\n },\n \"fields\": [\n \"name\",\n \"categories\",\n \"metrics.revenue\",\n \"metrics.units_sold\",\n \"metrics.revenue_growth_rate\"\n ],\n \"inputs\": [\n {\n \"type\": \"shop\",\n \"url\": \"https://www.tiktok.com/shop/glowlab\"\n },\n {\n \"type\": \"shop\",\n \"url\": \"https://www.tiktok.com/shop/northpeak\"\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.unif.dev/v1/enrich")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"currency\": \"USD\",\n \"period\": {\n \"preset\": \"last_30d\"\n },\n \"fields\": [\n \"name\",\n \"categories\",\n \"metrics.revenue\",\n \"metrics.units_sold\",\n \"metrics.revenue_growth_rate\"\n ],\n \"inputs\": [\n {\n \"type\": \"shop\",\n \"url\": \"https://www.tiktok.com/shop/glowlab\"\n },\n {\n \"type\": \"shop\",\n \"url\": \"https://www.tiktok.com/shop/northpeak\"\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"object": "enrich_response",
"data": [
{
"ref": "<string>",
"status": "enriched",
"type": "shop",
"data": {
"id": "shp_01k3m9x7v2q8r4t6y0b1n5d7fa",
"object": "shop",
"channel": "tiktok_shop",
"market": "US",
"name": "GlowLab",
"handle": "glowlab",
"url": "<string>",
"logo_url": "<string>",
"seller_type": "brand",
"categories": [
{
"id": "cat_beauty_personal_care",
"name": "Beauty & Personal Care",
"path": [
"<string>"
]
}
],
"rating": 2.5,
"reviews_count": 123,
"products_count": 123,
"opened_at": "2023-12-25",
"metrics": {
"revenue": 123,
"units_sold": 123,
"avg_unit_price": 123,
"revenue_growth_rate": 123,
"revenue_by_source": {
"video": 123,
"live": 123,
"mall": 123,
"search": 123
},
"products_sold_count": 123,
"creators_count": 123,
"videos_count": 123,
"livestreams_count": 123
},
"period": {
"start": "2023-12-25",
"end": "2023-12-25",
"granularity": "day",
"adjusted": true
},
"currency": "<string>",
"meta": {
"refreshed_at": "2023-11-07T05:31:56Z",
"completeness": 0.5,
"missing_fields": [
"<string>"
]
}
},
"meta": {
"refreshed_at": "2023-11-07T05:31:56Z",
"completeness": 0.5,
"missing_fields": [
"<string>"
]
}
}
],
"period": {
"start": "2023-12-25",
"end": "2023-12-25",
"granularity": "day",
"adjusted": true
},
"currency": "<string>",
"credits_charged": 123
}{
"error": {
"type": "invalid_request_error",
"code": "parameter_invalid",
"message": "filters.revenue.gte must be a non-negative number.",
"param": "filters.revenue.gte",
"doc_url": "https://unif.dev/docs/platform/errors#parameter_invalid",
"request_id": "req_01k3m9x7v2q8r4t6y0b1n5d7fa"
}
}{
"error": {
"type": "billing_error",
"code": "insufficient_credits",
"message": "This request costs 25 credits and 4 remain in the current period.",
"doc_url": "https://unif.dev/docs/platform/credits",
"request_id": "req_01k3m9x7v2q8r4t6y0b1n5d7fa"
}
}{
"error": {
"type": "invalid_request_error",
"code": "parameter_invalid",
"message": "<string>",
"param": "<string>",
"doc_url": "<string>",
"request_id": "<string>"
}
}Authorizations
Send your workspace API key as a bearer token:
Authorization: Bearer unif_sk_live_...
Keys are scoped to a single workspace. See Authentication.
Headers
A unique key, at most 255 characters. Retrying with the same key returns the original response instead of doing the work twice. Keys are retained for 24 hours.
Body
1 - 100 elementsHide child attributes
Hide child attributes
shop, product, creator, video, livestream, category A channel URL for the entity.
The channel handle
The entity's native ID on the channel.
A sales channel — the commerce surface a request is about. Behind each channel is a cascade of data sources, tried in cost order until one verifies; the roster is published, but which source answered a given row is not carried in the response, so the cascade can be re-tuned without breaking your code.
tiktok_shop "tiktok_shop"
An ISO 3166-1 alpha-2 country code identifying a channel storefront.
US, GB, IE, ES, FR, DE, IT, ID, TH, VN, MY, PH, SG, JP, BR, MX "US"
Your own identifier
Dot-paths to return, for example metrics.revenue. Omit to return the full record.
Narrowing the field set lowers the credit cost.
The window a metric is measured over. Supply either preset, or both start and
end. Periods are whole days in the market's local time zone.
{ "preset": "last_30d" }
{
"start": "2026-08-01",
"end": "2026-08-31"
}
Response
Enrichment results, in the order the inputs were sent.
"enrich_response"Hide child attributes
Hide child attributes
enriched, not_found, ambiguous, unsupported, partial shop, product, creator, video, livestream, category The normalized entity, shaped by fields. Null unless status is enriched or partial.
- Option 1
- Option 2
- Option 3
- Option 4
- Option 5
Hide child attributes
Hide child attributes
"shp_01k3m9x7v2q8r4t6y0b1n5d7fa"
"shop"A sales channel — the commerce surface a request is about. Behind each channel is a cascade of data sources, tried in cost order until one verifies; the roster is published, but which source answered a given row is not carried in the response, so the cascade can be re-tuned without breaking your code.
tiktok_shop "tiktok_shop"
An ISO 3166-1 alpha-2 country code identifying a channel storefront.
US, GB, IE, ES, FR, DE, IT, ID, TH, VN, MY, PH, SG, JP, BR, MX "US"
"GlowLab"
"glowlab"
Normalized seller classification.
brand, reseller, cross_border, local, unknown 0 <= x <= 5Shop performance over the requested period, in the requested currency.
Hide child attributes
Hide child attributes
Gross merchandise value attributed to the shop.
Change in revenue against the immediately preceding period of equal length, as a ratio. 0.25 is +25%.
Distinct products with at least one sale.
Distinct creators who drove attributed sales.
The concrete window a request was measured over, after any preset was expanded and any channel-specific snapping was applied. Always read this rather than assuming you got back exactly the dates you asked for.
Hide child attributes
Hide child attributes
The smallest bucket the channel reports for this market.
day, week, month True when the requested dates were snapped to the nearest boundary the channel supports. See Periods and currency.
How current and how complete this record is.
Hide child attributes
Hide child attributes
How current and how complete this record is.
The concrete window a request was measured over, after any preset was expanded and any channel-specific snapping was applied. Always read this rather than assuming you got back exactly the dates you asked for.
Hide child attributes
Hide child attributes
The smallest bucket the channel reports for this market.
day, week, month True when the requested dates were snapped to the nearest boundary the channel supports. See Periods and currency.
Was this page helpful?