Appearance
Get Link
Links are read through the links table field, which supports the full filtering, sorting, and pagination described in Querying Data.
Row-level permissions scope results to artists your account is attached to, so a bare links query is already safe to run.
Get one link by ID
graphql
query GetLink($id: uuid!) {
links_by_pk(id: $id) {
id
domain
path
type
title
subtitle
description
image
theme
layout
preview_type
display_artist_socials
release_name
release_time
views_total
clickthroughs_total
created_at
destinations(order_by: { priority: asc }) {
id
type
url
cta
text
logo
enabled
deeplink_ios
deeplink_android
priority
}
tracks(order_by: { priority: asc }) {
id
name
url
priority
}
}
}Returns the link, or null if the ID does not exist or the link belongs to an artist you do not manage — the two cases are deliberately indistinguishable.
Get a link by its public URL
The domain + path pair is unique, so this is the way to resolve a URL you already have.
graphql
query GetLinkByPath($domain: String!, $path: String!) {
links(
where: {
domain: { _eq: $domain }
path: { _eq: $path }
}
limit: 1
) {
id
title
type
views_total
clickthroughs_total
}
}https://vibe.to/example-single becomes { "domain": "vibe.to", "path": "example-single" }.
INFO
Path uniqueness is enforced case-insensitively — create_link will not let you register Example-Single alongside an existing example-single. But _eq in a query is case-sensitive, so use _ilike when your input casing is unreliable: path: { _ilike: $path }.
List an artist's links
graphql
query ArtistLinks($artist_id: uuid!, $limit: Int = 25, $offset: Int = 0) {
links(
where: { artist_id: { _eq: $artist_id } }
order_by: { created_at: desc }
limit: $limit
offset: $offset
) {
id
domain
path
type
title
image
views_total
clickthroughs_total
created_at
}
links_aggregate(where: { artist_id: { _eq: $artist_id } }) {
aggregate { count }
}
}Response
json
{
"data": {
"links_by_pk": {
"id": "9c4b2f10-...",
"domain": "vibe.to",
"path": "example-single",
"type": "release",
"title": "Example Single",
"subtitle": "Example Artist",
"theme": "light",
"layout": "2",
"preview_type": "image",
"views_total": 4821,
"clickthroughs_total": 2043,
"created_at": "2026-07-18T14:02:11.482Z",
"destinations": [
{
"id": "b2d1...",
"type": "spotify",
"url": "https://open.spotify.com/album/4uLU6hMCjMI75M1A2tKUQC",
"cta": "Stream on Spotify",
"enabled": true,
"priority": 1
}
],
"tracks": []
}
}
}Fields
| Field | Type | Description |
|---|---|---|
id | uuid! | Link ID. |
artist_id | uuid | Owning artist. |
domain | String | Domain the link is served from. |
path | String | Path within the domain. |
type | String | bio, release, or playlist. |
title | String | Headline shown on the page. |
subtitle | String | Secondary line, usually the artist name. |
description | String | Body text and social share description. |
image | String | Preview/cover image URL. |
title_image | String | Optional image used in place of the title text. |
theme | String | light or dark. |
layout | String | Layout variant. |
style | String | Style preset. |
background_color, background_style | String | Background treatment. |
cover_image_style, bio_header_style, title_font_size | String | Presentation options. |
preview_type | String | image or spotify. |
autoplay_track | String | Spotify track ID autoplayed on playlist links. |
display_artist_socials | Boolean | Whether the artist's socials render on the page. |
release_name | String | Release title as read from Spotify at creation. |
release_time | timestamptz | Scheduled release moment, for pre-release links. |
timezone, offset | String | Timezone context for release_time. |
post_release_title, post_release_subtitle | String | Copy swapped in after release_time passes. |
campaigns_enabled | Boolean | Whether campaign tracking is active. |
rid | String | Internal release identifier used for DSP matching. |
views_total | Int | Lifetime page views. |
clickthroughs_total | Int | Lifetime destination clicks. |
created_at | timestamptz | Creation time. |
views_total and clickthroughs_total are running lifetime counters, cheap to read. For time-series, per-country, or per-campaign breakdowns use Link Stats.
Relationships
| Relationship | Kind | Description |
|---|---|---|
artist | object | The owning artist. |
destinations | array | Destination buttons. See Destinations. |
tracks | array | Preview tracks, used when preview_type is spotify. |
pixels | array | Tracking pixels firing on this link. |
optins | array | Email opt-ins captured through this link. |
presaves | array | Presave records. |
Useful filters
graphql
# Only release links
where: { type: { _eq: "release" } }
# Created this year
where: { created_at: { _gte: "2026-01-01" } }
# Title search
where: { title: { _ilike: "%remix%" } }
# Top performers
order_by: { clickthroughs_total: desc }, limit: 10
# Links across several artists at once
where: { artist_id: { _in: ["3aad8009-...", "7b21ff40-..."] } }
# Links that never got an Apple Music destination
where: { _not: { destinations: { type: { _eq: "applemusic" } } } }That last one is a practical way to find links worth running fill_missing_deeplinks against.
Lifetime totals across many links
graphql
query Totals($artist_id: uuid!) {
links_aggregate(where: { artist_id: { _eq: $artist_id } }) {
aggregate {
count
sum { views_total clickthroughs_total }
}
}
}