Skimlinks Data Pipe
Version 0
The Skimlinks Data Pipe is the event-level data surface behind the Skimlinks affiliate platform: impressions, clicks, commissions and products purchased, cleaned and exported daily to a customer-owned (or Skimlinks-owned) Google Cloud Storage or Amazon S3 bucket. Skimlinks states that event-level data on individual commissions, clicks, page impressions and product purchases "can be accessed only via Data Pipe" — the Reporting API returns aggregates, so this is not a duplicate projection of the REST surface. TRANSPORT NOTE — read this before treating the document as a broker contract. Skimlinks does NOT publish an AsyncAPI document and does NOT ship webhooks. Delivery is a daily batch write of Avro or CSV files into a partitioned object-storage prefix; there is no broker, no subscription protocol, and no push callback. This AsyncAPI models that documented feed so the event schemas are machine-readable — every channel, message and property below is transcribed from the provider's own published column reference. Nothing here is inferred.
Channels
Messages
Servers
AsyncAPI Specification
asyncapi: 3.0.0
info:
title: Skimlinks Data Pipe
version: '0'
description: >-
The Skimlinks Data Pipe is the event-level data surface behind the
Skimlinks affiliate platform: impressions, clicks, commissions and products
purchased, cleaned and exported daily to a customer-owned (or
Skimlinks-owned) Google Cloud Storage or Amazon S3 bucket. Skimlinks states
that event-level data on individual commissions, clicks, page impressions
and product purchases "can be accessed only via Data Pipe" — the Reporting
API returns aggregates, so this is not a duplicate projection of the REST
surface.
TRANSPORT NOTE — read this before treating the document as a broker
contract. Skimlinks does NOT publish an AsyncAPI document and does NOT ship
webhooks. Delivery is a daily batch write of Avro or CSV files into a
partitioned object-storage prefix; there is no broker, no subscription
protocol, and no push callback. This AsyncAPI models that documented feed so
the event schemas are machine-readable — every channel, message and property
below is transcribed from the provider's own published column reference.
Nothing here is inferred.
contact:
name: Skimlinks Developer Documentation
url: https://developers.skimlinks.com/data-pipe.html
x-generated: '2026-08-13'
x-method: generated
x-source: >-
https://developers.skimlinks.com/data-pipe.html (Apiary blueprint
"datapipe1", fetched verbatim from
https://jsapi.apiary.io/apis/datapipe1.apib on 2026-08-13, HTTP 200)
x-provider-publishes-asyncapi: false
x-delivery-model: daily batch export to object storage (Avro or CSV)
defaultContentType: application/octet-stream
servers:
gcs:
host: storage.googleapis.com
protocol: gcs
title: Google Cloud Storage (preferred)
description: >-
Skimlinks' preferred destination. The bucket may be owned by the customer
or created and owned by Skimlinks; when Skimlinks owns it, download costs
are charged to the customer and files are retained for 30 days after the
initial upload.
s3:
host: s3.amazonaws.com
protocol: s3
title: Amazon S3
description: Alternative customer-owned destination bucket.
channels:
clicks:
address: '{bucket}/clicks/date={date}/version=0/'
title: Clicks
description: >-
Immutable click events, partitioned by the UTC event date. Each partition
contains multiple files; all files in a partition must be read. Reload a
partition with replace semantics to avoid duplicates.
servers:
- $ref: '#/servers/gcs'
- $ref: '#/servers/s3'
parameters:
bucket:
description: The destination bucket name agreed with Skimlinks.
date:
description: UTC event date partition key, YYYY-MM-DD.
messages:
click:
$ref: '#/components/messages/Click'
pages:
address: '{bucket}/pages/date={date}/version=0/'
title: Page impressions
description: >-
Immutable page-impression events, partitioned by the UTC event date. Same
partition-replace loading semantics as clicks.
servers:
- $ref: '#/servers/gcs'
- $ref: '#/servers/s3'
parameters:
bucket:
description: The destination bucket name agreed with Skimlinks.
date:
description: UTC event date partition key, YYYY-MM-DD.
messages:
pageImpression:
$ref: '#/components/messages/PageImpression'
commissions:
address: '{bucket}/commissions/snapshot_date={snapshot_date}/version=0/'
title: Commissions
description: >-
MUTABLE. A commission can be modified or cancelled after it occurs, so
Skimlinks exports a rolling 120-day snapshot of the current state of every
commission each day, including cancelled ones. Consumers are told to
delete-and-reinsert by transaction_datetime range rather than append.
servers:
- $ref: '#/servers/gcs'
- $ref: '#/servers/s3'
parameters:
bucket:
description: The destination bucket name agreed with Skimlinks.
snapshot_date:
description: Snapshot partition key, YYYY-MM-DD. Each snapshot restates a 120-day window.
messages:
commission:
$ref: '#/components/messages/Commission'
products:
address: '{bucket}/products/snapshot_date={snapshot_date}/version=0/'
title: Products purchased
description: >-
MUTABLE. Product-purchase rows can change due to returns, so a rolling
120-day snapshot is exported daily. Product identity fields (product_sku,
product_name) are populated only for merchants that share them; rows for
merchants that do not are still present with those fields empty.
servers:
- $ref: '#/servers/gcs'
- $ref: '#/servers/s3'
parameters:
bucket:
description: The destination bucket name agreed with Skimlinks.
snapshot_date:
description: Snapshot partition key, YYYY-MM-DD.
messages:
productPurchased:
$ref: '#/components/messages/ProductPurchased'
operations:
receiveClicks:
action: receive
channel:
$ref: '#/channels/clicks'
title: Read the daily clicks partition
description: >-
Read every file under the date partition (aws s3 ls / gsutil ls the
version=0 prefix). click_id can be duplicated but is unique when compared
with datehour.
messages:
- $ref: '#/channels/clicks/messages/click'
receivePageImpressions:
action: receive
channel:
$ref: '#/channels/pages'
title: Read the daily page-impressions partition
description: >-
impression_id can be duplicated but is unique when compared with datehour.
messages:
- $ref: '#/channels/pages/messages/pageImpression'
receiveCommissions:
action: receive
channel:
$ref: '#/channels/commissions'
title: Read the daily commissions snapshot
description: >-
Restates a 120-day window. Load by deleting the overlapping
transaction_datetime range in the target table and reinserting the
snapshot, so the result matches the Publisher Hub.
messages:
- $ref: '#/channels/commissions/messages/commission'
receiveProductsPurchased:
action: receive
channel:
$ref: '#/channels/products'
title: Read the daily products-purchased snapshot
description: Same delete-and-reinsert loading pattern as commissions.
messages:
- $ref: '#/channels/products/messages/productPurchased'
components:
messages:
Click:
name: Click
title: Click event
summary: One affiliate click recorded by Skimlinks.
payload:
$ref: '#/components/schemas/Click'
PageImpression:
name: PageImpression
title: Page impression event
summary: One page impression recorded by the Skimlinks JavaScript.
payload:
$ref: '#/components/schemas/PageImpression'
Commission:
name: Commission
title: Commission record (mutable snapshot row)
payload:
$ref: '#/components/schemas/Commission'
ProductPurchased:
name: ProductPurchased
title: Product purchased record (mutable snapshot row)
payload:
$ref: '#/components/schemas/ProductPurchased'
schemas:
Click:
type: object
description: Clicks columns as published in the Data Pipe column reference.
properties:
page_url: { type: string, description: The page_url that received the click. }
normalized_page_url: { type: string, description: A cleaned version of the page_url. This is easier to use for aggregations. }
target_url: { type: string, description: The url that was clicked on. }
normalized_target_url: { type: string, description: A cleaned version of the target_url. This is easier to use for aggregations. }
click_id: { type: string, description: 'The click ID. NOTE: This can be duplicated, but is always unique when compared with the click hour.' }
impression_id: { type: string, description: The impression ID. }
ts: { type: string, format: date-time, description: The timestamp (in UTC) of the click. }
publisher_domain_id: { type: integer, description: The ID of your publisher domain. }
merchant_id: { type: integer, description: The merchant ID. }
user_ip_country: { type: string, description: The 2 digit ISO-3166 country code associated with the user's IP address. }
user_ip_region: { type: string, nullable: true, description: The region associated with the user's ip address. This is now set to null. }
user_custom: { type: string, description: 'Also known as xcust. An optional user specified parameter used to pass your own internal tracking through Skimlinks'' monetisation engine.' }
user_timezone: { type: integer, description: The timezone difference from UTC associated with the user's ip address. }
browser_family: { type: string, description: The browser family. An example would be Chrome or Safari. }
browser_version: { type: string, description: The browser's version. }
device_type: { type: string, nullable: true, description: 'Can be mobile, bot, pc, tablet or null.' }
device_family: { type: string, description: 'The more granular version of the device type. Examples: iPhone, Samsung SM-T510.' }
os_family: { type: string, description: The operating system family. An example would be Windows or iOS. }
os_version: { type: string, description: The operating system version. }
skim_product_id: { type: integer, description: The Skimlinks product ID. See SkimlinksProductId. }
is_js: { type: boolean, description: Whether or not the click was affiliated using the SkimJS. }
is_affiliated: { type: boolean, description: Whether or not the click is affiliated. }
link_type: { type: integer, description: 1 means the click is affiliated. 0 means the click is not affiliated. }
datehour: { type: string, format: date-time, description: The date and hour (in UTC) of the click. This, used with click_id will be unique. }
is_reported: { type: boolean, description: Whether or not the click is reported. }
PageImpression:
type: object
description: Pages columns as published in the Data Pipe column reference.
properties:
publisher_domain_id: { type: integer, description: The ID of your publisher domain. }
page_url: { type: string, description: The page_url that received the impression. }
normalized_page_url: { type: string, description: A cleaned version of the page_url. }
impression_id: { type: string, description: 'The impression ID. NOTE: This can be duplicated, but is always unique when compared with the impression hour.' }
ts: { type: string, format: date-time, description: The timestamp (in UTC) of the impression. }
user_custom: { type: string, description: Also known as xcust. }
user_ip_country: { type: string, description: The 2 digit ISO-3166 country code associated with the user's ip address. }
user_ip_region: { type: string, nullable: true, description: This is now set to null. }
user_timezone: { type: integer, description: The timezone difference from UTC associated with the user's ip address. }
browser_family: { type: string }
browser_version: { type: string }
device_type: { type: string, nullable: true, description: 'Can be mobile, bot, pc, tablet or null.' }
device_family: { type: string }
os_family: { type: string }
os_version: { type: string }
affiliatable_links_count: { type: integer, description: The number of affiliatable links on the page. }
skimwords_count: { type: integer, description: The number of Skimwords on the page. }
page_referrer: { type: string, description: The page that the impression came from. }
datehour: { type: string, format: date-time, description: The date and hour (in UTC) of impression. This, used with impression_id will be unique. }
Commission:
type: object
description: Commission columns as published in the Data Pipe column reference.
properties:
id: { type: string, description: The commission ID. }
publisher_domain_id: { type: integer }
merchant_id: { type: integer }
merchant_name: { type: string }
click_id: { type: string }
skim_product_id: { type: integer }
commission_type: { type: integer, description: The commission type ID. See CommissionType. }
click_date: { type: string, format: date-time, description: The timestamp (in UTC) of the click. }
currency: { type: string, description: The currency of the transaction (NOT of the converted value). }
publisher_commission_amount: { type: string, description: The commission amount you received, converted to your chosen reporting currency, in MINOR currency units. }
order_amount: { type: string, description: The order amount, converted to your chosen reporting currency, in MINOR currency units. }
items_count: { type: integer, description: The number of items associated with the sale. }
target_url: { type: string }
normalized_target_url: { type: string }
page_url: { type: string }
normalized_page_url: { type: string }
user_custom: { type: string }
ts_updated: { type: string, format: date-time, description: The timestamp (in UTC) of when the commission was last updated. }
transaction_datetime: { type: string, format: date-time, description: 'The timestamp of the transaction that the network reported. NOTE: this is not in UTC.' }
cancelled: { type: boolean, description: Whether or not the transaction was cancelled. Commission amount itself may have some value. }
ProductPurchased:
type: object
description: Products (purchased) columns as published in the Data Pipe column reference.
properties:
merchant_name: { type: string }
merchant_id: { type: integer }
publisher_domain_id: { type: integer }
purchase_date: { type: string, format: date, description: 'The date of the transaction that the network reported. NOTE: this is not in UTC.' }
product_sku: { type: string, description: The stock keeping unit for the product. Populated only for merchants that share product information. }
product_name: { type: string, description: Populated only for merchants that share product information. }
price: { type: number, description: The price of the product, converted to your chosen reporting currency. }
publisher_revenue: { type: number, description: The revenue you received, converted to your chosen reporting currency. }
currency: { type: string }
quantity: { type: integer, description: The item count of the product. }
cancelled: { type: boolean }
skim_product_id: { type: integer }
target_url: { type: string }
page_url: { type: string }
normalized_target_url: { type: string }
normalized_page_url: { type: string }
user_custom: { type: string }
click_id: { type: string }
click_date: { type: string, format: date-time }
total_order_amount: { type: number, description: The value of the complete basket for the order, converted to your chosen reporting currency. }
aggregation_id: { type: string, description: In some cases Skimlinks marks commissions as cancelled when the total commission amount is 0 for an aggregation id. }
transaction_datetime: { type: string, format: date-time }
impression_id: { type: string }
user_ip_country: { type: string }
user_timezone: { type: integer }
browser_family: { type: string }
browser_version: { type: string }
device_type: { type: string, nullable: true }
device_family: { type: string }
os_family: { type: string }
os_version: { type: string }
is_js: { type: boolean }
platform_id: { type: integer, description: 0 is Web. 1 is AMP. }
page_referrer: { type: string }
normalized_page_referrer: { type: string }
page_utm_source: { type: string }
page_utm_term: { type: string }
page_utm_campaign: { type: string }
page_utm_medium: { type: string }
page_utm_content: { type: string }
page_utm_brand: { type: string }
link_utm_source: { type: string }
link_utm_term: { type: string }
link_utm_campaign: { type: string }
link_utm_medium: { type: string }
link_utm_content: { type: string }
page_fbclid: { type: string }
page_cid: { type: string }
page_ncid: { type: string }
page_source: { type: string }
page_src: { type: string }
CommissionType:
type: integer
description: Commission type IDs published by Skimlinks. Only types 1, 2 and 3 may have an associated click, and even then rarely absent; types 4-10 never have one.
oneOf:
- { const: 1, title: Sale }
- { const: 2, title: Lead }
- { const: 3, title: Click }
- { const: 4, title: Performance incentive (redistributed) }
- { const: 5, title: Referral bonus }
- { const: 6, title: Standard bonus }
- { const: 7, title: Performance Incentives (Original) }
- { const: 8, title: Bonus merchant }
- { const: 9, title: Flat-fee bonus }
- { const: 10, title: Flat-fee bonus Skimlinks fee }
SkimlinksProductId:
type: integer
description: Skimlinks product IDs published by Skimlinks.
oneOf:
- { const: 1, title: Skimlinks }
- { const: 2, title: Skimwords }
- { const: 12, title: PCM }
- { const: 13, title: Editorial }
- { const: 16, title: Product Key }
x-encoding:
description: >-
The column types above are LOGICAL types. On-disk encoding depends on the
file format agreed with Skimlinks (Avro binary, or CSV compressed or
uncompressed), exactly as published.
timestamp: { avro: long (UNIX milliseconds, UTC), csv: 'string YYYY-MM-DD HH:MM:SS (UTC)' }
date: { avro: int (days since 1970-01-01), csv: string YYYY-MM-DD }
boolean: { avro: native AVRO boolean, csv: string TRUE / FALSE }
x-partitioning:
immutable_datasets: [clicks, pages]
immutable_partition_key: date
mutable_datasets: [commissions, products]
mutable_partition_key: snapshot_date
snapshot_window_days: 120
version_prefix: version=0
restatement: >-
Every partition is written under version=0/. A restated partition REPLACES
the contents of the same version=0/ directory — higher version numbers are
never created and the previous files are removed before the new ones are
written, so a read job finishing after a restate sees only the latest data.
retention: >-
When the destination bucket is owned by Skimlinks, files are retained for 30
days after initial upload; customers are told to keep their own backups.
x-onboarding:
model: sales-assisted
steps:
- Agree that Data Pipe is the right solution and choose the delivery file format.
- Set up the destination bucket (GCS preferred, or S3) and arrange permissions with Skimlinks.
- Skimlinks configures the daily export pipeline and runs a testing period before handover.
note: >-
There is no self-serve provisioning API and no published price. Access is
arranged with Skimlinks directly.
Work with this as data
Every AsyncAPI spec here is available over the APIs.io API and to AI agents over MCP.
MCP server
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
Tools for asyncapi
4 MCP tools reach this
find_asyncapisBrowse and filter every AsyncAPI spec in the catalog.apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.resolveTurn a domain, URL or GitHub org into the provider it belongs to.find_cohortsEvery scored population of providers in the catalog.
Call it yourself
curl for this page
curl "https://apis.io/api/v1/asyncapis/skimbit-data-pipe-asyncapi"
curl "https://apis.io/api/v1/asyncapis?limit=25"
Discovery needs no key. Ratings and market analysis are Pro.
Get an API key
Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.
A second provider on the same verified email joins the account you already have.