Appearance
Edit Link
Links are edited with the links table mutations — update_links_by_pk for a single link, update_links for a filtered set. There is no edit_link mutation.
INFO
create_link exists as a custom resolver because creating a link involves scraping Spotify and resolving DSPs. Editing needs none of that, so it goes through the ordinary table mutation surface described in Querying Data.
Update one link
graphql
mutation EditLink($id: uuid!, $changes: links_set_input!) {
update_links_by_pk(pk_columns: { id: $id }, _set: $changes) {
id
domain
path
title
subtitle
description
image
theme
layout
preview_type
display_artist_socials
release_name
release_time
}
}Variables:
json
{
"id": "9c4b2f10-...",
"changes": {
"title": "Example Single (Deluxe)",
"subtitle": "Example Artist",
"theme": "dark"
}
}Returns the updated row, or null if the link does not exist or belongs to an artist you do not manage.
Editable columns
A manager may set these columns and no others:
| Column | Type | Notes |
|---|---|---|
title | String | Headline. |
subtitle | String | Secondary line. |
description | String | Body and share description. |
image | String | Preview image URL. |
title_image | String | Image used instead of title text. |
theme | String | light or dark only — see below. |
layout | String | Layout variant. |
style | String | Style preset. |
background_color | String | Background colour. |
background_style | String | Background treatment. |
cover_image_style | String | Cover art presentation. |
bio_header_style | String | Bio header presentation. |
title_font_size | String | Title sizing. |
preview_type | String | image or spotify. |
display_artist_socials | Boolean | Show artist socials. |
domain | String | Move the link to another domain. |
path | String | Change the path. |
type | String | bio, release, or playlist. |
release_name | String | Release title. |
release_time | timestamptz | Scheduled release moment. |
timezone | String | Timezone for release_time. |
offset | String | UTC offset for release_time. |
post_release_title | String | Title shown after release. |
post_release_subtitle | String | Subtitle shown after release. |
rid | String | Internal release identifier. |
Setting anything outside this list — artist_id, views_total, clickthroughs_total, created_at, id — fails with permission-error. Counters and ownership are server-managed.
WARNING
theme must be light or dark. The permission rule that governs updates includes a theme check, so an update that sets theme to any other value matches zero rows and silently returns null — it does not raise a validation error. If an update mysteriously affects nothing, check theme first.
Changing the public URL
domain and path are editable, so a link can be moved:
graphql
mutation MoveLink($id: uuid!) {
update_links_by_pk(
pk_columns: { id: $id }
_set: { domain: "listen.to", path: "example-single-2026" }
) {
id
domain
path
}
}Two cautions. The new domain + path must be free, or the write fails with constraint-violation — check with path_available first. And the old URL stops working immediately; anything already printed, posted, or running in ads breaks. Confirm availability before moving:
graphql
mutation { path_available(domain: "listen.to", path: "example-single-2026") { success } }Custom domains must be assigned to the artist before a link can be moved onto them. See Domains.
Scheduling a release
Pre-release links show one set of copy before release_time and another after.
graphql
mutation Schedule($id: uuid!) {
update_links_by_pk(
pk_columns: { id: $id }
_set: {
release_time: "2026-09-04T00:00:00Z"
timezone: "America/New_York"
post_release_title: "Out Now"
post_release_subtitle: "Stream Example Single everywhere"
}
) {
id
release_time
post_release_title
}
}Updating several links at once
graphql
mutation ThemeAll($artist_id: uuid!) {
update_links(
where: { artist_id: { _eq: $artist_id }, type: { _eq: "release" } }
_set: { theme: "dark" }
) {
affected_rows
returning { id path theme }
}
}affected_rows is the count actually written. A lower number than expected means some rows were filtered out by permissions — including the theme rule above.
Deleting a link
graphql
mutation DeleteLink($id: uuid!) {
delete_links_by_pk(id: $id) {
id
domain
path
}
}Or in bulk:
graphql
mutation DeleteLinks($ids: [uuid!]!) {
delete_links(where: { id: { _in: $ids } }) {
affected_rows
}
}DANGER
Deletion is permanent and cascades to the link's destinations and tracks. The public URL returns a 404 immediately, and historical analytics for the link become unreachable through link_statistics. There is no undo — archive by disabling destinations instead if you may want the link back.
Editing destinations
Destination buttons are separate rows and are edited through their own mutations. See Destinations.
Errors
| Symptom | Cause |
|---|---|
Returns null | Link does not exist, is not yours, or theme was set to a value other than light/dark. |
permission-error | A column outside the editable list was included in _set. |
constraint-violation | The new domain + path pair is already taken. |
validation-failed | Missing token, or a column name that does not exist. |