Valise API
Build developer integrations on top of Valise.
The API is a technical feature meant for developers. If you’re looking for ways to get your data out of Valise, check out our export options.
Valise offers a REST API for programmatically accessing your data. You can use this API to build integrations on top of Valise, such as:
- Powering a website with artworks from your vault
- Updating data in other systems when it changes in Valise
Getting Started
To start using the API, create an API key from the developer settings of your dashboard. You can use this key to authenticate to the API calls described in the endpoints section.
Overview
Base URL
All requests should be made to the following base URL:
https://api.valise.worksAuthentication
The API uses API keys to authenticate requests. For any endpoint, pass a Bearer token in the Authorization header of the request.
Authorization: Bearer <API_KEY>curl https://api.valise.works/v0/artworks
--header "Authorization: Bearer <API_KEY>"fetch("https://api.valise.works/v0/artworks", {
headers: {
Authorization: "Bearer <API_KEY>",
},
})To generate an API key, go to the developer settings of your dashboard and press the Create API key button.
API keys are associated with a vault, not with a user account, so you don’t need to worry about leaving a vault revoking the key’s access. By default, keys don’t expire.
Permissions
When you create a key, you choose its scope:
- Read-only keys can fetch data using the
GETendpoints. This is the default. - Read and write keys can additionally create, update, and delete records.
If a read-only key is used on a write endpoint, the API responds with a 403 error. Keys created before scopes were introduced are read-only.
Pagination
When an API response returns a list of records, information about pages will be returned in the response.
By default, up to 100 items are returned per page, which is the maximum value. You can change this limit by passing the limit query parameter to the endpoint.
Paginated responses will look like this:
{
"data": [ ... ],
"page": {
"count": 100, // Number of items in the current page
"next": "https://api.valise.works/..." // Next page of results, or null if no more
}
}You can use the page.next URL to make additional requests to get all the records by looping through the values until they return null.
For example, here’s how you could fetch all the artworks in your vault in Javascript:
const fetchArtworks = async () => {
let artworks = []
let next = "https://api.valise.works/v0/artworks"
while (next) {
// Note: authentication and error handling are omitted here for brevity.
const response = await fetch(next)
const data = await response.json()
artworks.push(...data.data)
next = data.page.next
}
return artworks
}Rate limiting
The API allows up to 300 requests per minute. Every response includes headers so you can track your usage:
| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum requests allowed per window (300) |
X-RateLimit-Remaining | Requests remaining in the current window |
Retry-After | Seconds to wait before retrying (only on 429 errors) |
If you exceed the limit, the API will return a 429 status code. You should wait for the number of seconds in the Retry-After header before retrying.
Response codes
We use standard HTTP codes to indicate the success or failure of a request. In general, 2xx codes indicate success, 4xx codes indicate client errors, and 5xx codes indicate infrastructure issues.
| Status | Description |
|---|---|
200 | Successful request |
201 | A resource was created |
204 | The request succeeded with no response body |
400 | Check that the request parameters are correct |
401 | No API key was provided with the request |
403 | The API key is invalid or not permitted to do this |
404 | The resource was not found |
409 | The request conflicts with existing data |
413 | The request body is too large |
429 | The rate limit has been exceeded |
500 | An error happened with Valise’s servers |
Errors
When an API request fails, Valise returns a structured error response that follows this format:
{
"error": {
"code": "unauthenticated",
"message": "Please provide a valid API key with your request."
}
}The HTTP status code should give you a general sense of the error category, and the error.code field will give you a more specific reason for the error.
When a request fails validation, the response also includes a details array describing every problem at once, so you can fix them in a single pass. Each entry names the offending field (when applicable) and a message:
{
"error": {
"code": "bad_request",
"message": "The request is invalid.",
"details": [
{ "field": "title", "message": "Must be at most 500 characters." },
{ "field": "uid", "message": "Must be a valid UID, e.g. \"VD-123\"." }
]
}
}Endpoints
The API is still early: it currently covers artworks, collections, and tags, and we’re developing endpoints for other record types like sales, consignments, contacts, presentations, and press. If there’s an endpoint you need, please let us know, we’re happy to prioritize building it.
List artworks
Get information about all the artworks in your vault by calling this endpoint.
GET /v0/artworkscurl https://api.valise.works/v0/artworks
--method GET
--header "Authorization: Bearer <API_KEY>"Here’s an example response:
{
"data": [
{
"id": "d2qv8sj5i88kat3bka30",
"uid": "VD-123",
"title": "My Artwork",
"year": "2022",
"medium": "Acrylic on paper",
"dimensions": "35.56h x 31.75w x 3.81d cm; 14.0h x 13.0w x 2.0d in",
"notes": "Stored in the flat file, second drawer.",
"images": [
{
"id": "d2qv94c5i88kavrvigcg",
"type": "image",
"url": "https://uploads.valise.works/...",
"width": 1024,
"height": 1024,
"filename": "my-artwork.jpg"
}
],
"tags": [
{
"id": "d2qv8rb5i88kat33l28g",
"slug": "painting",
"title": "Painting"
}
],
"editions": [],
"createdAt": "2024-09-06T11:17:15.150Z",
"updatedAt": "2024-09-06T11:17:15.150Z"
}
],
"page": {
"count": 1,
"next": null
}
}If the artwork has editions, they’re listed in the editions array:
{
"id": "d2qv8sj5i88kat3bkbb0",
"type": "ap",
"editionNumber": 1,
"editionSize": 2
}The type is none for regular editions, ap for artist proofs, pp for printer proofs, and ec for exhibition copies. An artwork of 12+2AP has an editionSize of 12 for the regular editions and 2 for the artist proofs.
Get an artwork
Fetch a single artwork by its ID.
GET /v0/artworks/{id}curl https://api.valise.works/v0/artworks/d2qv8sj5i88kat3bka30
--header "Authorization: Bearer <API_KEY>"The response is a single artwork in the same shape as the entries in the list artworks response:
{
"data": {
"id": "d2qv8sj5i88kat3bka30",
"uid": "VD-123",
"title": "My Artwork"
// ...
}
}Create an artwork
Create a new artwork in your vault. Requires a key with read and write permission.
POST /v0/artworksThe request body accepts the following fields. Only title is required; Valise generates the artwork’s id and, if you don’t provide one, its uid.
| Field | Type | Description |
|---|---|---|
title | string | The title of the artwork. Required. |
uid | string | A user-provided ID (e.g. VD-123). If omitted, Valise generates the next UID for the vault. |
year | string | The year the artwork was created. |
medium | string | The medium of the artwork. |
dimensions | string | The dimensions of the artwork. |
notes | string | Free-form notes about the artwork. |
curl https://api.valise.works/v0/artworks
--method POST
--header "Authorization: Bearer <API_KEY>"
--header "Content-Type: application/json"
--data '{"title": "My Artwork", "year": "2022", "medium": "Acrylic on paper"}'On success, the API returns a 201 status code with the new artwork:
{
"data": {
"id": "d2qv8sj5i88kat3bka30",
"uid": "VD-123",
"title": "My Artwork",
"year": "2022",
"medium": "Acrylic on paper",
"dimensions": "",
"notes": "",
"images": [],
"tags": [],
"editions": [],
"createdAt": "2024-09-06T11:17:15.150Z",
"updatedAt": "2024-09-06T11:17:15.150Z"
}
}Update an artwork
Update an existing artwork. Requires a key with read and write permission.
PATCH /v0/artworks/{id}Only the fields you include in the request body are changed; omitted fields are left untouched. The body accepts the same fields as creating an artwork, all of which are optional here. To clear a field, pass an empty string.
Every artwork keeps a uid, so it can’t be cleared. Pass a new value to change it.
curl https://api.valise.works/v0/artworks/d2qv8sj5i88kat3bka30
--method PATCH
--header "Authorization: Bearer <API_KEY>"
--header "Content-Type: application/json"
--data '{"title": "Updated Title"}'On success, the API returns a 200 status code with the updated artwork, in the same shape as the create response.
Delete an artwork
Permanently delete an artwork and all of its associated data. This cannot be undone. Requires a key with read and write permission.
DELETE /v0/artworks/{id}curl https://api.valise.works/v0/artworks/d2qv8sj5i88kat3bka30
--method DELETE
--header "Authorization: Bearer <API_KEY>"On success, the API returns a 204 status code with no response body.
List collections
Get information about all the collections in a vault by calling this endpoint.
The artworkIds field is returned in the order of the works in the collection, and can be cross-referenced with data from the list artworks endpoint to display artworks as needed.
GET /v0/collectionscurl https://api.valise.works/v0/collections
--method GET
--header "Authorization: Bearer <API_KEY>"Here’s an example response:
{
"data": [
{
"id": "ehptxdig36vlctxmpe89p34n",
"title": "My Collection",
"notes": "Works for the spring exhibition",
"artworkIds": [
"ahvxb9zbcew4a0fhroz9ijs0",
"iogf1yv44dtudcam42a9rx8o",
"bes9dncmjfv9o2xbtrskzc1r"
// ...
],
"createdAt": "2024-09-06T11:17:15.150Z",
"updatedAt": "2024-09-06T11:17:15.150Z"
}
],
"page": {
"count": 1,
"next": null
}
}Get a collection
Fetch a single collection by its ID.
GET /v0/collections/{id}curl https://api.valise.works/v0/collections/ehptxdig36vlctxmpe89p34n
--header "Authorization: Bearer <API_KEY>"The response is a single collection in the same shape as the entries in the list collections response.
Create a collection
Create a new collection in your vault. Requires a key with read and write permission.
POST /v0/collectionsEvery field is optional. Passing artworkIds fills the collection at creation time, in the order given; you can also add works later with the add an artwork endpoint.
| Field | Type | Description |
|---|---|---|
title | string | The title of the collection. |
notes | string | A description of the collection. |
artworkIds | string[] | Artworks to add, in order. Each must be in the same vault. |
curl https://api.valise.works/v0/collections
--method POST
--header "Authorization: Bearer <API_KEY>"
--header "Content-Type: application/json"
--data '{"title": "Spring Show", "artworkIds": ["ahvxb9zbcew4a0fhroz9ijs0"]}'On success, the API returns a 201 status code with the new collection. If any of the artworkIds don’t exist in your vault, the API returns a 409 instead and nothing is created.
Update a collection
Update an existing collection. Requires a key with read and write permission.
PATCH /v0/collections/{id}Only the title and notes fields can be updated, and only the ones you include in the request body are changed. To clear a field, pass an empty string. To change which artworks are in the collection, use the endpoints below.
curl https://api.valise.works/v0/collections/ehptxdig36vlctxmpe89p34n
--method PATCH
--header "Authorization: Bearer <API_KEY>"
--header "Content-Type: application/json"
--data '{"title": "Spring Show 2025"}'On success, the API returns a 200 status code with the updated collection.
Delete a collection
Permanently delete a collection. The artworks in it are not deleted, only their membership in this collection. This cannot be undone. Requires a key with read and write permission.
DELETE /v0/collections/{id}curl https://api.valise.works/v0/collections/ehptxdig36vlctxmpe89p34n
--method DELETE
--header "Authorization: Bearer <API_KEY>"On success, the API returns a 204 status code with no response body.
Add an artwork to a collection
Add an artwork to the end of a collection. Requires a key with read and write permission.
POST /v0/collections/{id}/artworkscurl https://api.valise.works/v0/collections/ehptxdig36vlctxmpe89p34n/artworks
--method POST
--header "Authorization: Bearer <API_KEY>"
--header "Content-Type: application/json"
--data '{"artworkId": "ahvxb9zbcew4a0fhroz9ijs0"}'On success, the API returns a 200 status code with the updated collection. If the artwork is already in the collection, or isn’t in your vault, the API returns a 409.
Remove an artwork from a collection
Remove an artwork from a collection. The artwork itself is not deleted. Requires a key with read and write permission.
DELETE /v0/collections/{id}/artworks/{artworkId}curl https://api.valise.works/v0/collections/ehptxdig36vlctxmpe89p34n/artworks/ahvxb9zbcew4a0fhroz9ijs0
--method DELETE
--header "Authorization: Bearer <API_KEY>"On success, the API returns a 204 status code with no response body. Removing an artwork that isn’t in the collection also returns 204.
Reorder a collection
Set the order of the artworks in a collection. Requires a key with read and write permission.
POST /v0/collections/{id}/reorderThe artworkIds array must list every artwork currently in the collection exactly once. This endpoint only changes the order, so use the endpoints above to add or remove works.
curl https://api.valise.works/v0/collections/ehptxdig36vlctxmpe89p34n/reorder
--method POST
--header "Authorization: Bearer <API_KEY>"
--header "Content-Type: application/json"
--data '{"artworkIds": ["iogf1yv44dtudcam42a9rx8o", "ahvxb9zbcew4a0fhroz9ijs0"]}'On success, the API returns a 200 status code with the updated collection. If the list doesn’t match the collection’s current artworks, the API returns a 400 naming each work that’s missing, duplicated, or not in the collection.
Tags
Tags group artworks together.
Tag names are compared without regard to case or punctuation, so a vault can’t hold both an “Oil on Canvas” and an “oil on canvas” tag. To merge two tags into one, use the Valise dashboard.
List tags
Get all the tags in your vault. Use the IDs here to attach tags to artworks.
GET /v0/tagscurl https://api.valise.works/v0/tags
--header "Authorization: Bearer <API_KEY>"Here’s an example response:
{
"data": [
{
"id": "d2qv8rb5i88kat33l28g",
"title": "Painting",
"slug": "painting"
}
],
"page": {
"count": 1,
"next": null
}
}The slug is unique within a vault, so a vault can’t hold both a “Painting” and a “painting” tag.
Create a tag
Create a new tag in your vault. Requires a key with read and write permission.
POST /v0/tags| Field | Type | Description |
|---|---|---|
title | string | The name of the tag, up to 100 characters. Required. |
curl https://api.valise.works/v0/tags
--method POST
--header "Authorization: Bearer <API_KEY>"
--header "Content-Type: application/json"
--data '{"title": "Works on Paper"}'On success, the API returns a 201 status code with the new tag:
{
"data": {
"id": "d2qv8rb5i88kat33l28g",
"title": "Works on Paper",
"slug": "works-on-paper"
}
}If a tag with the same name already exists, the API returns a 409 and nothing is created. Use the list tags endpoint to find the existing one.
Rename a tag
Change a tag’s name. The tag keeps its ID, so every artwork already carrying it keeps it. Requires a key with read and write permission.
PATCH /v0/tags/{id}| Field | Type | Description |
|---|---|---|
title | string | The new name for the tag, up to 100 characters. Required. |
curl https://api.valise.works/v0/tags/d2qv8rb5i88kat33l28g
--method PATCH
--header "Authorization: Bearer <API_KEY>"
--header "Content-Type: application/json"
--data '{"title": "Drawings"}'On success, the API returns a 200 status code with the updated tag. If another tag already has that name, the API returns a 409.
Delete a tag
Permanently delete a tag. It’s removed from every artwork carrying it, but the artworks are not deleted. This cannot be undone. Requires a key with read and write permission.
DELETE /v0/tags/{id}curl https://api.valise.works/v0/tags/d2qv8rb5i88kat33l28g
--method DELETE
--header "Authorization: Bearer <API_KEY>"On success, the API returns a 204 status code with no response body.
Add a tag to an artwork
Attach an existing tag to an artwork. The tag must already be in the same vault, so create it first if it doesn’t exist. Requires a key with read and write permission.
POST /v0/artworks/{id}/tags| Field | Type | Description |
|---|---|---|
tagId | string | The ID of the tag to add. Required. |
curl https://api.valise.works/v0/artworks/d2qv8sj5i88kat3bka30/tags
--method POST
--header "Authorization: Bearer <API_KEY>"
--header "Content-Type: application/json"
--data '{"tagId": "d2qv8rb5i88kat33l28g"}'On success, the API returns a 200 status code with the updated artwork. Adding a tag the artwork already has also returns 200 and changes nothing, so it’s safe to retry. If the artwork or the tag isn’t in your vault, the API returns a 404.
Remove a tag from an artwork
Detach a tag from an artwork. The tag itself is not deleted. Requires a key with read and write permission.
DELETE /v0/artworks/{id}/tags/{tagId}curl https://api.valise.works/v0/artworks/d2qv8sj5i88kat3bka30/tags/d2qv8rb5i88kat33l28g
--method DELETE
--header "Authorization: Bearer <API_KEY>"On success, the API returns a 204 status code with no response body. Removing a tag the artwork doesn’t have also returns 204.
Community Resources
Valise users have built framework specific integrations on top of our API that may be helpful when working with the API:
- astro-loader-valise, for loading collections and artworks into an Astro-based site.