NAV
shell

Introduction

Welcome to the Kanvas API specs!

The API examples use http, basically cURL but a bit easier to use.

Authentication

Endpoints that require a logged in user expect a valid token in the Authorization header. To get new a token, call /auth/login.

# Login, and get an access token:
http POST "/auth/login" <<EOF
{
    "userAddress": "$user_address",
    "signedPayload": "$user_password",
}
EOF

To authorize at authorization guarded endpoints, eg /auth/logged_in, set the "Authorization" header alike:

http GET "/auth/logged_in" \
  Authorization:"Bearer $access_token"

Make sure to replace $access_token with your token.

For more info see the "Users auth" section.

NFTs

Get NFTs (optionally with filters)

http "/nfts"

The above command returns JSON structured alike:

{
    "currentPage": 1,
    "numberOfPages": 4,
    "lowerPriceBound": "1.12",
    "upperPriceBound": "105.00",
    "nfts": [
        {
            "artifactUri": "https://kanvas-admin-files.s3.amazonaws.com/NFT_FILE__6_image.png",
            "categories": [
                {
                    "description": "Not actually visual",
                    "id": 3,
                    "name": "Applied Art"
                }
            ],
            "createdAt": 1645710471,
            "description": "Nice for breakfast",
            "displayUri": "https://kanvas-admin-files.s3.amazonaws.com/NFT_FILE__6_image.png",
            "editionsAvailable": 0,
            "editionsSize": 1,
            "id": 6,
            "ipfsHash": "ipfs://QmQx1zaVfbXk1JfPGhHo3pRaBgcHBzsHC1EVzXEkG2k1rz",
            "launchAt": 1645743600,
            "name": "baguette",
            "price": "1.68",
            "thumbnailUri": "https://kanvas-admin-files.s3.eu-central-1.amazonaws.com/NFT_FILE__6_thumbnail.png"
        }
    ]
}

Results are paginated.

Optionally, a set of filters can be specified. NFTs can be filtered by: categories, userAddress, priceAtLeast, priceAtMost, availability (for more info see the Query parameters section below).

For each filter, if not specified, it's not applied (so, for example, if no availability is specified, NFTs of all availability status' are returned).

If multiple filters are specified, NFTs that fit each criteria are returned (AND logic, not OR).

The return includes additional general info:

Note: ipfsHash may be null in the response. It's only set (not null) for NFTs that have already been purchased at least once. We do this to allow remaining uncommitted to the existence of an NFT for as long as possible. This would be useful in case for some reason an NFT no longer is deemed appropriate and should be delisted. Delisting is always possible, in the sense of blacklisting it from the store, however once the IPFS hash is shared and the NFT is minted on the blockchain, it is no longer possible to erase the NFT entirely.

HTTP Request

GET /nfts

HTTP Request (with some filters set)

GET /nfts?userAddress=tz1..&availability=onSale,upcoming

Query parameters

Parameter Default Description
page 1 Paginate through results, first page is 1
pageSize 10 Number of NFTs to fit on a single page
orderBy 'id' must be one of ['id', 'createdAt', 'price', 'name', 'views'].
orderDirection 'asc' must be one of ['asc', 'desc'].
categories undefined Get NFTs that belong to any of a comma separated set of category identifiers (eg: 1,4,10). Multiple entries here means: find NFTs that belong to at least one of the given categories.
userAddress undefined Get NFTs that are owned by some tezos address.
availability undefined Comma separated enable-list of availability status (each entry being one of 'onSale','soldOut','upcoming'). Multiple entries means find NFTs that belong to one of the entries.
priceAtLeast undefined Get NFTs that at least cost x amount (x is inclusive).
priceAtMost undefined Get NFTs that at most cost x amount (x is inclusive).
firstRequestAt undefined In seconds since UNIX, the timestamp of first pagination action (note: responsibility of setting this is at the caller). If set, only NFTs will be returned that were listed on the store at or before this timestamp.
currency EUR Specify on which currency the price is returned. Options: USD, GBP, EUR, XTZ.

Search NFTs

http "/nfts/search" searchString=='rock'

The above command returns JSON structured alike:


{
    "categories": [
        {
            "id": 2,
            "name": "rock n roll",
            "description": "guitar music"
        }
    ],
    "nfts": [
        "nfts": [
        {
            "artifactUri": "https://kanvas-admin-files.s3.amazonaws.com/NFT_FILE__54_image.png",
            "categories": [
                {
                    "description": "Sub photography category",
                    "id": 9,
                    "name": "Abstract"
                }
            ],
            "createdAt": 1653314947,
            "description": "testing nft end date",
            "displayUri": "https://kanvas-admin-files.s3.amazonaws.com/NFT_FILE__54_image.png",
            "editionsAvailable": 33,
            "editionsSize": 34,
            "id": 54,
            "ipfsHash": "ipfs://QmUVVgxmjpBt6SF8pNJZRNJiqy5nczL9xN8jiNJkTDApGW",
            "launchAt": 0,
            "name": "nft with end date",
            "onsaleUntil": 1662019200,
            "price": "13.00",
            "thumbnailUri": "https://kanvas-admin-files.s3.eu-central-1.amazonaws.com/NFT_FILE__54_thumbnail.png"
        }
    ]
}

This searches for:

Currently returns a maximum of 3 NFTs and a maximum of 5 categories, sorted by most relevant first.

HTTP Request

GET /nfts/search

Query parameters

Parameter Description
searchString The text to search for

Get a specific NFT

http POST "/nfts/2"

The above command returns JSON structured alike:

{
    "artifactUri": "https://kanvas-admin-files.s3.eu-central-1.amazonaws.com/NFT_FILE__39_image.png",
    "categories": [
        {
            "description": "Sub photography category",
            "id": 16,
            "name": "Black & White"
        }
    ],
    "createdAt": 1649094886,
    "description": "oldschool",
    "displayUri": "https://kanvas-admin-files.s3.eu-central-1.amazonaws.com/NFT_FILE__39_image.png",
    "editionsAvailable": 3,
    "editionsSize": 6,
    "id": 39,
    "ipfsHash": "ipfs://QmYdeHrRH1K6PKP5rmie5KYCHePJYXjn2CGauP5FJWnj2i",
    "launchAt": 0,
    "name": "typewriter",
    "price": "0.04",
    "thumbnailUri": "https://kanvas-admin-files.s3.eu-central-1.amazonaws.com/NFT_FILE__39_thumbnail.png"
}

Note: this is a POST, not a GET, because on each call we increment a "views" count. This is then used to allow for sorting /nfts on number of views.

HTTP Request

POST /nfts/:id

URL parameters

Parameter Description
id The id of the NFT to retrieve

Categories

Get all categories

http "/categories"

The above command returns JSON structured alike:

[
    {
        "children": [
            {
                "children": [
                    {
                        "children": [],
                        "description": "its part of rock",
                        "id": 4,
                        "name": "nirvana"
                    }
                ],
                "description": "its part of a mountain",
                "id": 3,
                "name": "rock"
            }
        ],
        "description": "steep hills that go heigh",
        "id": 1,
        "name": "mountains"
    },
    {
        "children": [],
        "description": "its not actually blue",
        "id": 2,
        "name": "water"
    }
]

HTTP Request

GET /categories

Users auth

Create account

http POST "/auth/register" <<EOF
{
    "userAddress": "$user_address",
    "signedPayload": "$user_password"
}
EOF

HTTP Request

POST /auth/register

Body parameters

Parameter Description
userAddress tezos address
signedPayload password
userName username (currently it's optional)

Login

http POST "/auth/login" <<EOF
{
    "userAddress": "$user_address",
    "signedPayload": "$user_password"
}
EOF

The above command returns JSON structured alike:

{
    "userAddress": "addr",
    "id": 1,
    "maxAge": "86400000",
    "userName": null,
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwibmFtZSI6bnVsbCwiYWRkcmVzcyI6ImFkZHIiLCJyb2xlcyI6W10sImlhdCI6MTYzNzI0ODM5Nn0.HovGQYf8QaVh0ZEdLhYBzBYqqYTrH34j6MUDBw8Bb2M"
}

The "token" in the response is a JWT, it's the token that can be passed to any endpoints that require authorization by setting the "Authorization" header to "Bearer $token".

HTTP Request

POST /auth/login

Body parameters

Parameter Description
userAddress tezos address
signedPayload password

Logged in user

http "/auth/logged_user" Authorization:"Bearer $access_token"

The above command returns JSON structured alike:

{
    "id": 3,
    "userName": "utan_second-hand_10",
    "userAddress": "tz2D1s4VvB8HU8YrYGjKQJ3zXxiJw6QHyZQa",
    "createdAt": 1645716097,
    "profilePicture": null
}

HTTP Request

GET /auth/logged_user

Logout

http POST "/auth/Logout" Authorization:"Bearer $access_token"

HTTP Request

POST /auth/logout

User profile

Get profile

http "/users/profile" userAddress==tz1

The above command returns JSON structured alike:

{
    "nftCount": 2,
    "user": {
        "createdAt": 1638452668,
        "id": 2,
        "profilePicture": "https://some-url (eg may be AWS S3 hosted)",
        "userAddress": "tz1",
        "userName": "test user"
    }
}

HTTP Request

GET /users/profile

Query parameters

Parameter Description
userAddress tezos address (optional, if undefined the endpoint returns currently logged in user if logged in).

Edit profile

Edit:

http -f POST "/users/profile/edit" profilePicture@./tg_image_775116946.jpeg userName=test

The above command only returns the status code (201 on success), no body

HTTP Request

POST /users/profile/edit (form, content-type: multipart/form-data)

Body parameters

Parameter Description
userName change username

Check validity of username edit

http "/users/profile/edit/check" userName==test

The above command returns JSON structured alike:

{
    "available": true,
    "userName": "test"
}

Note: must be logged in.

HTTP Request

GET /users/profile/edit/check

Query parameters

Parameter Description
userName username to check availability for

Top buyers

Get the list of top buyers.

http "/users/topBuyers"

The above command only returns JSON structured alike:

{
    "topBuyers": [
        {
            "totalPaid": "3019.91",
            "userAddress": "tz1g3coajkc9N77XDy55pVEgBGWspQfYqMiH",
            "userId": 1,
            "userName": "Setter_agitated_17",
            "userPicture": null
        },
        {
            "totalPaid": "1019.84",
            "userAddress": "tz2D1s4VvB8HU8YrYGjKQJ3zXxiJw6QHyZQa",
            "userId": 3,
            "userName": "utan_second-hand_10",
            "userPicture": null
        },
        {
            "totalPaid": "25.00",
            "userAddress": "tz1WWcuiKUN4Ed5zouETqr7MbVzd3vkC4ubr",
            "userId": 16,
            "userName": "Rattlesnake_naive_7",
            "userPicture": null
        },
        ...
    ]
}

HTTP Request

POST /users/profile/edit (form, content-type: multipart/form-data)

Cart

All endpoints related to shopping cart management.

A cart session is either derived from the cookie session (when not logged in) or from the cart session that is connected to the logged in user. When logging in after having done some cart operations on the cookie session, the user is connected to the cookie based cart session (and if the user was already connected to another cart session, this other session is canceled).

The only cart related endpoint that requires being logged in is the checkout endpoint.

Every cart session has an expiration date. In our demo deployments this is 30 minutes after the last POST action (add, remove, list), but this can be set to whichever duration, determined by an environment variable.

List NFTs in the cart

http POST "/users/cart/list"

The above command returns JSON structured alike:

{
    "expiresAt": "2021-11-18T14:29:59.403Z",
    "nfts": [
        {
            "id": 1,
            "name": "SomeNFT",
            ...
        }
    ]
}

HTTP Request

POST /users/cart/list

Add NFT

Note, this may fail if

http POST "/users/cart/add/2"

HTTP Request

POST /users/cart/add/:id

URL parameters

Parameter Description
id The id of the NFT to add to the cart

Remove NFT

http POST "/users/cart/remove/2"

HTTP Request

POST /users/cart/remove/:id

URL parameters

Parameter Description
id The id of the NFT to remove from the cart

Checkout cart

Checking out the cart involves creating a payment intent, which then has to be met (finalized) in the frontend application. For example, if paying with Stripe, the payment intent has to be finalized by applying Stripe's SDK in the frontend.

http POST "/payment/create-payment-intent" Authorization:"Bearer $access_token"

HTTP Request

POST /payment/create-payment-intent

Nft Ownership status

This endpoint is used to find out after having finished payment whether the purchased NFTs have arrived to the user's wallet onchain or if this process is still pending.

Note that a user can own multiple editions of a single NFT (though limited by 1 edition per NFT per cart, users can own multiple editions regardless either through multiple payments or through onchain transfers). Therefore this endpoint returns per requested nftId a list of ownerships, eg if someone already fully owns nftId 1, and then purchases again nftId 1, until the latter purchase has been processed onchain the response for this nftId will be: { nftId: "37", ownerStatuses: ["owned", "pending"] }.


```shell
http POST /users/nftOwnership

Example response is alike: [ { nftId: "37", ownerStatuses: ["owned", "pending"] } ]

HTTP Request

POST /users/nftOwnership?nftIds=5,10,..

URL parameters

Parameter Description
nftIds A comma separated list of nft IDs to check the status of

Checkout cart

Checking out the cart involves creating a payment intent, which then has to be met (finalized) in the frontend application. For example, if paying with Stripe, the payment intent has to be finalized by applying Stripe's SDK in the frontend.

http POST "/payment/create-payment-intent" Authorization:"Bearer $access_token"

Response is alike: { "amount": "0.66", "currency": "EUR", "clientSecret": "pi_3L2foUEdRDZNp7JF0yajTKrM_secret_cs3SWGJy7xdd5M19EwShCjbdE", "id": "pi_3L2foUEdRDZNp7JF0yajTKrM" }

The "clientSecret" here is the important piece that links the following finalization of the payment with the newly created payment intent.

HTTP Request

POST /payment/create-payment-intent

Errors

-