Appearance
Getting Started
Endpoint
The ArtistHub API is a GraphQL endpoint that takes POST requests.
https://api.artisthub.io/v1/graphqlGET is not supported and returns 404. Every request must be a POST with a JSON body.
Why GraphQL?
GraphQL is a query language for APIs and a runtime for executing those queries against a type system defined for your data. Unlike REST, which relies on rigid endpoint structures, GraphQL lets clients shape queries and mutations exactly as needed, reducing over-fetching and under-fetching.
In practice this means one round trip can return an artist, its links, each link's destinations, and each link's tracks — rather than four calls and a client-side join.
Building a Request
There are two pieces of information you need to start using the ArtistHub API.
Authentication token. Nearly every field requires a token. Get one with the login mutation and send it as a Bearer token in the authorization header. See Authentication.
Artist ID. Each artist has a unique UUID. Most operations take this ID to identify which artist you are acting on. You receive the list of artists you can access in the login response, and can re-fetch it any time with Get Artists.
Request shape
A request body is JSON with a query string and an optional variables object.
json
{
"query": "query GetArtists { artists { id name spotify_id } }",
"variables": {}
}Required headers:
| Header | Value |
|---|---|
content-type | application/json |
authorization | Bearer <token> |
Your first three calls
1. Log in
graphql
mutation Login($email: String!, $password: String!) {
login(email: $email, password: $password) {
token
user {
id
email
artists {
id
name
spotify_id
}
}
}
}Keep token. Keep the artists[].id values — those are your artist IDs.
2. List the artist's links
graphql
query GetLinks($artist_id: uuid!) {
links(
where: { artist_id: { _eq: $artist_id } }
order_by: { created_at: desc }
limit: 25
) {
id
domain
path
type
title
views_total
clickthroughs_total
}
}The public URL of a link is https://{domain}/{path}.
3. Pull analytics for one link
graphql
query LinkStats($link_id: uuid!, $start_time: date!, $end_time: date!) {
link_statistics(
link_id: $link_id
start_time: $start_time
end_time: $end_time
) {
events
countries
campaigns
destinations
}
}See Link Stats for the response shape and the campaign filters.
HTTP status codes
The API almost always answers 200 OK, including for errors. GraphQL reports failures in the errors array of the response body, not in the status line. Check errors before data. See Errors for the full list of codes and what each one means.
json
{
"errors": [
{
"extensions": { "code": "validation-failed", "path": "$.selectionSet.links" },
"message": "field 'links' not found in type: 'query_root'"
}
]
}That particular error usually means you are unauthenticated, not that the field is misspelled.
Rate limits
There is no published per-key rate limit today. The API is backed by a shared database and a shared analytics store, so treat it accordingly:
- Batch related reads into one GraphQL document instead of issuing many small requests.
- Use
limitandoffsetwhen walking large collections rather than fetching everything. - Cache analytics responses.
link_statisticsandartist_statisticsare the most expensive fields in the API — they fan out to an external analytics store on every call. - Back off and retry on
5xxresponses.
Next steps
- Authentication — tokens, roles, and claims
- Querying Data — filtering, sorting, pagination, aggregates
- Errors — every error code and how to recover
- Schema Reference — every query and mutation