From 7e834c9e1c1511e2314460430aa03e6539cec216 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vinko=20=C5=A0mid?= Date: Wed, 11 Oct 2023 21:20:00 +0200 Subject: [PATCH 1/7] Storage & hosting api refacturing and new endpoints WIP --- build/3-apillon-api.md | 1755 +--------------------------------------- build/4-storage-api.md | 720 +++++++++++++++++ build/5-hosting-api.md | 699 ++++++++++++++++ build/6-nfts-api.md | 756 +++++++++++++++++ 4 files changed, 2206 insertions(+), 1724 deletions(-) create mode 100644 build/4-storage-api.md create mode 100644 build/5-hosting-api.md create mode 100644 build/6-nfts-api.md diff --git a/build/3-apillon-api.md b/build/3-apillon-api.md index 46529f69..a69c9862 100644 --- a/build/3-apillon-api.md +++ b/build/3-apillon-api.md @@ -59,6 +59,20 @@ If a request is made with an API key that lacks permission for called endpoint, | 403 | Insufficient permissions - missing `permission name` permission | API key lacks required permission for called service. | | 403 | Insufficient permissions to access this record | API key has required permissions for endpoint, but it does not have the right to access addressed record (e. g., a record belongs to a different project). | +### Listing requests + +Endpoints starting with "List" are intended to list different data, where the response contains 2 properties: `items`(records that match the current query) and `total` (number of all records. This information should be used for pagination: Round up (`total` / `limit`) = number of pages. + +Listing endpoints by default supports below query parameters: + +| Name | Description | Required | +| ------- | ----------------------------------------------------------------------------------------- | -------- | +| search | Search the items usually by name or by some other property, which specifies this item. | false | +| page | Items are paginated by default. This parameter is used to get items from a specific page. | false | +| limit | Number of items on a page (default: 20). | false | +| orderBy | One or multiple properties, separated by a comma, used to order data. | false | +| desc | `Boolean` values, mapped to the index of the `orderBy` parameter. Defaults to false. | false | + ### Responses
@@ -95,6 +109,7 @@ List of responses: - **201**: Creation successful - **400**: Bad request - **401**: Unauthenticated access +- **402**: Payment required - **403**: Unauthorized access - **404**: Path not found - **422**: Data validation failed @@ -184,1742 +199,34 @@ Fields in validation exception: | path | Endpoint that threw the error | timestamp | Date when the error occurred -## Web3 Storage API - -**Note:** To use Apillon Web3 Storage APIs, you should first create a bucket on the [Apillon dashboard](app.apillon.io/service/storage). - -In all cURL examples, parameters with a colon as a prefix should be replaced with real values. - -**File upload process through Apillon Web3 Storage API** - -1. Request signed URL(s) for upload. -2. File is uploaded to Apillon central server. -3. File is transferred to IPFS and available through the Apillon gateway. -4. File is replicated to different IPFS nodes globally via Crust Network. - -### Upload to bucket - -> API that creates file upload requests and returns URLs for file upload along with `sessionUuid`. - -
POST /storage/:bucketUuid/upload
- -
-
- -#### URL parameters - -| Name | Description | Required | -| ---------- | ---------------------------------------------------------------------- | -------- | -| bucketUuid | Unique key of storage bucket. Key is displayed on developer dashboard. | true | - -#### Body fields - -| Name | Type | Description | Required | -| ----- | ------- | ------------------------ | -------- | -| files | `array` | Array of files metadata. | true | - -Each file metadata object in `files` array, contain below properties. - -| Name | Type | Description | Required | -| ----------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | -| fileName | `string` | Full name (name and extension) of file to be uploaded | true | -| contentType | `string` | File [MIME type](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types) | false | -| path | `string` | Virtual file path. Empty for root. Must not contain `fileName`.

The `path` field can be used to place file in virtual directories inside a bucket. If directories do not yet exist, they will be automatically generated.

For example, an `images/icons` path creates `images` directory in a bucket and `icons` directory inside it. File will then be created in the `icons` directory. | false | - -#### Possible errors - -| Code | Description | -| -------- | ------------------------------------------------------------------------------ | -| 40406002 | Bucket does not exist. | -| 42200040 | Request body is missing a `files` field. | -| 42200008 | Request body file object is missing a `fileName` field. | -| 40006002 | Bucket has reached max size limit. | -| 40406009 | Bucket is marked for deletion. It is no longer possible to upload files to it. | -| 50006003 | Internal error - Apillon was unable to generate upload URL. | - -#### Response - -| Name | Type | Description | -| ----------- | -------- | ---------------------------------------------------------------------------------- | -| sessionUuid | `string` | Session unique key, which is later used to end upload and transfer files to bucket | -| files | `array` | Array of files metadata. | - -Files in request body are returned in response `data.files` property. Each file is equipped with `url` and `fileUuid`. All properties are displayed below. - -| Field | Type | Description | -| ----------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| url | `string` | URL for file upload. Signed URL is unique for each file and is valid only for a limited time (1 min), so you should start with file upload as soon as possible.

Request should use `PUT` method and `binary` body.

Binary data should be sent in body as-is, but with the appropriate Content-Type header (e.g., text/plain). | -| fileUuid | `string` | File unique identifier used to query file status, etc. | -| fileName | `string` | Full name (name and extension) of file to be uploaded | -| contentType | `string` | File [MIME type](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types) | -| path | `string` | File path. | - -
-
-
- - - -```sh -curl --location --request POST "https://api.apillon.io/storage/:bucketUuid/upload" \ ---header "Authorization: Basic :credentials" \ ---header "Content-Type: application/json" \ ---data-raw "{ - \"files\": [ - { - \"fileName\": \"My test file\", - \"contentType\": \"text/html\" - } - ] - -}" -``` - - - - - - -```json -{ - "id": "cbdc4930-2bbd-4b20-84fa-15daa4429952", - "status": 201, - "data": { - "sessionUuid": "3b6113bc-f265-4662-8cc5-ea86f06cc74b", - "files": [ - { - "path": null, - "fileName": "My test file", - "contentType": "text/html", - "url": "https://sync-to-ipfs-queue.s3.eu-west-1.amazonaws.com/STORAGE_sessions/73/3b6113bc-f265-4662-8cc5-ea86f06cc74b/My%20test%20file?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIAQIMRRA6GJRL57L7G%2F20230215%2Feu-west-1%2Fs3%2Faws4_request&X-Amz-Date=20230215T114524Z&X-Amz-Expires=900&X-Amz-Signature=499367f6c6bff5be50686724475ac2fa6307b77b94fd1a25584c092fe74b0a58&X-Amz-SignedHeaders=host&x-id=PutObject", - "fileUuid": "4ef1177b-f7c9-4434-be56-a559cec0cc18" - } - ] - } -} -``` - -**Example for uploading to signed URL:** - - - - - - - -```sh -curl --location --request PUT "https://sync-to-ipfs-queue.s3.eu-west-1.amazonaws.com/STORAGE_sessions/73/3b6113bc-f265-4662-8cc5-ea86f06cc74b/My%20test%20file?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIAQIMRRA6GJRL57L7G%2F20230215%2Feu-west-1%2Fs3%2Faws4_request&X-Amz-Date=20230215T114524Z&X-Amz-Expires=900&X-Amz-Signature=499367f6c6bff5be50686724475ac2fa6307b77b94fd1a25584c092fe74b0a58&X-Amz-SignedHeaders=host&x-id=PutObject" \ ---data-binary "My test content" -``` - - - - -```sh -curl --location --request PUT "https://sync-to-ipfs-queue.s3.eu-west-1.amazonaws.com/STORAGE_sessions/73/3b6113bc-f265-4662-8cc5-ea86f06cc74b/My%20test%20file?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIAQIMRRA6GJRL57L7G%2F20230215%2Feu-west-1%2Fs3%2Faws4_request&X-Amz-Date=20230215T114524Z&X-Amz-Expires=900&X-Amz-Signature=499367f6c6bff5be50686724475ac2fa6307b77b94fd1a25584c092fe74b0a58&X-Amz-SignedHeaders=host&x-id=PutObject" \ ---header "Content-Type: text/plain" \ ---data-binary ":full path to file" -``` - - - - -
-
- -### End upload session - -> Once files are uploaded to cloud server via received URL, trigger sync of files to IPFS and CRUST. - -
POST /storage/:bucketUuid/upload/:sessionUuid/end
- -
-
- -#### URL parameters - -| Name | Description | Required | -| ----------- | --------------------------------------------------------------- | -------- | -| bucketUuid | Unique key of bucket. Key is displayed in developer dashboard. | true | -| sessionUuid | Session uuid, recieved in [upload to bucket](#upload-to-bucket) | true | - -#### Possible errors - -| Code | Description | -| -------- | ---------------------------------------------- | -| 40406004 | Session does not exists | -| 40006001 | Files in this session were already transferred | - -#### Response - -Api respond with status `200 OK` , if operation is successfully executed. - -
-
-
- - - -```sh -curl --location --request POST "https://api.apillon.io/storage/:bucketUuid/upload/:sessionUuid/end" \ ---header "Authorization: Basic :credentials" \ ---header "Content-Type: application/json" \ ---data-raw "{ - \"directSync\": true -}" -``` - - - - - - -```json -{ - "id": "b64b1c07-1a8a-4b05-9e3b-3c6a519d6ff7", - "status": 200, - "data": true -} -``` - - - -
-
- -### Get bucket content - -> Gets directories and files in bucket. Items are paginated and can be filtered and ordered through query parameters. - -**Note: This endpoint returns files, that are successfully transferred to IPFS node. I.e. files with [fileStatus](#file-statuses) 3 or 4.** - -
GET /storage/:bucketUuid/content
- -
-
- -#### URL parameters - -| Name | Description | Required | -| ---------- | -------------------------------------------------------------- | -------- | -| bucketUuid | Unique key of bucket. Key is displayed on developer dashboard. | true | - -#### Query parameters - -| Name | Description | Required | -| ----------- | ----------------------------------------------------------------------------------------- | -------- | -| search | Filters file by file name. | false | -| directoryId | Gets files inside a specific directory. | false | -| page | Files are paginated by default. This parameter is used to get files from a specific page. | false | -| limit | Number of files on a page (default: 20). | false | -| orderBy | One or multiple properties, separated by a comma, used to order data. | false | -| desc | `Boolean` values, mapped to the index of the `orderBy` parameter. Defaults to false. | false | - -#### Possible errors - -| Code | Description | -| -------- | ---------------------- | -| 40406002 | Bucket does not exist. | - -#### Response fields - -The `Data` property of API response contains two properties: `items` (records that match the current query) and `total` (number of all records. This information should be used for pagination: Round up (`total` / `limit`) = number of pages. - -Properties of each item: - -| Field | Type | Description | -| ----------------- | ---------- | ------------------------------------------------------------------ | -| id | `integer` | Item internal ID | -| type | `integer` | Item type with possible values `1`(directory) and `2`(file) | -| name | `string` | Item (directory or file) name | -| createTime | `DateTime` | Item create time | -| updateTime | `DateTime` | Item last update time | -| contentType | `string` | Item content type (MIME type) | -| size | `integer` | Item size in bytes | -| parentDirectoryId | `integer` | ID of directory where a file is located | -| fileUuid | `string` | File unique identifier | -| CID | `string` | File content identifier - label used to point to material in IPFS. | -| link | `string` | File link on Apillon IPFS gateway. | - -
-
-
- - - -```sh -curl --location --request GET "https://api.apillon.io/storage/:bucketUuid/content" \ ---header "Authorization: Basic :credentials" -``` - - - - -```sh -curl --location --request GET "https://api.apillon.io/storage/:bucketUuid/content?orderBy=name&desc=false&limit=5&page=1" \ ---header "Authorization: Basic :credentials" -``` - - - - - - -```json -{ - "id": "c8c50b3b-91ff-42c7-b0af-f866ce23f18a", - "status": 200, - "data": { - "items": [ - ... - { - "type": 1, - "id": 11, - "status": 5, - "name": "My directory", - "CID": null, - "createTime": "2022-12-08T13:27:00.000Z", - "updateTime": "2023-01-10T12:18:55.000Z", - "contentType": null, - "size": null, - "parentDirectoryId": null, - "fileUuid": null, - "link": null - }, - { - "type": 2, - "id": 397, - "status": 5, - "name": "My file.txt", - "CID": "QmcG9r6Rdw9ZdJ4imGBWc6mi5VzWHQfkcLDMe2aP74eb42", - "createTime": "2023-01-19T10:10:01.000Z", - "updateTime": "2023-01-19T10:10:31.000Z", - "contentType": "text/plain", - "size": 68, - "parentDirectoryId": null, - "fileUuid": "0a775bfa-a0d0-4e0b-9a1e-e909e426bd11", - "link": "https://ipfs.apillon.io/ipfs/QmcG9r6Rdw9ZdJ4imGBWc6mi5VzWHQfkcLDMe2aP74eb42" - } - ... - ], - "total": 10 - } -} -``` - - - -
-
- -### Get file details - -> Gets details of a specific file inside a bucket. - -
GET /storage/:bucketUuid/file/:id/detail
- -
-
- -#### URL parameters - -| Name | Description | required | -| ---------- | ---------------------------------------------------------------- | -------- | -| bucketUuid | Unique key of a bucket. Key is displayed on developer dashboard. | true | -| id | File internal ID, UUID or CID. | true | - -#### Possible errors - -| Code | Description | -| -------- | -------------------- | -| 40406005 | File does not exist. | - -#### Response fields - -Response `data` property contains two properties: `fileStatus` and `file`. File status tells the current status of the file relative to the entire flow the file goes through to be fully loaded and pinned on Crust Network, while `file` property contains file metadata fields. - -##### File statuses - -| Number | Description | -| ------ | ----------------------------------------------------------------- | -| 1 | Request for upload to Apillon storage was generated. | -| 2 | File is uploaded to Apillon central server. | -| 3 | File is transferred to IPFS node. | -| 4 | File is replicated to different IPFS nodes through Crust Network. | - -##### File metadata - -`CID`, `size`, and `downloadLink` are present if file is already loaded to IPFS. - -| Field | Type | Description | -| ------------------------------------------------------------------------ | --------- | ---------------------------------------------------- | -| id | `integer` | Apillon internal file ID | -| status | `integer` | Apillon internal file status | -| fileUuid | `string` | File unique identifier | -| name | `string` | File name | -| contentType | `string` | File content type (MIME type) | -| [CID](https://docs.ipfs.tech/concepts/content-addressing/#what-is-a-cid) | `string` | File content identifier pointing to material in IPFS | -| size | `integer` | File size in bytes | -| downloadLink | `string` | File link on Apillon IPFS gateway | - -
-
-
- - - -```sh -curl --location --request GET "https://api.apillon.io/storage/:bucketUuid/file/:id/detail" \ ---header "Authorization: Basic :credentials" -``` - - - - - - -```json -{ - "id": "5be33c54-2cc9-46f4-8f50-debc98866810", - "status": 200, - "data": { - "fileStatus": 4, - "file": { - "id": 397, - "status": 5, - "fileUuid": "0a775bfa-a0d0-4e0b-9a1e-e909e426bd11", - "CID": "QmcG9r6Rdw9ZdJ4imGBWc6mi5VzWHQfkcLDMe2aP74eb42", - "name": "My file.txt", - "contentType": "text/plain", - "size": 68, - "fileStatus": 4, - "downloadLink": "https://ipfs.apillon.io/ipfs/QmcG9r6Rdw9ZdJ4imGBWc6mi5VzWHQfkcLDMe2aP74eb42" - } - } -} -``` - - - -
-
- -### Delete file - -> Marks a file inside bucket for deletion by `id`, `fileUuid`, or `CID`. File will be completely deleted from the Apillon system and Apillon IPFS node after 3 months. -> If file is marked for deletion, it will not be renewed on Crust Network. - -
DELETE /storage/:bucketUuid/file/:id
- -
-
- -#### URL parameters - -| Name | Description | required | -| ---------- | -------------------------------------------------------------- | -------- | -| bucketUuid | Unique key of bucket. Key is displayed on developer dashboard. | true | -| id | File internal ID, UUID, or CID. | true | - -#### Possible errors - -| Code | Description | -| -------- | ---------------------------- | -| 40406005 | File does not exist. | -| 40006009 | File is marked for deletion. | - -#### Response fields - -The response of delete function is a record that has been marked for deletion. - -Returned fields are the same as fields that are returned in [GET file details API](#file-metadata). - -**Note:** The `status` property of file is 8. This means the file is marked for deletion and will be deleted after a certain period. - -
-
-
- - - -```sh -curl --location --request DELETE "https://api.apillon.io/storage/:bucketUuid/file/:id" \ ---header "Authorization: Basic :credentials" \ ---data-raw "" -``` - - - - - - -```json -{ - "id": "bc92ff8d-05f2-4380-bb13-75a1b6b7f388", - "status": 200, - "data": { - "id": 397, - "status": 8, - "fileUuid": "0a775bfa-a0d0-4e0b-9a1e-e909e426bd11", - "CID": "QmcG9r6Rdw9ZdJ4imGBWc6mi5VzWHQfkcLDMe2aP74eb42", - "name": "My file.txt", - "contentType": "text/plain", - "size": 68, - "fileStatus": 4 - } -} -``` - - - -
-
- -## Web3 Hosting API +### Common errors -Hosting API provides endpoints, that can be used to implement [CI/CD](https://en.wikipedia.org/wiki/CI/CD). -To deploy page through Apillon API, follow below steps: +Through whole Apillon API, same errors can occur. Reason behind it can be current subscription package limits or current credit balance. -1. Upload website files to Apillon cloud server. +#### Not enough storage space -- Request URLs for files upload -- Upload files to cloud server -- Trigger transfer into website - -2. Execute deployment to staging or production environment. - -**Note:** To use Apillon Web3 Hosting APIs, you should first create a website on the [Apillon dashboard](https://app.apillon.io/dashboard/service/hosting). - -In all cURL examples, parameters with a colon as a prefix should be replaced with real values. - -### Get URLs for files upload - -> API that creates file upload requests and returns URLs for files upload. - -
POST /hosting/websites/:websiteUuid/upload
- -
-
- -#### URL parameters - -| Name | Description | Required | -| ----------- | ---------------------------------------------------------------------- | -------- | -| websiteUuid | Unique key of website bucket. Key is displayed on developer dashboard. | true | - -#### Body fields - -| Name | Type | Description | Required | -| ----- | ------- | ------------------------ | -------- | -| files | `array` | Array of files metadata. | true | - -Each file metadata object in `files` array, contain below properties. - -| Name | Type | Description | Required | -| ----------- | -------- | ---------------------------------------------------------------------------------------------------------- | -------- | -| fileName | `string` | Full name (name and extension) of file to be uploaded | true | -| contentType | `string` | File [MIME type](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types) | false | -| path | `string` | File path inside website. Empty for root. Must not contain `fileName`. | false | - -#### Possible errors - -| Code | Description | -| -------- | ----------------------------------------------------------- | -| 40406010 | Website does not exists | -| 42200040 | Request body is missing a `files` field. | -| 42200008 | Request body file object is missing a `fileName` field. | -| 40006002 | Website has reached max size limit. | -| 50006003 | Internal error - Apillon was unable to generate upload URL. | - -#### Response - -| Name | Type | Description | -| ----------- | -------- | ----------------------------------------------------------------------------------- | -| sessionUuid | `string` | Session unique key, which is later used to end upload and transfer files ti website | -| files | `array` | Array of files metadata. | - -Files in request body are returned in response `data.files` property. Each file is equipped with `url` and `fileUuid`. All properties are displayed below. - -| Field | Type | Description | -| ----------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| url | `string` | URL for file upload. Signed URL is unique for each file and is valid only for a limited time (1 min), so you should start with file upload as soon as possible.

Request should use `PUT` method and `binary` body.

Binary data should be sent in body as-is, but with the appropriate Content-Type header (e.g., text/plain). | -| fileUuid | `string` | File unique identifier used to query file status, etc. | -| fileName | `string` | Full name (name and extension) of file to be uploaded | -| contentType | `string` | File [MIME type](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types) | -| path | `string` | File path. | - -
-
-
- - - -```sh -curl --location --request POST "https://api.apillon.io/hosting/websites/:websiteUuid/upload" \ ---header "Authorization: Basic :credentials" \ ---header "Content-Type: application/json" \ ---data-raw "{ - \"files\": [ - { - \"fileName\": \"index.html\", - \"contentType\": \"text/html\" - }, - { - \"fileName\": \"styles.css\", - \"contentType\": \"text/css\", - \"path\": \"assets/\" - } - - ] - -}" -``` - - - - - +One of the limits, which is based on project subscription package, is available storage space (on IPFS node). +If project reach storage space limit, below error will occur. ```json { - "id": "7dd011ec-20e2-4c28-b585-da6c6f7fce8d", - "status": 201, - "data": { - "sessionUuid": "29ef6ca2-b171-440c-b934-db8aa88c3424", - "files": [ - { - "path": null, - "fileName": "index.html", - "contentType": "text/html", - "url": "https://sync-to-ipfs-queue.s3.eu-west-1.amazonaws.com/HOSTING_sessions/70/29ef6ca2-b171-440c-b934-db8aa88c3424/index.html?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIAQIMRRA6GJRL57L7G%2F20230215%2Feu-west-1%2Fs3%2Faws4_request&X-Amz-Date=20230215T105030Z&X-Amz-Expires=900&X-Amz-Signature=187035d2307bc089101eff3abbdd7baa3e8691b4d5d3bafa5aebb87e589e8c0c&X-Amz-SignedHeaders=host&x-id=PutObject", - "fileUuid": "e17436a1-5292-4380-ad91-eaac02a862b1" - }, - { - "path": "assets/", - "fileName": "styles.css", - "contentType": "text/css", - "url": "https://sync-to-ipfs-queue.s3.eu-west-1.amazonaws.com/HOSTING_sessions/70/29ef6ca2-b171-440c-b934-db8aa88c3424/assets/styles.css?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIAQIMRRA6GJRL57L7G%2F20230215%2Feu-west-1%2Fs3%2Faws4_request&X-Amz-Date=20230215T105030Z&X-Amz-Expires=900&X-Amz-Signature=f91b03a951fe3f99291802306be3e79812ca64e39effbb7dea1c19bb7cd1e42b&X-Amz-SignedHeaders=host&x-id=PutObject", - "fileUuid": "358c2942-4ced-421e-9a6f-edbf94c55dff" - } - ] - } + ... + "code": 40006003, + "message": "NOT_ENOUGH_STORAGE_SPACE", + ... } ``` -**Example for uploading to signed URL:** - - - - - - - -```sh -curl --location --request PUT "https://sync-to-ipfs-queue.s3.eu-west-1.amazonaws.com/HOSTING_sessions/70/29ef6ca2-b171-440c-b934-db8aa88c3424/index.html?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIAQIMRRA6GJRL57L7G%2F20230215%2Feu-west-1%2Fs3%2Faws4_request&X-Amz-Date=20230215T105030Z&X-Amz-Expires=900&X-Amz-Signature=187035d2307bc089101eff3abbdd7baa3e8691b4d5d3bafa5aebb87e589e8c0c&X-Amz-SignedHeaders=host&x-id=PutObject" \ ---header "Content-Type: text/plain" \ ---data-raw "

-Welcome to my awesome website -

" -``` - -
- - -```sh -curl --location --request PUT "https://sync-to-ipfs-queue.s3.eu-west-1.amazonaws.com/HOSTING_sessions/70/29ef6ca2-b171-440c-b934-db8aa88c3424/index.html?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIAQIMRRA6GJRL57L7G%2F20230215%2Feu-west-1%2Fs3%2Faws4_request&X-Amz-Date=20230215T105030Z&X-Amz-Expires=900&X-Amz-Signature=187035d2307bc089101eff3abbdd7baa3e8691b4d5d3bafa5aebb87e589e8c0c&X-Amz-SignedHeaders=host&x-id=PutObject" \ ---header "Content-Type: text/plain" \ ---data-binary ":full path to file" -``` - - -
- -
-
- -### End upload session - -> Transfer files to website bucket, which is used as source for deploy to staging(preview) environment. - -
POST /hosting/websites/:websiteUuid/upload/:sessionUuid/end
+#### Credit balance too low -
-
- -#### URL parameters - -| Name | Description | Required | -| ----------- | ------------------------------------------------------------------------------------- | -------- | -| websiteUuid | Unique key of website. Key is displayed in developer dashboard. | true | -| sessionUuid | Session uuid, recieved in [get URL for upload request](#post-storagebucketuuidupload) | true | - -#### Possible errors - -| Code | Description | -| -------- | ---------------------------------------------- | -| 40406004 | Session does not exists | -| 40006001 | Files in this session were already transferred | - -#### Response - -Api respond with status `200 OK` , if operation is successfully executed. - -
-
-
- - - -```sh -curl --location --request POST "https://api.apillon.io/hosting/websites/:websiteUuid/upload/:sessionUuid/end" \ ---header "Authorization: Basic :credentials" \ ---header "Content-Type: application/json" \ ---data-raw "{ - \"directSync\": true -}" -``` - - - - - +Some non recurrent actions requires payment with credit. +If project credit balance is lower than price for executed action, API will return status 402 and below response. ```json { - "id": "b64b1c07-1a8a-4b05-9e3b-3c6a519d6ff7", - "status": 200, - "data": true + ... + "code": 40210000, + "message": "CREDIT_BALANCE_TOO_LOW", + ... } ``` - - - -
-
- -### Deploy website - -> Endpoint to trigger website deployment into specific environment. - -
POST /hosting/websites/:websiteUuid/deploy
- -
-
- -#### URL parameters - -| Name | Description | Required | -| ----------- | ----------------------------------------------------------- | -------- | -| websiteUuid | Website UUID, visible in developer console website overview | true | - -#### Body fields - -| Name | Type | Description | Required | -| ----------- | -------- | ------------------------------------------------- | -------- | -| environment | `number` | Possible `environment` values are explained below | true | - -##### Environments - -| Status | Description | -| ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| 1 | Uploaded files are deployed to staging environment. Website will be available through staging IPNS link | -| 2 | Files from current staging environment are deployed to production environment. Website is pinned to CRUST, replicated and available through production IPNS link | -| 3 | Same as `2`, only that the source are uploaded files, not files in staging environment. | - -#### Possible errors - -| Code | Description | -| -------- | ----------------------------------------------- | -| 42200039 | Request body is missing an `environment` field. | -| 40406010 | Website does not exists | -| 40006016 | There are no files to deploy. | -| 40006017 | There are no changes to deploy. | - -#### Response - -Endpoint triggers deployment of website to specific environment. As result, deployment record with below field is returned. -This deployment is now waiting to be processed. - -**Note:** Deployment is processed in background, which may take several minutes. -When deploying to `staging` environment, files are added to IPFS and wrapped to directory, which is then accessible in IPFS via IPNS or CID. -In `production`, this CID is pinned to CRUST and replicated to other nodes. - -| Field | Type | Description | -| ---------------- | -------- | --------------------------------------------------------------------------------------------- | -| id | `number` | Deployment internal number | -| status | `number` | Deployment record status | -| bucketId | `number` | Internal ID of bucket, which contain files for this environment | -| environment | `number` | Environment to where website will be deployed | -| deploymentStatus | `number` | Current status of deployment. Possible values are listed below. | -| cid | `string` | When deployment is successful, CID points to directory on IPFS, where this page is accessible | -| size | `number` | Size of website | -| number | `number` | Deployment serial number - for this environment | - -Deployment goes through different stages and each stage updates `deploymentStatus`. Possible deployment statuses: - -| Status | Description | -| ------ | --------------------- | -| 0 | Deployment initiated | -| 1 | In processing | -| 10 | Deployment successful | -| 100 | Deployment failed | - -
-
-
- - - -```sh -curl --location --request POST "https://api.apillon.io/hosting/websites/:websiteUuid/deploy" \ ---header "Authorization: Basic :credentials" \ ---header "Content-Type: application/json" \ ---data-raw "{ - \"environment\": 1 -}" -``` - - - - - - -```json -{ - "id": "32eff81a-6b0b-4a92-a5cb-e5cebf6d6c28", - "status": 200, - "data": { - "id": 51, - "status": 5, - "websiteId": 4, - "bucketId": 62, - "environment": 1, - "deploymentStatus": 0, - "cid": null, - "size": null, - "number": 11 - } -} -``` - - - -
-
- -### Get deployment - -> Endpoint to get deployment. - -
GET /hosting/websites/:websiteUuid/deployments/:deploymentId
- -
-
- -#### URL parameters - -| Name | Description | Required | -| ------------ | ------------------------------------------------------------------- | -------- | -| websiteUuid | Website UUID, visible in developer console website overview | true | -| deploymentId | Deployment internal number, returned from `deploy` website endpoint | true | - -#### Possible errors - -| Code | Description | -| -------- | -------------------------- | -| 40406011 | Deployment does not exists | - -#### Response fields - -| Field | Type | Description | -| ---------------- | -------- | --------------------------------------------------------------------------------------------- | -| id | `number` | Deployment internal number | -| status | `number` | Deployment DB status | -| bucketId | `number` | Internal ID of bucket, which contain files for this environment | -| environment | `number` | Environment to where website will be deployed | -| deploymentStatus | `number` | Current status of deployment | -| cid | `string` | When deployment is successful, CID points to directory on IPFS, where this page is accessible | -| size | `number` | Size of website | -| number | `number` | Deployment serial number - for this environment | - -Deployment goes through different stages and each stage updates `deploymentStatus`. Possible deployment statuses: - -| Status | Description | -| ------ | --------------------- | -| 0 | Deployment initiated | -| 1 | In processing | -| 10 | Deployment successful | -| 100 | Deployment failed | - -
-
-
- - - -```sh -curl --location --request GET "https://api.apillon.io/hosting/websites/:websiteUuid/deployments/:deploymentId" \ ---header "Authorization: Basic :credentials" -``` - - - - - - -```json -{ - "id": "2d7d1b0c-15b1-4816-9aec-857182c7b617", - "status": 200, - "data": { - "id": 51, - "status": 5, - "bucketId": 62, - "environment": 1, - "deploymentStatus": 10, - "cid": "QmY3KF4F6Ap5HbrwWpq8dTVaR65Cd674jYXKBayNynDASJ", - "size": 289, - "number": 11 - } -} -``` - - - -
-
- -### Get website - -> Endpoint to get website. Endpoint returns basic website data, along with IPNS links. - -
GET /hosting/websites/:websiteUuid
- -
-
- -#### URL parameters - -| Name | Description | Required | -| ----------- | ----------------------------------------------------------- | -------- | -| websiteUuid | Website UUID, visible in developer console website overview | true | - -#### Possible errors - -| Code | Description | -| -------- | ----------------------- | -| 40406010 | Website does not exists | - -#### Response fields - -| Field | Type | Description | -| ------------------ | -------- | ----------------------------------------------------------- | -| id | `number` | Website id | -| status | `number` | Website DB status | -| name | `string` | Website name | -| description | `string` | Website description | -| domain | `string` | Domain for production environment | -| bucketUuid | `string` | UUID of bucket, for file upload | -| ipnsStagingLink | `string` | IPNS address of staging version, on Apillon IPFS gateway | -| ipnsProductionLink | `string` | IPNS address of production version, on Apillon IPFS gateway | - -
-
-
- - - -```sh -curl --location --request GET "https://api.apillon.io/hosting/websites/:websiteUuid" \ ---header "Authorization: Basic :credentials" -``` - - - - - - -```json -{ - "id": "0eb223ce-51c0-4a9b-96ce-331a1cd99603", - "status": 200, - "data": { - "id": 4, - "status": 5, - "name": "My test page", - "description": null, - "domain": "", - "bucketUuid": "57aef0fc-84cb-4564-9af2-0f7bfc0ef729", - "ipnsStagingLink": "https://ipfs.apillon.io/ipns/k2k4r8p6fvcyq5qogaqdtvmqn5vyvyy3khut1llkrz13ls16ocp4gojx", - "ipnsProductionLink": "https://ipfs.apillon.io/ipns/k2k4r8ng8nqexubrmbwnhsuu1d6n4ebgnxsbdcu9gxk8uv3l67098hge" - } -} -``` - - - -
-
- - - -## Web3 NFTs API - -API is for creating and managing NFTs. To prepare images and metadata you can use storage API. To learn more about metadata standards you can visit: https://docs.opensea.io/docs/metadata-standards - -### Get NFT Collection - -> Get NFT collection by UUID - -#### GET /nfts/collections/:uuid - -
-
- -#### URL parameters - -| Name | Description | Required | -|-------|--------------------------------------------------------------------| -------- | -| uuid | Unique key of collection. Key is displayed in developer dashboard. | true | - -#### Possible errors - -| Code | Description | -| -------- |-----------------------------------| -| 40300000 | Not allowed to access collection. | -| 50012009 | Collection does not exist. | - -#### Response Fields - -| Name | Type | Description | -|------------------|-------------|----------------------------------------------------------------------------------------------------------| -| createTime | `DateTime` | Collection create time. | -| updateTime | `DateTime` | Collection last update time. | -| collectionType | `number` | Type of smart contract to use for collection. Available types are described [here](#collection-types). | -| collectionUuid | `string` | Unique key of a collection. | -| symbol | `string` | NFT collection symbol (usually 3-4 characters long). | -| name | `string` | NFT collection name. | -| description | `string` | NFT collection description. | -| maxSupply | `number` | Maximal number of NFTs ever in existence (0 stands for unlimited). | -| bucketUuid | `string` | UUID of the bucket where metadata is stored. | -| baseUri | `string` | Base URI for collection metadata (token id and file extension is appended to it). | -| baseExtension | `string` | File extension that is auto appended after token id to form a full URL. | -| isSoulbound | `boolean` | Soul bound tokens are NFTs that are bounded to wallet and not transferable. | -| isRevokable | `boolean` | For revocable collection owner can destroy NFTs at any time. | -| royaltiesFees | `number` | Percentage (between 0 and 100) of each NFT sale sent to wallet specified under royalties address. | -| royaltiesAddress | `string` | Address where royalties are sent to. | -| collectionStatus | `number` | Apillon internal/database collection status. | -| contractAddress | `string` | Smart address of contract for deployed collection. | -| transactionHash | `string` | Deployment transaction hash/id. | -| deployerAddress | `string` | Wallet address of deployer. | -| chain | `number` | Blockchain id on which you want to release your collection. | -| drop | `boolean` | Determines if collection is mintable by public. | -| dropStart | `number` | UNIX timestamp which determines public mint opening date and time. | -| dropPrice | `number` | Price of NFT at mint stage in token that is used on `chain`. | -| dropReserve | `number` | Amount of NFTs reserved by owner. | - -
-
- - - - -```sh -curl --location 'https://api.apillon.io/nfts/collections/:uuid' \ ---header 'Authorization: Basic :credentials' -``` - - - - - - -```json -{ - "id": "b5935c73-204d-4365-9f9a-6a1792adab5b", - "status": 200, - "data": { - "createTime": "2023-06-13T10:15:58.000Z", - "updateTime": "2023-06-13T10:15:58.000Z", - "collectionType": 1, - "collectionUuid": "d6355fd3-640d-4803-a4d9-79d875abcb5a", - "symbol": "NFT", - "name": "NFT Collection", - "description": "NFT Collection Description", - "maxSupply": 1000, - "bucketUuid": "a9425ff7-4802-4a38-b771-84a790112c30", - "baseUri": "https://ipfs.apillon.io/metadata/", - "baseExtension": ".json", - "isSoulbound": false, - "isRevokable": true, - "royaltiesFees": 0.1, - "royaltiesAddress": "0x4156edbafc5091507de2dd2a53ded551a346f83b", - "collectionStatus": 0, - "contractAddress": "0x452101C96A1Cf2cBDfa5BB5353e4a7F235241557", - "transactionHash": "0x6b97424de3367cd0335b08265787b83053b62bee2d1c8bec1f776936bea4fb26", - "deployerAddress": "0x4156edbafc5091507de2dd2a53ded551a346f83b", - "chain": 1287, - "drop": true, - "dropStart": 1687251003, - "dropPrice": 0.1, - "dropReserve": 5 - } -} -``` - - - -
-
- - -##### Collection Type - -| Number | Description | -|--------|--------------------------| -| 0 | Generic NFT collection. | -| 1 | Nestable NFT collection. | - -##### Collection Statuses - -| Number | Description | -|--------|------------------------------------------| -| 0 | Collection was created. | -| 1 | Deploying collection was initiated. | -| 2 | Collection is being deployed. | -| 3 | Collection was deployed successfully. | -| 4 | Collection was transferred successfully. | -| 5 | Failed deploying collection. | - - -### List NFT Collections - -> List NFT collections. Items are paginated and can be filtered and ordered through query parameters. - -#### GET /nfts/collections - -
-
- -#### Query parameters - -| Name | Description | Required | -|------------------|-------------------------------------------------------------------------------------------------------|----------| -| collectionStatus | Collection status. Find available statuses [here](#collection-statuses). | false | -| search | Search by collection name. | false | -| page | Collections are paginated by default. This parameter is used to get collections from a specific page. | false | -| limit | Number of files on a page (default: 20). | false | -| orderBy | One or multiple properties, separated by a comma, used to order data. | false | -| desc | `Boolean` values, mapped to the index of the `orderBy` parameter. Defaults to false. | false | - -#### Response -Response is a list of items described [under Response Fields above](#get-nft-collection). - -
-
- - - - -```sh -curl --location 'https://api.apillon.io/nfts/collections' \ ---header 'Authorization: Basic :credentials' -``` - - - - - - -```json -{ - "id": "b5935c73-204d-4365-9f9a-6a1792adab5b", - "status": 200, - "data": { - "items": [ - { - "createTime": "2023-06-13T10:15:58.000Z", - "updateTime": "2023-06-13T10:15:58.000Z", - "collectionType": 1, - "collectionUuid": "d6355fd3-640d-4803-a4d9-79d875abcb5a", - "symbol": "NFT", - "name": "NFT Collection", - "description": "NFT Collection Description", - "maxSupply": 1000, - "bucketUuid": "a9425ff7-4802-4a38-b771-84a790112c30", - "baseUri": "https://ipfs.apillon.io/metadata/", - "baseExtension": ".json", - "isSoulbound": false, - "isRevokable": true, - "royaltiesFees": 0.1, - "royaltiesAddress": "0x4156edbafc5091507de2dd2a53ded551a346f83b", - "collectionStatus": 0, - "contractAddress": "0x452101C96A1Cf2cBDfa5BB5353e4a7F235241557", - "transactionHash": "0x6b97424de3367cd0335b08265787b83053b62bee2d1c8bec1f776936bea4fb26", - "deployerAddress": "0x4156edbafc5091507de2dd2a53ded551a346f83b", - "chain": 1287, - "drop": true, - "dropStart": 1687251003, - "dropPrice": 0.1, - "dropReserve": 5 - } - ], - "total": 1 - } -} -``` - - - -
-
- - -### List Collection Transactions - -> List NFT collections. Items are paginated and can be filtered and ordered through query parameters. - -#### GET /nfts/collections/:uuid/transactions - -
-
- -#### URL parameters - -| Name | Description | Required | -|-------|--------------------------------------------------------------------| -------- | -| uuid | Unique key of collection. Key is displayed in developer dashboard. | true | - -#### Query parameters - -| Name | Description | Required | -|-------------------|---------------------------------------------------------------------------------------------------------|----------| -| transactionStatus | Transaction status. | false | -| transactionType | Transaction type. | false | -| search | Search by transaction hash. | false | -| page | Transactions are paginated by default. This parameter is used to get transactions from a specific page. | false | -| limit | Number of transactions on a page (default: 20). | false | -| orderBy | One or multiple properties, separated by a comma, used to order data. | false | -| desc | `Boolean` values, mapped to the index of the `orderBy` parameter. Defaults to false. | false | - -#### Response Fields - -| Name | Type | Description | -|-------------------|-------------|-------------------------------------------------------------| -| chainId | `number` | Blockchain id on which you want to release your collection. | -| transactionType | `number` | Transaction type. | -| transactionStatus | `number` | Transaction status | -| transactionHash | `number` | Transaction hash/id. | -| updateTime | `DateTime` | Transaction last update time. | -| createTime | `DateTime` | Transaction create time. | - -
-
- - - - -```sh -curl --location 'https://api.apillon.io/nfts/collections/:uuid/transactions' \ ---header 'Authorization: Basic :credentials' -``` - - - - - - -```json -{ - "id": "b5935c73-204d-4365-9f9a-6a1792adab5b", - "status": 200, - "data": { - "items": [ - { - "chainId": 1287, - "transactionType": 1, - "transactionStatus": 1, - "transactionHash": "0xb988c8cda7ec8b441611b208360e0aace9c294e1ca5672375b21e815890a54d1", - "updateTime": "2023-06-13T10:15:58.000Z", - "createTime": "2023-06-13T10:15:58.000Z" - } - ], - "total": 1 - } -} -``` - - - -
-
- -##### Transaction Types - -| Number | Description | -|--------|-----------------------------| -| 1 | Deploy Contract | -| 2 | Transfer Contract Ownership | -| 3 | Mint NFT | -| 4 | Set Collection Base URI | -| 5 | Burn NFT | -| 6 | Nest mint NFT | - -##### Transaction Status - -| Number | Description | -|--------|-------------| -| 1 | Pending | -| 2 | Confirmed | -| 3 | Failed | -| 4 | Error | - - - -### Create NFT Collection - -> API endpoint that creates NFT collection and deploys it on selected network. - -Collection can be created with a few features/functionalities: - -- drop: collection can be minted/purchased by users -- revokable: NFTs can be revoked by collection owner who can burn them -- soulbound: NFTs are bound to wallet address and can't be transferred -- royalties: owner can enable royalties to earn specified percentage per each NFT trade - -2 types of collections are supported: -1. Generic collection (based on [OpenZeppelins ERC-721](https://docs.openzeppelin.com/contracts/3.x/erc721) NFT standard) -2. Nestable collection which allows nesting NFTs under each other (based on [RMRKs ERC-7401](https://evm.rmrk.app/general-overview/rmrk-legos/nestable) NFT standard) - -#### POST /nfts/collections - -
-
- -#### Body fields - -| Name | Type | Description | Required | -|------------------|-----------|------------------------------------------------------------------------------------------|----------| -| collectionType | `number` | Type of smart contract to use when deploying collection (1 for generic, 2 for nestable). | true | -| chain | `number` | Blockchain id on which you want to release your collection. | true | -| symbol | `string` | NFT collection symbol (usually 3-4 characters long). | true | -| name | `string` | NFT collection name. | true | -| description | `string` | NFT collection description. | false | -| maxSupply | `number` | Maximal number of NFTs ever in existence (0 stands for unlimited). | true | -| baseUri | `string` | Base URI for collection metadata (token id and file extension is appended to it). | true | -| baseExtension | `string` | File extension that is auto appended after token id to form a full URL. | true | -| isRevokable | `boolean` | For revocable collection owner can destroy NFTs at any time. | true | -| isSoulbound | `boolean` | Soul bound tokens are NFTs that are bound to wallet and not transferable. | true | -| royaltiesAddress | `string` | Address where royalties are sent to. | true | -| royaltiesFees | `number` | Percentage of royalties earned per each NFT trade. | true | -| drop | `boolean` | Determines if collection is mintable by public. | true | -| dropStart* | `number` | UNIX timestamp (in seconds) which determines public mint opening date and time. | true | -| dropPrice* | `number` | Price of NFT at mint stage. | true | -| dropReserve* | `number` | Amount of NFTs reserved by owner. | true | - - -**Notes:** - -*`dropStart`, `dropPrice` and `dropReserve` are only used if `drop` is set to boolean `true`. - -#### Possible errors -Beside validation errors (with 422 http status code) these are the error codes may be returned: - -| Code | Description | -| -------- |-----------------------------------------------| -| 40012002 | Collection quota reached | -| 50012003 | Failed deploying NFT contract on chain. | -| 50012010 | Failed to create bucket for storing metadata. | - - -#### Response -Response payload is described [under Response Fields above](#get-nft-collection). - -
-
- - - - -```sh -curl --location 'https://api.apillon.io/nfts/collections' \ ---header 'Content-Type: application/json' \ ---header 'Authorization: Basic :credentials' \ ---data '{ - "collectionType": 1, - "chain": 1287, - "symbol": "NFT", - "name": "NFT Collection", - "description": "NFT Collection description", - "maxSupply": 1000, - "baseUri": "https://ipfs.apillon.io/metadata/", - "baseExtension": "json", - "isRevokable": true, - "isSoulbound": false, - "royaltiesAddress": "0x4156edbafc5091507de2dd2a53ded551a346f83b", - "royaltiesFees": 10, - "drop": true, - "dropStart": 1687251003, - "dropReserve": 5, - "dropPrice": 0.1 -}' -``` - - - - - - -```json -{ - "id": "b5935c73-204d-4365-9f9a-6a1792adab5b", - "status": 200, - "data": { - "createTime": "2023-06-13T10:15:58.000Z", - "updateTime": "2023-06-13T10:15:58.000Z", - "collectionType": 1, - "collectionUuid": "d6355fd3-640d-4803-a4d9-79d875abcb5a", - "symbol": "NFT", - "name": "NFT Collection", - "description": "NFT Collection Description", - "maxSupply": 1000, - "bucketUuid": "a9425ff7-4802-4a38-b771-84a790112c30", - "baseUri": "https://ipfs.apillon.io/metadata/", - "baseExtension": ".json", - "isSoulbound": false, - "isRevokable": true, - "royaltiesFees": 0.1, - "royaltiesAddress": "0x4156edbafc5091507de2dd2a53ded551a346f83b", - "collectionStatus": 0, - "contractAddress": "0x452101C96A1Cf2cBDfa5BB5353e4a7F235241557", - "transactionHash": "0x6b97424de3367cd0335b08265787b83053b62bee2d1c8bec1f776936bea4fb26", - "deployerAddress": "0x4156edbafc5091507de2dd2a53ded551a346f83b", - "chain": 1287, - "drop": true, - "dropStart": 1687251003, - "dropPrice": 0.1, - "dropReserve": 5 - } -} -``` - - -
-
- - -### Transfer Collection - -> Transfer collection ownership from a wallet owned by caller to a new wallet address. - -#### POST /nfts/collections/:uuid/transfer - -
-
- -#### URL parameters - -| Name | Description | Required | -|-------|--------------------------------------------------------------------| -------- | -| uuid | Unique key of collection. Key is displayed in developer dashboard. | true | - -#### Body fields - -| Name | Type | Description | Required | -|---------|----------|--------------------------------| -------- | -| address | `string` | Wallet address of a new owner. | true | - -#### Possible errors -Beside validation errors (with 422 http status code) these are the error codes may be returned: - -| Code | Description | -| -------- |-------------------------------------------------------------------------------------| -| 40012003 | Contract can't be transferred to wallet address that already owns this collection. | -| 40012004 | Transfer transaction already exists. | -| 40300000 | Not allowed to access collection | -| 50012002 | Collection doesn't exist, wasn't deployed or was already transferred. | -| 50012004 | Collection transfer failed. | - -#### Response - -Response payload is described [under Response Fields above](#get-nft-collection). - -
-
- - - - -```sh -curl --location 'https://api.apillon.io/nfts/collections/:uuid/transfer' \ ---header 'Content-Type: application/json' \ ---header 'Authorization: Basic :credentials' \ ---data '{"address": "0x452101C96A1Cf2cBDfa5BB5353e4a7F235241551"}' -``` - - - - - - -```json -{ - "id": "b5935c73-204d-4365-9f9a-6a1792adab5b", - "status": 200, - "data": { - "createTime": "2023-06-13T10:15:58.000Z", - "updateTime": "2023-06-13T10:15:58.000Z", - "collectionType": 1, - "collectionUuid": "d6355fd3-640d-4803-a4d9-79d875abcb5a", - "symbol": "NFT", - "name": "NFT Collection", - "description": "NFT Collection Description", - "maxSupply": 1000, - "bucketUuid": "a9425ff7-4802-4a38-b771-84a790112c30", - "baseUri": "https://ipfs.apillon.io/metadata/", - "baseExtension": ".json", - "isSoulbound": false, - "isRevokable": true, - "royaltiesFees": 0.1, - "royaltiesAddress": "0x4156edbafc5091507de2dd2a53ded551a346f83b", - "collectionStatus": 0, - "contractAddress": "0x452101C96A1Cf2cBDfa5BB5353e4a7F235241557", - "transactionHash": "0x6b97424de3367cd0335b08265787b83053b62bee2d1c8bec1f776936bea4fb26", - "deployerAddress": "0x4156edbafc5091507de2dd2a53ded551a346f83b", - "chain": 1287, - "drop": true, - "dropStart": 1687251003, - "dropPrice": 0.1, - "dropReserve": 5 - } -} -``` - - - -
-
- - -### Mint Collection NFTs - -> Mint specified amount of NFTs to a wallet address provided in request. - -**Note:** if the collection is set as `drop` this endpoint can only mint reserved NFTs. - -#### POST /nfts/collections/:uuid/mint - -
-
- -#### URL parameters - -| Name | Description | Required | -|-------|--------------------------------------------------------------------| -------- | -| uuid | Unique key of collection. Key is displayed in developer dashboard. | true | - -#### Body fields - -| Name | Type | Description | Required | -|------------------|----------|---------------------------------| -------- | -| receivingAddress | `string` | Wallet address of NFT receiver. | true | -| quantity | `number` | Number of NFTs to mint. | true | - - -#### Possible errors -Beside validation errors (with 422 http status code) these are the error codes may be returned: - -| Code | Description | -| -------- |--------------------------------------------------------------------------| -| 40300000 | Not allowed to access collection. | -| 50012002 | Collection doesn't exist, wasn't deployed or was already transferred. | -| 50012005 | Error minting NFT. | -| 50012007 | Total number of minted NFTs would exceed max supply for this collection. | -| 50012008 | All of the reserved NFTs were already minted. | - -#### Response Fields - -| Field | Type | Description | -| ---------------- |-----------|-------------------| -| success | `boolean` | Status of action. | - -
-
- - - - -```sh -curl --location 'https://api.apillon.io/nfts/collections/:uuid/mint' \ ---header 'Content-Type: application/json' \ ---header 'Authorization: Basic :credentials' \ ---data '{"receivingAddress": "0x452101C96A1Cf2cBDfa5BB5353e4a7F235241557", "quantity": 1}' -``` - - - - - - -```json -{ - "id": "b5935c73-204d-4365-9f9a-6a1792adab5b", - "status": 200, - "data": { - "success": true - } -} -``` - - - -
-
- - -### Nest Mint Collection NFTs - -> Nest mint specified amount of NFTs under a parent NFT defined by the parent collection UUID and token id. - -#### POST /nfts/collections/:uuid/nest-mint - -
-
- -#### URL parameters - -| Name | Description | Required | -|-------|--------------------------------------------------| -------- | -| uuid | Unique key of (child) collection we are minting. | true | - -#### Body fields - -| Name | Type | Description | Required | -|----------------------|----------|---------------------------------------------------| -------- | -| parentCollectionUuid | `string` | Collection UUID of NFT receiving nest-minted NFT. | true | -| parentNftId | `number` | Token id of NFT receiving nest-minted NFT. | true | -| quantity | `number` | Number of NFTs to nest-mint. | true | - - -#### Possible errors -Beside validation errors (with 422 http status code) these are the error codes may be returned: - -| Code | Description | -| -------- |--------------------------------------------------------------------------| -| 40300000 | Not allowed to access collection. | -| 50012002 | Collection doesn't exist, wasn't deployed or was already transferred. | -| 50012007 | Total number of minted NFTs would exceed max supply for this collection. | -| 50012008 | All of the reserved NFTs were already minted. | -| 50012013 | Parrent collection doesn't support nesting. | -| 50012014 | Parrent and child collection chain missmatch. | - -#### Response Fields - -| Field | Type | Description | -| ---------------- |-----------|-------------------| -| success | `boolean` | Status of action. | - -
-
- - - - -```sh -curl --location 'https://api.apillon.io/nfts/collections/:uuid/next-mint' \ ---header 'Content-Type: application/json' \ ---header 'Authorization: Basic :credentials' \ ---data '{"parentCollectionUuid": "d6355fd3-640d-4803-a4d9-79d875abcb5a", "parentNftId": 1, "quantity": 1}' -``` - - - - - - -```json -{ - "id": "b5935c73-204d-4365-9f9a-6a1792adab5b", - "status": 200, - "data": { - "success": true - } -} -``` - - - -
-
- - -### Burn Collection NFT - -> Burn specific NFT belonging to collection specified. - -**Note:** burning NFTs is only available if `isRevokable` is enabled on collection. - -#### POST /nfts/collections/:uuid/burn - -
-
- -#### URL parameters - -| Name | Description | Required | -|-------|--------------------------------------------------------------------| -------- | -| uuid | Unique key of collection. Key is displayed in developer dashboard. | true | - -#### Body fields - -| Name | Type | Description | Required | -|----------|----------|--------------------------------------------| -------- | -| tokenId | `number` | Non fungible token id that we are burning. | true | - -#### Possible errors -Beside validation errors (with 422 http status code) these are the error codes may be returned: - -| Code | Description | -| -------- |-----------------------------------------------------------------------| -| 40300000 | Not allowed to access collection. | -| 50012002 | Collection doesn't exist, wasn't deployed or was already transferred. | -| 50012012 | Burning NFT failed. | - -#### Response fields - -| Field | Type | Description | -| ---------------- |-----------|-------------------| -| success | `boolean` | Status of action. | - -
-
- - - - -```sh -curl --location 'https://api.apillon.io/nfts/collections/:uuid/burn' \ ---header 'Content-Type: application/json' \ ---header 'Authorization: Basic :credentials' \ ---data '{"tokenId": 1}' -``` - - - - - - -```json -{ - "id": "b5935c73-204d-4365-9f9a-6a1792adab5b", - "status": 200, - "data": { - "status": true - } -} -``` - - - -
-
diff --git a/build/4-storage-api.md b/build/4-storage-api.md new file mode 100644 index 00000000..a044ba3c --- /dev/null +++ b/build/4-storage-api.md @@ -0,0 +1,720 @@ +# Storage API + +In all cURL examples, parameters with a colon as a prefix should be replaced with real values. + +**File upload process through Apillon Web3 Storage API** + +1. Request signed URL(s) for upload. +2. File is uploaded to Apillon central server. +3. File is transferred to IPFS and available through the Apillon gateway. +4. File is replicated to different IPFS nodes globally via Crust Network. + +### List buckets + +> API to list all buckets in project. Items are paginated and can be filtered and ordered through query parameters. + +#### GET /storage/buckets + +
+
+ +#### Query parameters + +| Name | Description | Required | +| ------- | ------------------------------------------------------------------------------------------------- | -------- | +| search | Search by bucket name. | false | +| page | Buckets are paginated by default. This parameter is used to get collections from a specific page. | false | +| limit | Number of items on a page (default: 20). | false | +| orderBy | One or multiple properties, separated by a comma, used to order data. | false | +| desc | `Boolean` values, mapped to the index of the `orderBy` parameter. Defaults to false. | false | + +#### Response fields + +The `Data` property of API response contains two properties: `items` (records that match the current query) and `total` (number of all records. This information should be used for pagination: Round up (`total` / `limit`) = number of pages. + +Each item is an instance of bucket DTO, with below properties: + +| Field | Type | Description | +| ----------- | ---------- | ------------------------------------------------------------------------------------------- | +| createTime | `DateTime` | Item create time | +| updateTime | `DateTime` | Item last update time | +| bucketUuid | `string` | Bucket unique identifier | +| bucketType | `integer` | Item type with possible values `1`(storage bucket), `2`(website bucket) and `3`(nft bucket) | +| name | `string` | Bucket name | +| description | `string` | Bucket description | +| size | `integer` | Size of bucket | + +
+
+
+ + + +```sh +curl --location --request GET "https://api.apillon.io/storage/buckets" \ +--header "Authorization: Basic :credentials" +``` + + + + +```sh +curl --location --request GET "https://api.apillon.io/storage/buckets?search=My bucket" \ +--header "Authorization: Basic :credentials" +``` + + + + + + +```json +{ + "id": "75095bf9-e976-45c8-8a9d-e013ca3b203a", + "status": 200, + "data": { + "items": [ + ... + { + "createTime": "2022-12-06T12:03:32.000Z", + "updateTime": "2023-10-09T11:42:23.000Z", + "bucketUuid": "cee9f151-a371-495b-acd2-4362fbb87780", + "bucketType": 1, + "name": "Storage bucket", + "description": "", + "size": 3215839730 + } + ... + ], + "total": 10 + } +} +``` + + + +
+
+ +### Create new bucket + +> API for creating new storage bucket. NFT and website bucket are automatically generated, when new website or NFT collection is initialized. + +
POST /storage/buckets
+ +
+
+ +#### Body fields + +| Name | Type | Description | Required | +| ----------- | -------- | ------------------- | -------- | +| name | `string` | Bucket name. | true | +| description | `string` | Bucket description. | false | + +| Code | Description | +| -------- | --------------------------------------- | +| 42200003 | Request body is missing a `name` field. | + +#### Response + +Response is an instance of bucket DTO, described above. + +
+
+
+ + + +```sh +curl --location --request POST "https://api.apillon.io/storage/:bucketUuid/upload" \ +--header "Authorization: Basic :credentials" \ +--header "Content-Type: application/json" \ +--data-raw "{ + \"files\": [ + { + \"fileName\": \"My test file\", + \"contentType\": \"text/html\" + } + ] + +}" +``` + + + + + + +```json +{ + "id": "cbdc4930-2bbd-4b20-84fa-15daa4429952", + "status": 201, + "data": { + "sessionUuid": "3b6113bc-f265-4662-8cc5-ea86f06cc74b", + "files": [ + { + "path": null, + "fileName": "My test file", + "contentType": "text/html", + "url": "https://sync-to-ipfs-queue.s3.eu-west-1.amazonaws.com/STORAGE_sessions/73/3b6113bc-f265-4662-8cc5-ea86f06cc74b/My%20test%20file?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIAQIMRRA6GJRL57L7G%2F20230215%2Feu-west-1%2Fs3%2Faws4_request&X-Amz-Date=20230215T114524Z&X-Amz-Expires=900&X-Amz-Signature=499367f6c6bff5be50686724475ac2fa6307b77b94fd1a25584c092fe74b0a58&X-Amz-SignedHeaders=host&x-id=PutObject", + "fileUuid": "4ef1177b-f7c9-4434-be56-a559cec0cc18" + } + ] + } +} +``` + +**Example for uploading to signed URL:** + + + + + + + +```sh +curl --location --request PUT "https://sync-to-ipfs-queue.s3.eu-west-1.amazonaws.com/STORAGE_sessions/73/3b6113bc-f265-4662-8cc5-ea86f06cc74b/My%20test%20file?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIAQIMRRA6GJRL57L7G%2F20230215%2Feu-west-1%2Fs3%2Faws4_request&X-Amz-Date=20230215T114524Z&X-Amz-Expires=900&X-Amz-Signature=499367f6c6bff5be50686724475ac2fa6307b77b94fd1a25584c092fe74b0a58&X-Amz-SignedHeaders=host&x-id=PutObject" \ +--data-binary "My test content" +``` + + + + +```sh +curl --location --request PUT "https://sync-to-ipfs-queue.s3.eu-west-1.amazonaws.com/STORAGE_sessions/73/3b6113bc-f265-4662-8cc5-ea86f06cc74b/My%20test%20file?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIAQIMRRA6GJRL57L7G%2F20230215%2Feu-west-1%2Fs3%2Faws4_request&X-Amz-Date=20230215T114524Z&X-Amz-Expires=900&X-Amz-Signature=499367f6c6bff5be50686724475ac2fa6307b77b94fd1a25584c092fe74b0a58&X-Amz-SignedHeaders=host&x-id=PutObject" \ +--header "Content-Type: text/plain" \ +--data-binary ":full path to file" +``` + + + + +
+
+ +### Upload to bucket + +> API that creates file upload requests and returns URLs for file upload along with `sessionUuid`. + +
POST /storage/:bucketUuid/upload
+ +
+
+ +#### URL parameters + +| Name | Description | Required | +| ---------- | ---------------------------------------------------------------------- | -------- | +| bucketUuid | Unique key of storage bucket. Key is displayed on developer dashboard. | true | + +#### Body fields + +| Name | Type | Description | Required | +| ----- | ------- | ------------------------ | -------- | +| files | `array` | Array of files metadata. | true | + +Each file metadata object in `files` array, contain below properties. + +| Name | Type | Description | Required | +| ----------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | +| fileName | `string` | Full name (name and extension) of file to be uploaded | true | +| contentType | `string` | File [MIME type](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types) | false | +| path | `string` | Virtual file path. Empty for root. Must not contain `fileName`.

The `path` field can be used to place file in virtual directories inside a bucket. If directories do not yet exist, they will be automatically generated.

For example, an `images/icons` path creates `images` directory in a bucket and `icons` directory inside it. File will then be created in the `icons` directory. | false | + +#### Possible errors + +| Code | Description | +| -------- | ------------------------------------------------------------------------------ | +| 40406002 | Bucket does not exist. | +| 42200040 | Request body is missing a `files` field. | +| 42200008 | Request body file object is missing a `fileName` field. | +| 40006002 | Bucket has reached max size limit. | +| 40406009 | Bucket is marked for deletion. It is no longer possible to upload files to it. | +| 50006003 | Internal error - Apillon was unable to generate upload URL. | + +#### Response + +| Name | Type | Description | +| ----------- | -------- | ---------------------------------------------------------------------------------- | +| sessionUuid | `string` | Session unique key, which is later used to end upload and transfer files to bucket | +| files | `array` | Array of files metadata. | + +Files in request body are returned in response `data.files` property. Each file is equipped with `url` and `fileUuid`. All properties are displayed below. + +| Field | Type | Description | +| ----------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| url | `string` | URL for file upload. Signed URL is unique for each file and is valid only for a limited time (1 min), so you should start with file upload as soon as possible.

Request should use `PUT` method and `binary` body.

Binary data should be sent in body as-is, but with the appropriate Content-Type header (e.g., text/plain). | +| fileUuid | `string` | File unique identifier used to query file status, etc. | +| fileName | `string` | Full name (name and extension) of file to be uploaded | +| contentType | `string` | File [MIME type](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types) | +| path | `string` | File path. | + +
+
+
+ + + +```sh +curl --location --request POST "https://api.apillon.io/storage/:bucketUuid/upload" \ +--header "Authorization: Basic :credentials" \ +--header "Content-Type: application/json" \ +--data-raw "{ + \"files\": [ + { + \"fileName\": \"My test file\", + \"contentType\": \"text/html\" + } + ] + +}" +``` + + + + + + +```json +{ + "id": "cbdc4930-2bbd-4b20-84fa-15daa4429952", + "status": 201, + "data": { + "sessionUuid": "3b6113bc-f265-4662-8cc5-ea86f06cc74b", + "files": [ + { + "path": null, + "fileName": "My test file", + "contentType": "text/html", + "url": "https://sync-to-ipfs-queue.s3.eu-west-1.amazonaws.com/STORAGE_sessions/73/3b6113bc-f265-4662-8cc5-ea86f06cc74b/My%20test%20file?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIAQIMRRA6GJRL57L7G%2F20230215%2Feu-west-1%2Fs3%2Faws4_request&X-Amz-Date=20230215T114524Z&X-Amz-Expires=900&X-Amz-Signature=499367f6c6bff5be50686724475ac2fa6307b77b94fd1a25584c092fe74b0a58&X-Amz-SignedHeaders=host&x-id=PutObject", + "fileUuid": "4ef1177b-f7c9-4434-be56-a559cec0cc18" + } + ] + } +} +``` + +**Example for uploading to signed URL:** + + + + + + + +```sh +curl --location --request PUT "https://sync-to-ipfs-queue.s3.eu-west-1.amazonaws.com/STORAGE_sessions/73/3b6113bc-f265-4662-8cc5-ea86f06cc74b/My%20test%20file?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIAQIMRRA6GJRL57L7G%2F20230215%2Feu-west-1%2Fs3%2Faws4_request&X-Amz-Date=20230215T114524Z&X-Amz-Expires=900&X-Amz-Signature=499367f6c6bff5be50686724475ac2fa6307b77b94fd1a25584c092fe74b0a58&X-Amz-SignedHeaders=host&x-id=PutObject" \ +--data-binary "My test content" +``` + + + + +```sh +curl --location --request PUT "https://sync-to-ipfs-queue.s3.eu-west-1.amazonaws.com/STORAGE_sessions/73/3b6113bc-f265-4662-8cc5-ea86f06cc74b/My%20test%20file?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIAQIMRRA6GJRL57L7G%2F20230215%2Feu-west-1%2Fs3%2Faws4_request&X-Amz-Date=20230215T114524Z&X-Amz-Expires=900&X-Amz-Signature=499367f6c6bff5be50686724475ac2fa6307b77b94fd1a25584c092fe74b0a58&X-Amz-SignedHeaders=host&x-id=PutObject" \ +--header "Content-Type: text/plain" \ +--data-binary ":full path to file" +``` + + + + +
+
+ +### End upload session + +> Once files are uploaded to cloud server via received URL, trigger sync of files to IPFS and CRUST. + +
POST /storage/:bucketUuid/upload/:sessionUuid/end
+ +
+
+ +#### URL parameters + +| Name | Description | Required | +| ----------- | --------------------------------------------------------------- | -------- | +| bucketUuid | Unique key of bucket. Key is displayed in developer dashboard. | true | +| sessionUuid | Session uuid, recieved in [upload to bucket](#upload-to-bucket) | true | + +#### Possible errors + +| Code | Description | +| -------- | ---------------------------------------------- | +| 40406004 | Session does not exists | +| 40006001 | Files in this session were already transferred | + +#### Response + +Api respond with status `200 OK` , if operation is successfully executed. + +
+
+
+ + + +```sh +curl --location --request POST "https://api.apillon.io/storage/:bucketUuid/upload/:sessionUuid/end" \ +--header "Authorization: Basic :credentials" \ +--header "Content-Type: application/json" \ +--data-raw "{ + \"directSync\": true +}" +``` + + + + + + +```json +{ + "id": "b64b1c07-1a8a-4b05-9e3b-3c6a519d6ff7", + "status": 200, + "data": true +} +``` + + + +
+
+ +### Get bucket content + +> Gets directories and files in bucket. Items are paginated and can be filtered and ordered through query parameters. + +**Note: This endpoint returns files, that are successfully transferred to IPFS node. I.e. files with [fileStatus](#file-statuses) 3 or 4.** + +
GET /storage/:bucketUuid/content
+ +
+
+ +#### URL parameters + +| Name | Description | Required | +| ---------- | -------------------------------------------------------------- | -------- | +| bucketUuid | Unique key of bucket. Key is displayed on developer dashboard. | true | + +#### Query parameters + +| Name | Description | Required | +| ----------- | ----------------------------------------------------------------------------------------- | -------- | +| search | Filters file by file name. | false | +| directoryId | Gets files inside a specific directory. | false | +| page | Files are paginated by default. This parameter is used to get files from a specific page. | false | +| limit | Number of files on a page (default: 20). | false | +| orderBy | One or multiple properties, separated by a comma, used to order data. | false | +| desc | `Boolean` values, mapped to the index of the `orderBy` parameter. Defaults to false. | false | + +#### Possible errors + +| Code | Description | +| -------- | ---------------------- | +| 40406002 | Bucket does not exist. | + +#### Response fields + +The `Data` property of API response contains two properties: `items` (records that match the current query) and `total` (number of all records. This information should be used for pagination: Round up (`total` / `limit`) = number of pages. + +Properties of each item: + +| Field | Type | Description | +| ----------------- | ---------- | ------------------------------------------------------------------ | +| id | `integer` | Item internal ID | +| type | `integer` | Item type with possible values `1`(directory) and `2`(file) | +| name | `string` | Item (directory or file) name | +| createTime | `DateTime` | Item create time | +| updateTime | `DateTime` | Item last update time | +| contentType | `string` | Item content type (MIME type) | +| size | `integer` | Item size in bytes | +| parentDirectoryId | `integer` | ID of directory where a file is located | +| fileUuid | `string` | File unique identifier | +| CID | `string` | File content identifier - label used to point to material in IPFS. | +| link | `string` | File link on Apillon IPFS gateway. | + +
+
+
+ + + +```sh +curl --location --request GET "https://api.apillon.io/storage/:bucketUuid/content" \ +--header "Authorization: Basic :credentials" +``` + + + + +```sh +curl --location --request GET "https://api.apillon.io/storage/:bucketUuid/content?orderBy=name&desc=false&limit=5&page=1" \ +--header "Authorization: Basic :credentials" +``` + + + + + + +```json +{ + "id": "c8c50b3b-91ff-42c7-b0af-f866ce23f18a", + "status": 200, + "data": { + "items": [ + ... + { + "type": 1, + "id": 11, + "status": 5, + "name": "My directory", + "CID": null, + "createTime": "2022-12-08T13:27:00.000Z", + "updateTime": "2023-01-10T12:18:55.000Z", + "contentType": null, + "size": null, + "parentDirectoryId": null, + "fileUuid": null, + "link": null + }, + { + "type": 2, + "id": 397, + "status": 5, + "name": "My file.txt", + "CID": "QmcG9r6Rdw9ZdJ4imGBWc6mi5VzWHQfkcLDMe2aP74eb42", + "createTime": "2023-01-19T10:10:01.000Z", + "updateTime": "2023-01-19T10:10:31.000Z", + "contentType": "text/plain", + "size": 68, + "parentDirectoryId": null, + "fileUuid": "0a775bfa-a0d0-4e0b-9a1e-e909e426bd11", + "link": "https://ipfs.apillon.io/ipfs/QmcG9r6Rdw9ZdJ4imGBWc6mi5VzWHQfkcLDMe2aP74eb42" + } + ... + ], + "total": 10 + } +} +``` + + + +
+
+ +### Get file details + +> Gets details of a specific file inside a bucket. + +
GET /storage/:bucketUuid/file/:id/detail
+ +
+
+ +#### URL parameters + +| Name | Description | required | +| ---------- | ---------------------------------------------------------------- | -------- | +| bucketUuid | Unique key of a bucket. Key is displayed on developer dashboard. | true | +| id | File internal ID, UUID or CID. | true | + +#### Possible errors + +| Code | Description | +| -------- | -------------------- | +| 40406005 | File does not exist. | + +#### Response fields + +Response `data` property contains two properties: `fileStatus` and `file`. File status tells the current status of the file relative to the entire flow the file goes through to be fully loaded and pinned on Crust Network, while `file` property contains file metadata fields. + +##### File statuses + +| Number | Description | +| ------ | ----------------------------------------------------------------- | +| 1 | Request for upload to Apillon storage was generated. | +| 2 | File is uploaded to Apillon central server. | +| 3 | File is transferred to IPFS node. | +| 4 | File is replicated to different IPFS nodes through Crust Network. | + +##### File metadata + +`CID`, `size`, and `downloadLink` are present if file is already loaded to IPFS. + +| Field | Type | Description | +| ------------------------------------------------------------------------ | --------- | ---------------------------------------------------- | +| id | `integer` | Apillon internal file ID | +| status | `integer` | Apillon internal file status | +| fileUuid | `string` | File unique identifier | +| name | `string` | File name | +| contentType | `string` | File content type (MIME type) | +| [CID](https://docs.ipfs.tech/concepts/content-addressing/#what-is-a-cid) | `string` | File content identifier pointing to material in IPFS | +| size | `integer` | File size in bytes | +| downloadLink | `string` | File link on Apillon IPFS gateway | + +
+
+
+ + + +```sh +curl --location --request GET "https://api.apillon.io/storage/:bucketUuid/file/:id/detail" \ +--header "Authorization: Basic :credentials" +``` + + + + + + +```json +{ + "id": "5be33c54-2cc9-46f4-8f50-debc98866810", + "status": 200, + "data": { + "fileStatus": 4, + "file": { + "id": 397, + "status": 5, + "fileUuid": "0a775bfa-a0d0-4e0b-9a1e-e909e426bd11", + "CID": "QmcG9r6Rdw9ZdJ4imGBWc6mi5VzWHQfkcLDMe2aP74eb42", + "name": "My file.txt", + "contentType": "text/plain", + "size": 68, + "fileStatus": 4, + "downloadLink": "https://ipfs.apillon.io/ipfs/QmcG9r6Rdw9ZdJ4imGBWc6mi5VzWHQfkcLDMe2aP74eb42" + } + } +} +``` + + + +
+
+ +### Delete file + +> Marks a file inside bucket for deletion by `id`, `fileUuid`, or `CID`. File will be completely deleted from the Apillon system and Apillon IPFS node after 3 months. +> If file is marked for deletion, it will not be renewed on Crust Network. + +
DELETE /storage/:bucketUuid/file/:id
+ +
+
+ +#### URL parameters + +| Name | Description | required | +| ---------- | -------------------------------------------------------------- | -------- | +| bucketUuid | Unique key of bucket. Key is displayed on developer dashboard. | true | +| id | File internal ID, UUID, or CID. | true | + +#### Possible errors + +| Code | Description | +| -------- | ---------------------------- | +| 40406005 | File does not exist. | +| 40006009 | File is marked for deletion. | + +#### Response fields + +The response of delete function is a record that has been marked for deletion. + +Returned fields are the same as fields that are returned in [GET file details API](#file-metadata). + +**Note:** The `status` property of file is 8. This means the file is marked for deletion and will be deleted after a certain period. + +
+
+
+ + + +```sh +curl --location --request DELETE "https://api.apillon.io/storage/:bucketUuid/file/:id" \ +--header "Authorization: Basic :credentials" \ +--data-raw "" +``` + + + + + + +```json +{ + "id": "bc92ff8d-05f2-4380-bb13-75a1b6b7f388", + "status": 200, + "data": { + "id": 397, + "status": 8, + "fileUuid": "0a775bfa-a0d0-4e0b-9a1e-e909e426bd11", + "CID": "QmcG9r6Rdw9ZdJ4imGBWc6mi5VzWHQfkcLDMe2aP74eb42", + "name": "My file.txt", + "contentType": "text/plain", + "size": 68, + "fileStatus": 4 + } +} +``` + + + +
+
+ +### Get storage info + +> Gets overall storage info for project. + +
GET /storage/info
+ +
+
+ +#### Response fields + +| Field | Type | Description | +| ---------------- | --------- | -------------------------------- | +| availableStorage | `integer` | Available storage space in bytes | +| usedStorage | `integer` | Used storage in bytes | + +
+
+
+ + + +```sh +curl --location --request GET "https://api.apillon.io/storage/info" \ +--header "Authorization: Basic :credentials" +``` + + + + + + +```json +{ + "id": "48e58f84-403a-43e4-bd81-fedeca195610", + "status": 200, + "data": { + "availableStorage": 3221225472, + "usedStorage": 1221225466 + } +} +``` + + + +
+
diff --git a/build/5-hosting-api.md b/build/5-hosting-api.md new file mode 100644 index 00000000..e0734be9 --- /dev/null +++ b/build/5-hosting-api.md @@ -0,0 +1,699 @@ +# Hosting API + +Hosting API provides endpoints, that can be used to implement [CI/CD](https://en.wikipedia.org/wiki/CI/CD). +To deploy page through Apillon API, follow below steps: + +1. Upload website files to Apillon cloud server. + +- Request URLs for files upload +- Upload files to cloud server +- Trigger transfer into website + +2. Execute deployment to staging or production environment. + +**Note:** You should first create a website on the [Apillon dashboard](https://app.apillon.io/dashboard/service/hosting) or through the Apillon API. + +In all cURL examples, parameters with a colon as a prefix should be replaced with real values. + +### List websites + +> API to list all websites in project. Items are paginated and can be filtered and ordered through query parameters as described [here](3-apillon-api.md#listing-requests) . + +#### GET /hosting/websites + +
+
+ +#### Response fields + +Each item is an instance of website DTO, with below properties: + +| Field | Type | Description | +| ----------- | ---------- | ------------------------------------------------------------------------------------------------------------------------ | +| websiteUuid | `string` | Website unique identifier | +| name | `string` | Website name | +| description | `string` | Website description | +| domain | `string` | Website domain. This property needs to be specified, so that Apillon is able to create SSL Certificates for IPFS gateway | +| createTime | `DateTime` | Item create time | +| updateTime | `DateTime` | Item last update time | + +
+
+
+ + + +```sh +curl --location --request GET "https://api.apillon.io/hosting/websites" \ +--header "Authorization: Basic :credentials" +``` + + + + +```sh +curl --location --request GET "https://api.apillon.io/storage/buckets?search=My website" \ +--header "Authorization: Basic :credentials" +``` + + + + + + +```json +{ + "id": "75095bf9-e976-45c8-8a9d-e013ca3b203a", + "status": 200, + "data": { + "items": [ + ... + { + "websiteUuid": "851595b6-ac6d-11ed-96a4-02420a000705", + "name": "My website", + "description": null, + "domain": "https://www.website.si", + "createTime": "2023-01-27T12:31:34.000Z", + "updateTime": "2023-02-14T13:43:10.000Z" + } + ... + ], + "total": 10 + } +} +``` + + + +
+
+ +### Create new website + +> API for creating new website. + +
POST /hosting/websites
+ +
+
+ +#### Body fields + +| Name | Type | Description | Required | +| ----------- | -------- | -------------------- | -------- | +| name | `string` | Website name. | true | +| description | `string` | Website description. | false | + +| Code | Description | +| -------- | --------------------------------------- | +| 42200037 | Request body is missing a `name` field. | + +#### Response + +Response is an instance of website DTO, described above. + +
+
+
+ + + +```sh +curl --location --request POST "https://api.apillon.io/hosting/websites" \ +--header "Authorization: Basic :credentials" \ +--header "Content-Type: application/json" \ +--data "{ + \"name\": \"My website\" +}" +``` + + + + + + +```json +{ + "id": "489f33ac-eef7-4599-b9c7-d6022f3dbf6b", + "status": 201, + "data": { + "createTime": "2023-10-10T20:36:08.782Z", + "updateTime": "2023-10-10T20:36:08.782Z", + "websiteUuid": "5b8d1943-afd9-4eb7-ba88-bd73af1445fb", + "name": "My website", + "description": null, + "domain": null, + "bucketUuid": "9c9aec59-8ea1-4522-bfe0-37a69284c294", + "ipnsStaging": null, + "ipnsProduction": null + } +} +``` + + + + +
+
+ +### Get website + +> Endpoint to get website. Endpoint returns basic website data, along with IPNS links. + +
GET /hosting/websites/:websiteUuid
+ +
+
+ +#### URL parameters + +| Name | Description | Required | +| ----------- | ----------------------------------------------------------- | -------- | +| websiteUuid | Website UUID, visible in developer console website overview | true | + +#### Possible errors + +| Code | Description | +| -------- | ----------------------- | +| 40406010 | Website does not exists | + +#### Response fields + +| Field | Type | Description | +| -------------- | -------- | ------------------------------------------------------------------------ | +| websiteUuid | `string` | Website unique identifier | +| name | `string` | Website name | +| description | `string` | Website description | +| domain | `string` | Domain for production environment | +| bucketUuid | `string` | UUID of bucket, for file upload | +| ipnsStaging | `string` | IPNS name of staging version. Use this to access website on IPFS gateway | +| ipnsProduction | `string` | IPNS name of production version | + +
+
+
+ + + +```sh +curl --location --request GET "https://api.apillon.io/hosting/websites/:websiteUuid" \ +--header "Authorization: Basic :credentials" +``` + + + + + + +```json +{ + "id": "0eb223ce-51c0-4a9b-96ce-331a1cd99603", + "status": 200, + "data": { + "websiteUuid": "a1d90d2c-f167-4889-8620-204862833851", + "name": "My test page", + "description": null, + "domain": "", + "bucketUuid": "57aef0fc-84cb-4564-9af2-0f7bfc0ef729", + "ipnsStaging": "k2k4r8p6fvcyq5qogaqdtvmqn5vyvyy3khut1llkrz13ls16ocp4gojx", + "ipnsProduction": "k2k4r8ng8nqexubrmbwnhsuu1d6n4ebgnxsbdcu9gxk8uv3l67098hge" + } +} +``` + + + +
+
+ +### Get URLs for files upload + +> API that creates file upload requests and returns URLs for files upload. + +
POST /hosting/websites/:websiteUuid/upload
+ +
+
+ +#### URL parameters + +| Name | Description | Required | +| ----------- | ---------------------------------------------------------------------- | -------- | +| websiteUuid | Unique key of website bucket. Key is displayed on developer dashboard. | true | + +#### Body fields + +| Name | Type | Description | Required | +| ----- | ------- | ------------------------ | -------- | +| files | `array` | Array of files metadata. | true | + +Each file metadata object in `files` array, contain below properties. + +| Name | Type | Description | Required | +| ----------- | -------- | ---------------------------------------------------------------------------------------------------------- | -------- | +| fileName | `string` | Full name (name and extension) of file to be uploaded | true | +| contentType | `string` | File [MIME type](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types) | false | +| path | `string` | File path inside website. Empty for root. Must not contain `fileName`. | false | + +#### Possible errors + +| Code | Description | +| -------- | ----------------------------------------------------------- | +| 40406010 | Website does not exists | +| 42200040 | Request body is missing a `files` field. | +| 42200008 | Request body file object is missing a `fileName` field. | +| 40006002 | Website has reached max size limit. | +| 50006003 | Internal error - Apillon was unable to generate upload URL. | + +#### Response + +| Name | Type | Description | +| ----------- | -------- | ----------------------------------------------------------------------------------- | +| sessionUuid | `string` | Session unique key, which is later used to end upload and transfer files ti website | +| files | `array` | Array of files metadata. | + +Files in request body are returned in response `data.files` property. Each file is equipped with `url` and `fileUuid`. All properties are displayed below. + +| Field | Type | Description | +| ----------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| url | `string` | URL for file upload. Signed URL is unique for each file and is valid only for a limited time (1 min), so you should start with file upload as soon as possible.

Request should use `PUT` method and `binary` body.

Binary data should be sent in body as-is, but with the appropriate Content-Type header (e.g., text/plain). | +| fileUuid | `string` | File unique identifier used to query file status, etc. | +| fileName | `string` | Full name (name and extension) of file to be uploaded | +| contentType | `string` | File [MIME type](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types) | +| path | `string` | File path. | + +
+
+
+ + + +```sh +curl --location --request POST "https://api.apillon.io/hosting/websites/:websiteUuid/upload" \ +--header "Authorization: Basic :credentials" \ +--header "Content-Type: application/json" \ +--data-raw "{ + \"files\": [ + { + \"fileName\": \"index.html\", + \"contentType\": \"text/html\" + }, + { + \"fileName\": \"styles.css\", + \"contentType\": \"text/css\", + \"path\": \"assets/\" + } + + ] + +}" +``` + + + + + + +```json +{ + "id": "7dd011ec-20e2-4c28-b585-da6c6f7fce8d", + "status": 201, + "data": { + "sessionUuid": "29ef6ca2-b171-440c-b934-db8aa88c3424", + "files": [ + { + "path": null, + "fileName": "index.html", + "contentType": "text/html", + "url": "https://sync-to-ipfs-queue.s3.eu-west-1.amazonaws.com/HOSTING_sessions/70/29ef6ca2-b171-440c-b934-db8aa88c3424/index.html?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIAQIMRRA6GJRL57L7G%2F20230215%2Feu-west-1%2Fs3%2Faws4_request&X-Amz-Date=20230215T105030Z&X-Amz-Expires=900&X-Amz-Signature=187035d2307bc089101eff3abbdd7baa3e8691b4d5d3bafa5aebb87e589e8c0c&X-Amz-SignedHeaders=host&x-id=PutObject", + "fileUuid": "e17436a1-5292-4380-ad91-eaac02a862b1" + }, + { + "path": "assets/", + "fileName": "styles.css", + "contentType": "text/css", + "url": "https://sync-to-ipfs-queue.s3.eu-west-1.amazonaws.com/HOSTING_sessions/70/29ef6ca2-b171-440c-b934-db8aa88c3424/assets/styles.css?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIAQIMRRA6GJRL57L7G%2F20230215%2Feu-west-1%2Fs3%2Faws4_request&X-Amz-Date=20230215T105030Z&X-Amz-Expires=900&X-Amz-Signature=f91b03a951fe3f99291802306be3e79812ca64e39effbb7dea1c19bb7cd1e42b&X-Amz-SignedHeaders=host&x-id=PutObject", + "fileUuid": "358c2942-4ced-421e-9a6f-edbf94c55dff" + } + ] + } +} +``` + +**Example for uploading to signed URL:** + + + + + + + +```sh +curl --location --request PUT "https://sync-to-ipfs-queue.s3.eu-west-1.amazonaws.com/HOSTING_sessions/70/29ef6ca2-b171-440c-b934-db8aa88c3424/index.html?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIAQIMRRA6GJRL57L7G%2F20230215%2Feu-west-1%2Fs3%2Faws4_request&X-Amz-Date=20230215T105030Z&X-Amz-Expires=900&X-Amz-Signature=187035d2307bc089101eff3abbdd7baa3e8691b4d5d3bafa5aebb87e589e8c0c&X-Amz-SignedHeaders=host&x-id=PutObject" \ +--header "Content-Type: text/plain" \ +--data-raw "

+Welcome to my awesome website +

" +``` + +
+ + +```sh +curl --location --request PUT "https://sync-to-ipfs-queue.s3.eu-west-1.amazonaws.com/HOSTING_sessions/70/29ef6ca2-b171-440c-b934-db8aa88c3424/index.html?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIAQIMRRA6GJRL57L7G%2F20230215%2Feu-west-1%2Fs3%2Faws4_request&X-Amz-Date=20230215T105030Z&X-Amz-Expires=900&X-Amz-Signature=187035d2307bc089101eff3abbdd7baa3e8691b4d5d3bafa5aebb87e589e8c0c&X-Amz-SignedHeaders=host&x-id=PutObject" \ +--header "Content-Type: text/plain" \ +--data-binary ":full path to file" +``` + + +
+ +
+
+ +### End upload session + +> Transfer files to website bucket, which is used as source for deploy to staging(preview) environment. + +
POST /hosting/websites/:websiteUuid/upload/:sessionUuid/end
+ +
+
+ +#### URL parameters + +| Name | Description | Required | +| ----------- | ------------------------------------------------------------------------------------- | -------- | +| websiteUuid | Unique key of website. Key is displayed in developer dashboard. | true | +| sessionUuid | Session uuid, recieved in [get URL for upload request](#post-storagebucketuuidupload) | true | + +#### Possible errors + +| Code | Description | +| -------- | ---------------------------------------------- | +| 40406004 | Session does not exists | +| 40006001 | Files in this session were already transferred | + +#### Response + +Api respond with status `200 OK` , if operation is successfully executed. + +
+
+
+ + + +```sh +curl --location --request POST "https://api.apillon.io/hosting/websites/:websiteUuid/upload/:sessionUuid/end" \ +--header "Authorization: Basic :credentials" \ +--header "Content-Type: application/json" \ +--data-raw "{ + \"directSync\": true +}" +``` + + + + + + +```json +{ + "id": "b64b1c07-1a8a-4b05-9e3b-3c6a519d6ff7", + "status": 200, + "data": true +} +``` + + + +
+
+ +### Deploy website + +> Endpoint to trigger website deployment into specific environment. + +
POST /hosting/websites/:websiteUuid/deploy
+ +
+
+ +#### URL parameters + +| Name | Description | Required | +| ----------- | ----------------------------------------------------------- | -------- | +| websiteUuid | Website UUID, visible in developer console website overview | true | + +#### Body fields + +| Name | Type | Description | Required | +| ----------- | -------- | ------------------------------------------------- | -------- | +| environment | `number` | Possible `environment` values are explained below | true | + +##### Environments + +| Status | Description | +| ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 1 | Uploaded files are deployed to staging environment. Website will be available through staging IPNS link | +| 2 | Files from current staging environment are deployed to production environment. Website is pinned to CRUST, replicated and available through production IPNS link | +| 3 | Same as `2`, only that the source are uploaded files, not files in staging environment. | + +#### Possible errors + +| Code | Description | +| -------- | ----------------------------------------------- | +| 42200039 | Request body is missing an `environment` field. | +| 40406010 | Website does not exists | +| 40006016 | There are no files to deploy. | +| 40006017 | There are no changes to deploy. | + +#### Response + +Endpoint triggers deployment of website to specific environment. As result, deployment record with below field is returned. +This deployment is now waiting to be processed. + +**Note:** Deployment is processed in background, which may take several minutes. +When deploying to `staging` environment, files are added to IPFS and wrapped to directory, which is then accessible in IPFS via IPNS or CID. +In `production`, this CID is pinned to CRUST and replicated to other nodes. + +##### Deployment fields + +| Field | Type | Description | +| ---------------- | -------- | --------------------------------------------------------------------------------------------- | +| id | `number` | Deployment internal number | +| environment | `number` | Environment to where website will be deployed | +| deploymentStatus | `number` | Current status of deployment. Possible values are listed below. | +| cid | `string` | When deployment is successful, CID points to directory on IPFS, where this page is accessible | +| size | `number` | Size of website | +| number | `number` | Deployment serial number - for this environment | + +##### Website deployment statuses + +Deployment goes through different stages and each stage updates `deploymentStatus`. Possible deployment statuses: + +| Status | Description | +| ------ | --------------------- | +| 0 | Deployment initiated | +| 1 | In processing | +| 10 | Deployment successful | +| 100 | Deployment failed | + +
+
+
+ + + +```sh +curl --location --request POST "https://api.apillon.io/hosting/websites/:websiteUuid/deploy" \ +--header "Authorization: Basic :credentials" \ +--header "Content-Type: application/json" \ +--data-raw "{ + \"environment\": 1 +}" +``` + + + + + + +```json +{ + "id": "32eff81a-6b0b-4a92-a5cb-e5cebf6d6c28", + "status": 200, + "data": { + "id": 91, + "createTime": "2023-10-11T19:06:55.347Z", + "updateTime": "2023-10-11T19:06:55.347Z", + "environment": 1, + "deploymentStatus": 0, + "cid": null, + "size": null, + "number": 5 + } +} +``` + + + +
+
+ +### List website deployments + +> API to list website deployments. More about listing requests can be found [here](3-apillon-api.md#listing-requests) + +#### GET /hosting/websites/:websiteUuid/deployments + +
+
+ +#### URL parameters + +| Name | Description | Required | +| ---------------- | --------------------------------------------------------- | -------- | +| deploymentStatus | Current deployment [status](#website-deployment-statuses) | false | +| environment | Deployment [environment](#environments) | false | + +#### Response fields + +Each item in list is a [deployment DTO](#deployment-fields) instance. + +
+
+
+ + + +```sh +curl --location --request GET "https://api.apillon.io/hosting/websites/:websiteUuid/deployments" \ +--header "Authorization: Basic :credentials" +``` + + + + +```sh +curl --location --request GET "https://api.apillon.io/hosting/websites/:websiteUuid/deployments?orderBy=number" \ +--header "Authorization: Basic :credentials" +``` + + + + + + +```json +{ + "id": "75095bf9-e976-45c8-8a9d-e013ca3b203a", + "status": 200, + "data": { + "items": [ + ... + { + "id": 90, + "createTime": "2023-10-11T19:04:40.000Z", + "updateTime": "2023-10-11T19:05:06.000Z", + "environment": 1, + "deploymentStatus": 100, + "cid": null, + "size": 11, + "number": 4 + }, + { + "id": 91, + "createTime": "2023-10-11T19:06:55.000Z", + "updateTime": "2023-10-11T19:07:20.000Z", + "environment": 1, + "deploymentStatus": 10, + "cid": "QmeY1amT7yUcSzjehwH7LcEwKNdTZnZnSYLXPnABTzUq8d", + "size": 11, + "number": 5 + } + ... + ], + "total": 10 + } +} +``` + + + +
+
+ +### Get deployment + +> Endpoint to get deployment. + +
GET /hosting/websites/:websiteUuid/deployments/:deploymentId
+ +
+
+ +#### URL parameters + +| Name | Description | Required | +| ------------ | ------------------------------------------------------------------- | -------- | +| websiteUuid | Website UUID, visible in developer console website overview | true | +| deploymentId | Deployment internal number, returned from `deploy` website endpoint | true | + +#### Possible errors + +| Code | Description | +| -------- | -------------------------- | +| 40406011 | Deployment does not exists | + +#### Response fields + +`Data` property is a [deployment DTO](#deployment-fields) instance. + +Deployment goes through different stages and each stage updates `deploymentStatus`. Possible deployment statuses: + +| Status | Description | +| ------ | --------------------- | +| 0 | Deployment initiated | +| 1 | Deploying | +| 10 | Deployment successful | +| 100 | Deployment failed | + +
+
+
+ + + +```sh +curl --location --request GET "https://api.apillon.io/hosting/websites/:websiteUuid/deployments/:deploymentId" \ +--header "Authorization: Basic :credentials" +``` + + + + + + +```json +{ + "id": "2d7d1b0c-15b1-4816-9aec-857182c7b617", + "status": 200, + "data": { + "id": 91, + "createTime": "2023-10-11T19:06:55.000Z", + "updateTime": "2023-10-11T19:07:20.000Z", + "environment": 1, + "deploymentStatus": 10, + "cid": "QmeY1amT7yUcSzjehwH7LcEwKNdTZnZnSYLXPnABTzUq8d", + "size": 11, + "number": 5 + } +} +``` + + + +
+
diff --git a/build/6-nfts-api.md b/build/6-nfts-api.md new file mode 100644 index 00000000..444a7784 --- /dev/null +++ b/build/6-nfts-api.md @@ -0,0 +1,756 @@ +# NFTs API + +API is for creating and managing NFTs. To prepare images and metadata you can use storage API. To learn more about metadata standards you can visit: https://docs.opensea.io/docs/metadata-standards + +### Get NFT Collection + +> Get NFT collection by UUID + +#### GET /nfts/collections/:uuid + +
+
+ +#### URL parameters + +| Name | Description | Required | +| ---- | ------------------------------------------------------------------ | -------- | +| uuid | Unique key of collection. Key is displayed in developer dashboard. | true | + +#### Possible errors + +| Code | Description | +| -------- | --------------------------------- | +| 40300000 | Not allowed to access collection. | +| 50012009 | Collection does not exist. | + +#### Response Fields + +| Name | Type | Description | +| ---------------- | ---------- | ------------------------------------------------------------------------------------------------------ | +| createTime | `DateTime` | Collection create time. | +| updateTime | `DateTime` | Collection last update time. | +| collectionType | `number` | Type of smart contract to use for collection. Available types are described [here](#collection-types). | +| collectionUuid | `string` | Unique key of a collection. | +| symbol | `string` | NFT collection symbol (usually 3-4 characters long). | +| name | `string` | NFT collection name. | +| description | `string` | NFT collection description. | +| maxSupply | `number` | Maximal number of NFTs ever in existence (0 stands for unlimited). | +| bucketUuid | `string` | UUID of the bucket where metadata is stored. | +| baseUri | `string` | Base URI for collection metadata (token id and file extension is appended to it). | +| baseExtension | `string` | File extension that is auto appended after token id to form a full URL. | +| isSoulbound | `boolean` | Soul bound tokens are NFTs that are bounded to wallet and not transferable. | +| isRevokable | `boolean` | For revocable collection owner can destroy NFTs at any time. | +| royaltiesFees | `number` | Percentage (between 0 and 100) of each NFT sale sent to wallet specified under royalties address. | +| royaltiesAddress | `string` | Address where royalties are sent to. | +| collectionStatus | `number` | Apillon internal/database collection status. | +| contractAddress | `string` | Smart address of contract for deployed collection. | +| transactionHash | `string` | Deployment transaction hash/id. | +| deployerAddress | `string` | Wallet address of deployer. | +| chain | `number` | Blockchain id on which you want to release your collection. | +| drop | `boolean` | Determines if collection is mintable by public. | +| dropStart | `number` | UNIX timestamp which determines public mint opening date and time. | +| dropPrice | `number` | Price of NFT at mint stage in token that is used on `chain`. | +| dropReserve | `number` | Amount of NFTs reserved by owner. | + +
+
+ + + + +```sh +curl --location 'https://api.apillon.io/nfts/collections/:uuid' \ +--header 'Authorization: Basic :credentials' +``` + + + + + + +```json +{ + "id": "b5935c73-204d-4365-9f9a-6a1792adab5b", + "status": 200, + "data": { + "createTime": "2023-06-13T10:15:58.000Z", + "updateTime": "2023-06-13T10:15:58.000Z", + "collectionType": 1, + "collectionUuid": "d6355fd3-640d-4803-a4d9-79d875abcb5a", + "symbol": "NFT", + "name": "NFT Collection", + "description": "NFT Collection Description", + "maxSupply": 1000, + "bucketUuid": "a9425ff7-4802-4a38-b771-84a790112c30", + "baseUri": "https://ipfs.apillon.io/metadata/", + "baseExtension": ".json", + "isSoulbound": false, + "isRevokable": true, + "royaltiesFees": 0.1, + "royaltiesAddress": "0x4156edbafc5091507de2dd2a53ded551a346f83b", + "collectionStatus": 0, + "contractAddress": "0x452101C96A1Cf2cBDfa5BB5353e4a7F235241557", + "transactionHash": "0x6b97424de3367cd0335b08265787b83053b62bee2d1c8bec1f776936bea4fb26", + "deployerAddress": "0x4156edbafc5091507de2dd2a53ded551a346f83b", + "chain": 1287, + "drop": true, + "dropStart": 1687251003, + "dropPrice": 0.1, + "dropReserve": 5 + } +} +``` + + + +
+
+ +##### Collection Type + +| Number | Description | +| ------ | ------------------------ | +| 0 | Generic NFT collection. | +| 1 | Nestable NFT collection. | + +##### Collection Statuses + +| Number | Description | +| ------ | ---------------------------------------- | +| 0 | Collection was created. | +| 1 | Deploying collection was initiated. | +| 2 | Collection is being deployed. | +| 3 | Collection was deployed successfully. | +| 4 | Collection was transferred successfully. | +| 5 | Failed deploying collection. | + +### List NFT Collections + +> List NFT collections. Items are paginated and can be filtered and ordered through query parameters. + +#### GET /nfts/collections + +
+
+ +#### Query parameters + +| Name | Description | Required | +| ---------------- | ----------------------------------------------------------------------------------------------------- | -------- | +| collectionStatus | Collection status. Find available statuses [here](#collection-statuses). | false | +| search | Search by collection name. | false | +| page | Collections are paginated by default. This parameter is used to get collections from a specific page. | false | +| limit | Number of files on a page (default: 20). | false | +| orderBy | One or multiple properties, separated by a comma, used to order data. | false | +| desc | `Boolean` values, mapped to the index of the `orderBy` parameter. Defaults to false. | false | + +#### Response + +Response is a list of items described [under Response Fields above](#get-nft-collection). + +
+
+ + + + +```sh +curl --location 'https://api.apillon.io/nfts/collections' \ +--header 'Authorization: Basic :credentials' +``` + + + + + + +```json +{ + "id": "b5935c73-204d-4365-9f9a-6a1792adab5b", + "status": 200, + "data": { + "items": [ + { + "createTime": "2023-06-13T10:15:58.000Z", + "updateTime": "2023-06-13T10:15:58.000Z", + "collectionType": 1, + "collectionUuid": "d6355fd3-640d-4803-a4d9-79d875abcb5a", + "symbol": "NFT", + "name": "NFT Collection", + "description": "NFT Collection Description", + "maxSupply": 1000, + "bucketUuid": "a9425ff7-4802-4a38-b771-84a790112c30", + "baseUri": "https://ipfs.apillon.io/metadata/", + "baseExtension": ".json", + "isSoulbound": false, + "isRevokable": true, + "royaltiesFees": 0.1, + "royaltiesAddress": "0x4156edbafc5091507de2dd2a53ded551a346f83b", + "collectionStatus": 0, + "contractAddress": "0x452101C96A1Cf2cBDfa5BB5353e4a7F235241557", + "transactionHash": "0x6b97424de3367cd0335b08265787b83053b62bee2d1c8bec1f776936bea4fb26", + "deployerAddress": "0x4156edbafc5091507de2dd2a53ded551a346f83b", + "chain": 1287, + "drop": true, + "dropStart": 1687251003, + "dropPrice": 0.1, + "dropReserve": 5 + } + ], + "total": 1 + } +} +``` + + + +
+
+ +### List Collection Transactions + +> List NFT collections. Items are paginated and can be filtered and ordered through query parameters. + +#### GET /nfts/collections/:uuid/transactions + +
+
+ +#### URL parameters + +| Name | Description | Required | +| ---- | ------------------------------------------------------------------ | -------- | +| uuid | Unique key of collection. Key is displayed in developer dashboard. | true | + +#### Query parameters + +| Name | Description | Required | +| ----------------- | ------------------------------------------------------------------------------------------------------- | -------- | +| transactionStatus | Transaction status. | false | +| transactionType | Transaction type. | false | +| search | Search by transaction hash. | false | +| page | Transactions are paginated by default. This parameter is used to get transactions from a specific page. | false | +| limit | Number of transactions on a page (default: 20). | false | +| orderBy | One or multiple properties, separated by a comma, used to order data. | false | +| desc | `Boolean` values, mapped to the index of the `orderBy` parameter. Defaults to false. | false | + +#### Response Fields + +| Name | Type | Description | +| ----------------- | ---------- | ----------------------------------------------------------- | +| chainId | `number` | Blockchain id on which you want to release your collection. | +| transactionType | `number` | Transaction type. | +| transactionStatus | `number` | Transaction status | +| transactionHash | `number` | Transaction hash/id. | +| updateTime | `DateTime` | Transaction last update time. | +| createTime | `DateTime` | Transaction create time. | + +
+
+ + + + +```sh +curl --location 'https://api.apillon.io/nfts/collections/:uuid/transactions' \ +--header 'Authorization: Basic :credentials' +``` + + + + + + +```json +{ + "id": "b5935c73-204d-4365-9f9a-6a1792adab5b", + "status": 200, + "data": { + "items": [ + { + "chainId": 1287, + "transactionType": 1, + "transactionStatus": 1, + "transactionHash": "0xb988c8cda7ec8b441611b208360e0aace9c294e1ca5672375b21e815890a54d1", + "updateTime": "2023-06-13T10:15:58.000Z", + "createTime": "2023-06-13T10:15:58.000Z" + } + ], + "total": 1 + } +} +``` + + + +
+
+ +##### Transaction Types + +| Number | Description | +| ------ | --------------------------- | +| 1 | Deploy Contract | +| 2 | Transfer Contract Ownership | +| 3 | Mint NFT | +| 4 | Set Collection Base URI | +| 5 | Burn NFT | +| 6 | Nest mint NFT | + +##### Transaction Status + +| Number | Description | +| ------ | ----------- | +| 1 | Pending | +| 2 | Confirmed | +| 3 | Failed | +| 4 | Error | + +### Create NFT Collection + +> API endpoint that creates NFT collection and deploys it on selected network. + +Collection can be created with a few features/functionalities: + +- drop: collection can be minted/purchased by users +- revokable: NFTs can be revoked by collection owner who can burn them +- soulbound: NFTs are bound to wallet address and can't be transferred +- royalties: owner can enable royalties to earn specified percentage per each NFT trade + +2 types of collections are supported: + +1. Generic collection (based on [OpenZeppelins ERC-721](https://docs.openzeppelin.com/contracts/3.x/erc721) NFT standard) +2. Nestable collection which allows nesting NFTs under each other (based on [RMRKs ERC-7401](https://evm.rmrk.app/general-overview/rmrk-legos/nestable) NFT standard) + +#### POST /nfts/collections + +
+
+ +#### Body fields + +| Name | Type | Description | Required | +| ---------------- | --------- | ---------------------------------------------------------------------------------------- | -------- | +| collectionType | `number` | Type of smart contract to use when deploying collection (1 for generic, 2 for nestable). | true | +| chain | `number` | Blockchain id on which you want to release your collection. | true | +| symbol | `string` | NFT collection symbol (usually 3-4 characters long). | true | +| name | `string` | NFT collection name. | true | +| description | `string` | NFT collection description. | false | +| maxSupply | `number` | Maximal number of NFTs ever in existence (0 stands for unlimited). | true | +| baseUri | `string` | Base URI for collection metadata (token id and file extension is appended to it). | true | +| baseExtension | `string` | File extension that is auto appended after token id to form a full URL. | true | +| isRevokable | `boolean` | For revocable collection owner can destroy NFTs at any time. | true | +| isSoulbound | `boolean` | Soul bound tokens are NFTs that are bound to wallet and not transferable. | true | +| royaltiesAddress | `string` | Address where royalties are sent to. | true | +| royaltiesFees | `number` | Percentage of royalties earned per each NFT trade. | true | +| drop | `boolean` | Determines if collection is mintable by public. | true | +| dropStart\* | `number` | UNIX timestamp (in seconds) which determines public mint opening date and time. | true | +| dropPrice\* | `number` | Price of NFT at mint stage. | true | +| dropReserve\* | `number` | Amount of NFTs reserved by owner. | true | + +**Notes:** + +\*`dropStart`, `dropPrice` and `dropReserve` are only used if `drop` is set to boolean `true`. + +#### Possible errors + +Beside validation errors (with 422 http status code) these are the error codes may be returned: + +| Code | Description | +| -------- | --------------------------------------------- | +| 40012002 | Collection quota reached | +| 50012003 | Failed deploying NFT contract on chain. | +| 50012010 | Failed to create bucket for storing metadata. | + +#### Response + +Response payload is described [under Response Fields above](#get-nft-collection). + +
+
+ + + + +```sh +curl --location 'https://api.apillon.io/nfts/collections' \ +--header 'Content-Type: application/json' \ +--header 'Authorization: Basic :credentials' \ +--data '{ + "collectionType": 1, + "chain": 1287, + "symbol": "NFT", + "name": "NFT Collection", + "description": "NFT Collection description", + "maxSupply": 1000, + "baseUri": "https://ipfs.apillon.io/metadata/", + "baseExtension": "json", + "isRevokable": true, + "isSoulbound": false, + "royaltiesAddress": "0x4156edbafc5091507de2dd2a53ded551a346f83b", + "royaltiesFees": 10, + "drop": true, + "dropStart": 1687251003, + "dropReserve": 5, + "dropPrice": 0.1 +}' +``` + + + + + + +```json +{ + "id": "b5935c73-204d-4365-9f9a-6a1792adab5b", + "status": 200, + "data": { + "createTime": "2023-06-13T10:15:58.000Z", + "updateTime": "2023-06-13T10:15:58.000Z", + "collectionType": 1, + "collectionUuid": "d6355fd3-640d-4803-a4d9-79d875abcb5a", + "symbol": "NFT", + "name": "NFT Collection", + "description": "NFT Collection Description", + "maxSupply": 1000, + "bucketUuid": "a9425ff7-4802-4a38-b771-84a790112c30", + "baseUri": "https://ipfs.apillon.io/metadata/", + "baseExtension": ".json", + "isSoulbound": false, + "isRevokable": true, + "royaltiesFees": 0.1, + "royaltiesAddress": "0x4156edbafc5091507de2dd2a53ded551a346f83b", + "collectionStatus": 0, + "contractAddress": "0x452101C96A1Cf2cBDfa5BB5353e4a7F235241557", + "transactionHash": "0x6b97424de3367cd0335b08265787b83053b62bee2d1c8bec1f776936bea4fb26", + "deployerAddress": "0x4156edbafc5091507de2dd2a53ded551a346f83b", + "chain": 1287, + "drop": true, + "dropStart": 1687251003, + "dropPrice": 0.1, + "dropReserve": 5 + } +} +``` + + + +
+
+ +### Transfer Collection + +> Transfer collection ownership from a wallet owned by caller to a new wallet address. + +#### POST /nfts/collections/:uuid/transfer + +
+
+ +#### URL parameters + +| Name | Description | Required | +| ---- | ------------------------------------------------------------------ | -------- | +| uuid | Unique key of collection. Key is displayed in developer dashboard. | true | + +#### Body fields + +| Name | Type | Description | Required | +| ------- | -------- | ------------------------------ | -------- | +| address | `string` | Wallet address of a new owner. | true | + +#### Possible errors + +Beside validation errors (with 422 http status code) these are the error codes may be returned: + +| Code | Description | +| -------- | ---------------------------------------------------------------------------------- | +| 40012003 | Contract can't be transferred to wallet address that already owns this collection. | +| 40012004 | Transfer transaction already exists. | +| 40300000 | Not allowed to access collection | +| 50012002 | Collection doesn't exist, wasn't deployed or was already transferred. | +| 50012004 | Collection transfer failed. | + +#### Response + +Response payload is described [under Response Fields above](#get-nft-collection). + +
+
+ + + + +```sh +curl --location 'https://api.apillon.io/nfts/collections/:uuid/transfer' \ +--header 'Content-Type: application/json' \ +--header 'Authorization: Basic :credentials' \ +--data '{"address": "0x452101C96A1Cf2cBDfa5BB5353e4a7F235241551"}' +``` + + + + + + +```json +{ + "id": "b5935c73-204d-4365-9f9a-6a1792adab5b", + "status": 200, + "data": { + "createTime": "2023-06-13T10:15:58.000Z", + "updateTime": "2023-06-13T10:15:58.000Z", + "collectionType": 1, + "collectionUuid": "d6355fd3-640d-4803-a4d9-79d875abcb5a", + "symbol": "NFT", + "name": "NFT Collection", + "description": "NFT Collection Description", + "maxSupply": 1000, + "bucketUuid": "a9425ff7-4802-4a38-b771-84a790112c30", + "baseUri": "https://ipfs.apillon.io/metadata/", + "baseExtension": ".json", + "isSoulbound": false, + "isRevokable": true, + "royaltiesFees": 0.1, + "royaltiesAddress": "0x4156edbafc5091507de2dd2a53ded551a346f83b", + "collectionStatus": 0, + "contractAddress": "0x452101C96A1Cf2cBDfa5BB5353e4a7F235241557", + "transactionHash": "0x6b97424de3367cd0335b08265787b83053b62bee2d1c8bec1f776936bea4fb26", + "deployerAddress": "0x4156edbafc5091507de2dd2a53ded551a346f83b", + "chain": 1287, + "drop": true, + "dropStart": 1687251003, + "dropPrice": 0.1, + "dropReserve": 5 + } +} +``` + + + +
+
+ +### Mint Collection NFTs + +> Mint specified amount of NFTs to a wallet address provided in request. + +**Note:** if the collection is set as `drop` this endpoint can only mint reserved NFTs. + +#### POST /nfts/collections/:uuid/mint + +
+
+ +#### URL parameters + +| Name | Description | Required | +| ---- | ------------------------------------------------------------------ | -------- | +| uuid | Unique key of collection. Key is displayed in developer dashboard. | true | + +#### Body fields + +| Name | Type | Description | Required | +| ---------------- | -------- | ------------------------------- | -------- | +| receivingAddress | `string` | Wallet address of NFT receiver. | true | +| quantity | `number` | Number of NFTs to mint. | true | + +#### Possible errors + +Beside validation errors (with 422 http status code) these are the error codes may be returned: + +| Code | Description | +| -------- | ------------------------------------------------------------------------ | +| 40300000 | Not allowed to access collection. | +| 50012002 | Collection doesn't exist, wasn't deployed or was already transferred. | +| 50012005 | Error minting NFT. | +| 50012007 | Total number of minted NFTs would exceed max supply for this collection. | +| 50012008 | All of the reserved NFTs were already minted. | + +#### Response Fields + +| Field | Type | Description | +| ------- | --------- | ----------------- | +| success | `boolean` | Status of action. | + +
+
+ + + + +```sh +curl --location 'https://api.apillon.io/nfts/collections/:uuid/mint' \ +--header 'Content-Type: application/json' \ +--header 'Authorization: Basic :credentials' \ +--data '{"receivingAddress": "0x452101C96A1Cf2cBDfa5BB5353e4a7F235241557", "quantity": 1}' +``` + + + + + + +```json +{ + "id": "b5935c73-204d-4365-9f9a-6a1792adab5b", + "status": 200, + "data": { + "success": true + } +} +``` + + + +
+
+ +### Nest Mint Collection NFTs + +> Nest mint specified amount of NFTs under a parent NFT defined by the parent collection UUID and token id. + +#### POST /nfts/collections/:uuid/nest-mint + +
+
+ +#### URL parameters + +| Name | Description | Required | +| ---- | ------------------------------------------------ | -------- | +| uuid | Unique key of (child) collection we are minting. | true | + +#### Body fields + +| Name | Type | Description | Required | +| -------------------- | -------- | ------------------------------------------------- | -------- | +| parentCollectionUuid | `string` | Collection UUID of NFT receiving nest-minted NFT. | true | +| parentNftId | `number` | Token id of NFT receiving nest-minted NFT. | true | +| quantity | `number` | Number of NFTs to nest-mint. | true | + +#### Possible errors + +Beside validation errors (with 422 http status code) these are the error codes may be returned: + +| Code | Description | +| -------- | ------------------------------------------------------------------------ | +| 40300000 | Not allowed to access collection. | +| 50012002 | Collection doesn't exist, wasn't deployed or was already transferred. | +| 50012007 | Total number of minted NFTs would exceed max supply for this collection. | +| 50012008 | All of the reserved NFTs were already minted. | +| 50012013 | Parrent collection doesn't support nesting. | +| 50012014 | Parrent and child collection chain missmatch. | + +#### Response Fields + +| Field | Type | Description | +| ------- | --------- | ----------------- | +| success | `boolean` | Status of action. | + +
+
+ + + + +```sh +curl --location 'https://api.apillon.io/nfts/collections/:uuid/next-mint' \ +--header 'Content-Type: application/json' \ +--header 'Authorization: Basic :credentials' \ +--data '{"parentCollectionUuid": "d6355fd3-640d-4803-a4d9-79d875abcb5a", "parentNftId": 1, "quantity": 1}' +``` + + + + + + +```json +{ + "id": "b5935c73-204d-4365-9f9a-6a1792adab5b", + "status": 200, + "data": { + "success": true + } +} +``` + + + +
+
+ +### Burn Collection NFT + +> Burn specific NFT belonging to collection specified. + +**Note:** burning NFTs is only available if `isRevokable` is enabled on collection. + +#### POST /nfts/collections/:uuid/burn + +
+
+ +#### URL parameters + +| Name | Description | Required | +| ---- | ------------------------------------------------------------------ | -------- | +| uuid | Unique key of collection. Key is displayed in developer dashboard. | true | + +#### Body fields + +| Name | Type | Description | Required | +| ------- | -------- | ------------------------------------------ | -------- | +| tokenId | `number` | Non fungible token id that we are burning. | true | + +#### Possible errors + +Beside validation errors (with 422 http status code) these are the error codes may be returned: + +| Code | Description | +| -------- | --------------------------------------------------------------------- | +| 40300000 | Not allowed to access collection. | +| 50012002 | Collection doesn't exist, wasn't deployed or was already transferred. | +| 50012012 | Burning NFT failed. | + +#### Response fields + +| Field | Type | Description | +| ------- | --------- | ----------------- | +| success | `boolean` | Status of action. | + +
+
+ + + + +```sh +curl --location 'https://api.apillon.io/nfts/collections/:uuid/burn' \ +--header 'Content-Type: application/json' \ +--header 'Authorization: Basic :credentials' \ +--data '{"tokenId": 1}' +``` + + + + + + +```json +{ + "id": "b5935c73-204d-4365-9f9a-6a1792adab5b", + "status": 200, + "data": { + "status": true + } +} +``` + + + +
+
From 59f5601d340d5a0b31c421ac3c453a667a59ac31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vinko=20=C5=A0mid?= Date: Thu, 12 Oct 2023 15:06:52 +0200 Subject: [PATCH 2/7] Storage docs updated with new fields and endpoints --- build/4-storage-api.md | 162 ++++++++++++++++------------------------- 1 file changed, 61 insertions(+), 101 deletions(-) diff --git a/build/4-storage-api.md b/build/4-storage-api.md index a044ba3c..9adaacef 100644 --- a/build/4-storage-api.md +++ b/build/4-storage-api.md @@ -28,11 +28,9 @@ In all cURL examples, parameters with a colon as a prefix should be replaced wit | orderBy | One or multiple properties, separated by a comma, used to order data. | false | | desc | `Boolean` values, mapped to the index of the `orderBy` parameter. Defaults to false. | false | -#### Response fields - -The `Data` property of API response contains two properties: `items` (records that match the current query) and `total` (number of all records. This information should be used for pagination: Round up (`total` / `limit`) = number of pages. +#### Response fields (bucket) -Each item is an instance of bucket DTO, with below properties: +Each item is an instance of bucket model, with below properties: | Field | Type | Description | | ----------- | ---------- | ------------------------------------------------------------------------------------------- | @@ -112,13 +110,15 @@ curl --location --request GET "https://api.apillon.io/storage/buckets?search=My | name | `string` | Bucket name. | true | | description | `string` | Bucket description. | false | +#### Possible errors + | Code | Description | | -------- | --------------------------------------- | | 42200003 | Request body is missing a `name` field. | #### Response -Response is an instance of bucket DTO, described above. +Response is an instance of [bucket](#response-fields-bucket), described above.
@@ -127,18 +127,10 @@ Response is an instance of bucket DTO, described above. ```sh -curl --location --request POST "https://api.apillon.io/storage/:bucketUuid/upload" \ +curl --location --request POST "https://api.apillon.io/storage/buckets" \ --header "Authorization: Basic :credentials" \ --header "Content-Type: application/json" \ ---data-raw "{ - \"files\": [ - { - \"fileName\": \"My test file\", - \"contentType\": \"text/html\" - } - ] - -}" +--data-raw "{ \"name\": \"My bucket\" }" ``` @@ -148,43 +140,18 @@ curl --location --request POST "https://api.apillon.io/storage/:bucketUuid/uploa ```json { - "id": "cbdc4930-2bbd-4b20-84fa-15daa4429952", + "id": "e50c8276-fd8d-47c4-b42a-bf19645a204b", "status": 201, "data": { - "sessionUuid": "3b6113bc-f265-4662-8cc5-ea86f06cc74b", - "files": [ - { - "path": null, - "fileName": "My test file", - "contentType": "text/html", - "url": "https://sync-to-ipfs-queue.s3.eu-west-1.amazonaws.com/STORAGE_sessions/73/3b6113bc-f265-4662-8cc5-ea86f06cc74b/My%20test%20file?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIAQIMRRA6GJRL57L7G%2F20230215%2Feu-west-1%2Fs3%2Faws4_request&X-Amz-Date=20230215T114524Z&X-Amz-Expires=900&X-Amz-Signature=499367f6c6bff5be50686724475ac2fa6307b77b94fd1a25584c092fe74b0a58&X-Amz-SignedHeaders=host&x-id=PutObject", - "fileUuid": "4ef1177b-f7c9-4434-be56-a559cec0cc18" - } - ] + "createTime": "2023-10-12T11:49:49.551Z", + "updateTime": "2023-10-12T11:49:49.551Z", + "bucketUuid": "8218080f-1321-4687-9a89-200b06afb930", + "bucketType": 1, + "name": "My bucket", + "description": null, + "size": 0 } } -``` - -**Example for uploading to signed URL:** - - - - - - - -```sh -curl --location --request PUT "https://sync-to-ipfs-queue.s3.eu-west-1.amazonaws.com/STORAGE_sessions/73/3b6113bc-f265-4662-8cc5-ea86f06cc74b/My%20test%20file?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIAQIMRRA6GJRL57L7G%2F20230215%2Feu-west-1%2Fs3%2Faws4_request&X-Amz-Date=20230215T114524Z&X-Amz-Expires=900&X-Amz-Signature=499367f6c6bff5be50686724475ac2fa6307b77b94fd1a25584c092fe74b0a58&X-Amz-SignedHeaders=host&x-id=PutObject" \ ---data-binary "My test content" -``` - - - - -```sh -curl --location --request PUT "https://sync-to-ipfs-queue.s3.eu-west-1.amazonaws.com/STORAGE_sessions/73/3b6113bc-f265-4662-8cc5-ea86f06cc74b/My%20test%20file?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIAQIMRRA6GJRL57L7G%2F20230215%2Feu-west-1%2Fs3%2Faws4_request&X-Amz-Date=20230215T114524Z&X-Amz-Expires=900&X-Amz-Signature=499367f6c6bff5be50686724475ac2fa6307b77b94fd1a25584c092fe74b0a58&X-Amz-SignedHeaders=host&x-id=PutObject" \ ---header "Content-Type: text/plain" \ ---data-binary ":full path to file" ``` @@ -210,9 +177,10 @@ curl --location --request PUT "https://sync-to-ipfs-queue.s3.eu-west-1.amazonaws #### Body fields -| Name | Type | Description | Required | -| ----- | ------- | ------------------------ | -------- | -| files | `array` | Array of files metadata. | true | +| Name | Type | Description | Required | +| ----------- | -------- | -------------------------------------------------------------------------------------- | -------- | +| files | `array` | Array of files metadata. Maximum 200 items. | true | +| sessionUuid | `string` | Session unique key, which has to be specified to add more uploads to existing session. | true | Each file metadata object in `files` array, contain below properties. @@ -228,8 +196,8 @@ Each file metadata object in `files` array, contain below properties. | -------- | ------------------------------------------------------------------------------ | | 40406002 | Bucket does not exist. | | 42200040 | Request body is missing a `files` field. | +| 42200150 | `files` has invalid length. It should be between 1 and 200 | | 42200008 | Request body file object is missing a `fileName` field. | -| 40006002 | Bucket has reached max size limit. | | 40406009 | Bucket is marked for deletion. It is no longer possible to upload files to it. | | 50006003 | Internal error - Apillon was unable to generate upload URL. | @@ -360,9 +328,6 @@ Api respond with status `200 OK` , if operation is successfully executed. curl --location --request POST "https://api.apillon.io/storage/:bucketUuid/upload/:sessionUuid/end" \ --header "Authorization: Basic :credentials" \ --header "Content-Type: application/json" \ ---data-raw "{ - \"directSync\": true -}" ``` @@ -383,11 +348,11 @@ curl --location --request POST "https://api.apillon.io/storage/:bucketUuid/uploa
-### Get bucket content +### List bucket content -> Gets directories and files in bucket. Items are paginated and can be filtered and ordered through query parameters. +> Gets directories and files in bucket. More about listing requests can be found [here](3-apillon-api.md#listing-requests) -**Note: This endpoint returns files, that are successfully transferred to IPFS node. I.e. files with [fileStatus](#file-statuses) 3 or 4.** +**Note: This endpoint returns files from ended sessions. I.e. files with [fileStatus](#file-statuses) 2, 3 or 4.**
GET /storage/:bucketUuid/content
@@ -402,14 +367,11 @@ curl --location --request POST "https://api.apillon.io/storage/:bucketUuid/uploa #### Query parameters -| Name | Description | Required | -| ----------- | ----------------------------------------------------------------------------------------- | -------- | -| search | Filters file by file name. | false | -| directoryId | Gets files inside a specific directory. | false | -| page | Files are paginated by default. This parameter is used to get files from a specific page. | false | -| limit | Number of files on a page (default: 20). | false | -| orderBy | One or multiple properties, separated by a comma, used to order data. | false | -| desc | `Boolean` values, mapped to the index of the `orderBy` parameter. Defaults to false. | false | +All query parameters from [listing request](3-apillon-api.md#listing-requests) plus: + +| Name | Description | Required | +| ------------- | --------------------------------------- | -------- | +| directoryUuid | Gets files inside a specific directory. | false | #### Possible errors @@ -423,19 +385,19 @@ The `Data` property of API response contains two properties: `items` (records th Properties of each item: -| Field | Type | Description | -| ----------------- | ---------- | ------------------------------------------------------------------ | -| id | `integer` | Item internal ID | -| type | `integer` | Item type with possible values `1`(directory) and `2`(file) | -| name | `string` | Item (directory or file) name | -| createTime | `DateTime` | Item create time | -| updateTime | `DateTime` | Item last update time | -| contentType | `string` | Item content type (MIME type) | -| size | `integer` | Item size in bytes | -| parentDirectoryId | `integer` | ID of directory where a file is located | -| fileUuid | `string` | File unique identifier | -| CID | `string` | File content identifier - label used to point to material in IPFS. | -| link | `string` | File link on Apillon IPFS gateway. | +| Field | Type | Description | +| ------------- | ---------- | ----------------------------------------------------------------- | +| uuid | `string` | Item UUID property | +| type | `integer` | Item type with possible values `1`(directory) and `2`(file) | +| name | `string` | Item (directory or file) name | +| CID | `string` | File content identifier - label used to point to content in IPFS. | +| createTime | `DateTime` | Item create time | +| updateTime | `DateTime` | Item last update time | +| contentType | `string` | Item content type (MIME type). | +| size | `integer` | Item size in bytes | +| directoryUuid | `string` | Uuid of directory in which directory of file is located | +| link | `string` | Link on IPFS gateway. | +| fileStatus | `number` | Current [status](#file-statuses) of file |
@@ -469,32 +431,30 @@ curl --location --request GET "https://api.apillon.io/storage/:bucketUuid/conten "items": [ ... { - "type": 1, - "id": 11, - "status": 5, - "name": "My directory", - "CID": null, - "createTime": "2022-12-08T13:27:00.000Z", - "updateTime": "2023-01-10T12:18:55.000Z", - "contentType": null, - "size": null, - "parentDirectoryId": null, - "fileUuid": null, - "link": null + "uuid": "63ace39b-ec7c-4889-8d94-83a2ad7fb154", + "type": 2, + "name": "My file.txt", + "CID": "QmaufbAR2dX62TSiYYJUS5sV9KNFZLnxgP4ZMkKFoJhSAM", + "createTime": "2023-10-12T12:17:19.000Z", + "updateTime": "2023-10-12T12:17:42.000Z", + "contentType": "", + "size": 6, + "directoryUuid": null, + "link": "https://ipfs-dev.apillon.io/ipfs/QmaufbAR2dX62TSiYYJUS5sV9KNFZLnxgP4ZMkKFoJhSAM", + "fileStatus": 3 }, { + "uuid": "0d224e20-26b9-47a6-8d27-279c5c5a9751", "type": 2, - "id": 397, - "status": 5, - "name": "My file.txt", - "CID": "QmcG9r6Rdw9ZdJ4imGBWc6mi5VzWHQfkcLDMe2aP74eb42", - "createTime": "2023-01-19T10:10:01.000Z", - "updateTime": "2023-01-19T10:10:31.000Z", + "name": "My file in folder.txt", + "CID": "QmSjhrQ1eGCCYoorv1qvuJnzmud11JJxjv8Rdere7A76Za", + "createTime": "2023-10-12T12:17:19.000Z", + "updateTime": "2023-10-12T12:17:42.000Z", "contentType": "text/plain", - "size": 68, - "parentDirectoryId": null, - "fileUuid": "0a775bfa-a0d0-4e0b-9a1e-e909e426bd11", - "link": "https://ipfs.apillon.io/ipfs/QmcG9r6Rdw9ZdJ4imGBWc6mi5VzWHQfkcLDMe2aP74eb42" + "size": 6, + "directoryUuid": null, + "link": "https://ipfs-dev.apillon.io/ipfs/QmSjhrQ1eGCCYoorv1qvuJnzmud11JJxjv8Rdere7A76Za", + "fileStatus": 3 } ... ], From 1ecfc245e08982debb82e16d1c8dc46b7cb289b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vinko=20=C5=A0mid?= Date: Thu, 12 Oct 2023 21:34:27 +0200 Subject: [PATCH 3/7] update docs for bucket content listing, get file detail, delete file --- build/4-storage-api.md | 111 ++++++++++++++++++----------------------- 1 file changed, 49 insertions(+), 62 deletions(-) diff --git a/build/4-storage-api.md b/build/4-storage-api.md index 9adaacef..a15d3c56 100644 --- a/build/4-storage-api.md +++ b/build/4-storage-api.md @@ -430,6 +430,19 @@ curl --location --request GET "https://api.apillon.io/storage/:bucketUuid/conten "data": { "items": [ ... + { + "uuid": "d61753fd-26ba-45cb-9277-89e96d6cfd11", + "type": 1, + "name": "Folder 1", + "CID": null, + "createTime": "2023-10-12T12:20:54.000Z", + "updateTime": "2023-10-12T12:20:54.000Z", + "contentType": null, + "size": null, + "directoryUuid": null, + "link": null, + "fileStatus": null + }, { "uuid": "63ace39b-ec7c-4889-8d94-83a2ad7fb154", "type": 2, @@ -442,19 +455,6 @@ curl --location --request GET "https://api.apillon.io/storage/:bucketUuid/conten "directoryUuid": null, "link": "https://ipfs-dev.apillon.io/ipfs/QmaufbAR2dX62TSiYYJUS5sV9KNFZLnxgP4ZMkKFoJhSAM", "fileStatus": 3 - }, - { - "uuid": "0d224e20-26b9-47a6-8d27-279c5c5a9751", - "type": 2, - "name": "My file in folder.txt", - "CID": "QmSjhrQ1eGCCYoorv1qvuJnzmud11JJxjv8Rdere7A76Za", - "createTime": "2023-10-12T12:17:19.000Z", - "updateTime": "2023-10-12T12:17:42.000Z", - "contentType": "text/plain", - "size": 6, - "directoryUuid": null, - "link": "https://ipfs-dev.apillon.io/ipfs/QmSjhrQ1eGCCYoorv1qvuJnzmud11JJxjv8Rdere7A76Za", - "fileStatus": 3 } ... ], @@ -472,7 +472,7 @@ curl --location --request GET "https://api.apillon.io/storage/:bucketUuid/conten > Gets details of a specific file inside a bucket. -
GET /storage/:bucketUuid/file/:id/detail
+
GET /storage/:bucketUuid/files/:id
@@ -482,7 +482,7 @@ curl --location --request GET "https://api.apillon.io/storage/:bucketUuid/conten | Name | Description | required | | ---------- | ---------------------------------------------------------------- | -------- | | bucketUuid | Unique key of a bucket. Key is displayed on developer dashboard. | true | -| id | File internal ID, UUID or CID. | true | +| id | File UUID or CID. | true | #### Possible errors @@ -492,7 +492,20 @@ curl --location --request GET "https://api.apillon.io/storage/:bucketUuid/conten #### Response fields -Response `data` property contains two properties: `fileStatus` and `file`. File status tells the current status of the file relative to the entire flow the file goes through to be fully loaded and pinned on Crust Network, while `file` property contains file metadata fields. +| Field | Type | Description | +| ------------- | ---------- | ----------------------------------------------------------------- | +| createTime | `DateTime` | File create time | +| updateTime | `DateTime` | File last update time | +| fileUuid | `string` | File UUID property | +| CID | `string` | File content identifier - label used to point to content in IPFS. | +| CIDv1 | `string` | CID version 1 | +| name | `string` | File name | +| contentType | `string` | File content type. Value is taken from file upload request | +| path | `integer` | Full path to file | +| size | `integer` | File size in bytes | +| fileStatus | `number` | File statuses are described in below table | +| directoryUuid | `string` | Uuid of directory in which file is located | +| link | `string` | Link on IPFS gateway. | ##### File statuses @@ -503,21 +516,6 @@ Response `data` property contains two properties: `fileStatus` and `file`. File | 3 | File is transferred to IPFS node. | | 4 | File is replicated to different IPFS nodes through Crust Network. | -##### File metadata - -`CID`, `size`, and `downloadLink` are present if file is already loaded to IPFS. - -| Field | Type | Description | -| ------------------------------------------------------------------------ | --------- | ---------------------------------------------------- | -| id | `integer` | Apillon internal file ID | -| status | `integer` | Apillon internal file status | -| fileUuid | `string` | File unique identifier | -| name | `string` | File name | -| contentType | `string` | File content type (MIME type) | -| [CID](https://docs.ipfs.tech/concepts/content-addressing/#what-is-a-cid) | `string` | File content identifier pointing to material in IPFS | -| size | `integer` | File size in bytes | -| downloadLink | `string` | File link on Apillon IPFS gateway | -

@@ -525,7 +523,7 @@ Response `data` property contains two properties: `fileStatus` and `file`. File ```sh -curl --location --request GET "https://api.apillon.io/storage/:bucketUuid/file/:id/detail" \ +curl --location --request GET "https://api.apillon.io/storage/buckets/:bucketUuid/files/:id" \ --header "Authorization: Basic :credentials" ``` @@ -536,21 +534,21 @@ curl --location --request GET "https://api.apillon.io/storage/:bucketUuid/file/: ```json { - "id": "5be33c54-2cc9-46f4-8f50-debc98866810", + "id": "1beec975-9836-48b2-a284-591ae01f7a58", "status": 200, "data": { - "fileStatus": 4, - "file": { - "id": 397, - "status": 5, - "fileUuid": "0a775bfa-a0d0-4e0b-9a1e-e909e426bd11", - "CID": "QmcG9r6Rdw9ZdJ4imGBWc6mi5VzWHQfkcLDMe2aP74eb42", - "name": "My file.txt", - "contentType": "text/plain", - "size": 68, - "fileStatus": 4, - "downloadLink": "https://ipfs.apillon.io/ipfs/QmcG9r6Rdw9ZdJ4imGBWc6mi5VzWHQfkcLDMe2aP74eb42" - } + "createTime": "2023-10-12T12:20:54.000Z", + "updateTime": "2023-10-12T12:21:17.000Z", + "fileUuid": "120afe0e-b146-45a5-82e0-52d2125df294", + "CID": "QmXKvPVY6jJ7e4oL3QcYjKFw6Bg7EKzzJAXCgXYjuCSyq5", + "CIDv1": "bafybeiefrfkhkevhdvacfjds7gw7mh2wlnuo66aeyffrik7wao5tlvfy3q", + "name": "Hello.txt", + "contentType": "", + "path": "Folder 1/", + "size": 11, + "fileStatus": 3, + "link": "https://ipfs-dev.apillon.io/ipfs/QmXKvPVY6jJ7e4oL3QcYjKFw6Bg7EKzzJAXCgXYjuCSyq5", + "directoryUuid": "d61753fd-26ba-45cb-9277-89e96d6cfd11" } } ``` @@ -562,10 +560,10 @@ curl --location --request GET "https://api.apillon.io/storage/:bucketUuid/file/: ### Delete file -> Marks a file inside bucket for deletion by `id`, `fileUuid`, or `CID`. File will be completely deleted from the Apillon system and Apillon IPFS node after 3 months. +> Marks a file inside bucket for deletion. File will be completely deleted from the Apillon system and Apillon IPFS node after 3 months. > If file is marked for deletion, it will not be renewed on Crust Network. -
DELETE /storage/:bucketUuid/file/:id
+
DELETE /storage/buckets/:bucketUuid/files/:fileUuid
@@ -575,7 +573,7 @@ curl --location --request GET "https://api.apillon.io/storage/:bucketUuid/file/: | Name | Description | required | | ---------- | -------------------------------------------------------------- | -------- | | bucketUuid | Unique key of bucket. Key is displayed on developer dashboard. | true | -| id | File internal ID, UUID, or CID. | true | +| fileUuid | File internal ID, UUID, or CID. | true | #### Possible errors @@ -586,9 +584,7 @@ curl --location --request GET "https://api.apillon.io/storage/:bucketUuid/file/: #### Response fields -The response of delete function is a record that has been marked for deletion. - -Returned fields are the same as fields that are returned in [GET file details API](#file-metadata). +The response of delete function is a boolean value, depends if deletion was successful. **Note:** The `status` property of file is 8. This means the file is marked for deletion and will be deleted after a certain period. @@ -599,7 +595,7 @@ Returned fields are the same as fields that are returned in [GET file details AP ```sh -curl --location --request DELETE "https://api.apillon.io/storage/:bucketUuid/file/:id" \ +curl --location --request DELETE "https://api.apillon.io/storage/buckets/:bucketUuid/files/:fileUuid" \ --header "Authorization: Basic :credentials" \ --data-raw "" ``` @@ -613,16 +609,7 @@ curl --location --request DELETE "https://api.apillon.io/storage/:bucketUuid/fil { "id": "bc92ff8d-05f2-4380-bb13-75a1b6b7f388", "status": 200, - "data": { - "id": 397, - "status": 8, - "fileUuid": "0a775bfa-a0d0-4e0b-9a1e-e909e426bd11", - "CID": "QmcG9r6Rdw9ZdJ4imGBWc6mi5VzWHQfkcLDMe2aP74eb42", - "name": "My file.txt", - "contentType": "text/plain", - "size": 68, - "fileStatus": 4 - } + "data": true } ``` From 790cf579382c4386f11b4d8d4c666c73a2fae7ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vinko=20=C5=A0mid?= Date: Fri, 13 Oct 2023 14:40:58 +0200 Subject: [PATCH 4/7] Docs for list files endpoint. Hosting docs fixes. --- build/4-storage-api.md | 133 ++++++++++++++++++++++-- build/5-hosting-api.md | 223 +++++++++++++++++++++-------------------- 2 files changed, 237 insertions(+), 119 deletions(-) diff --git a/build/4-storage-api.md b/build/4-storage-api.md index a15d3c56..a9f39b16 100644 --- a/build/4-storage-api.md +++ b/build/4-storage-api.md @@ -180,7 +180,7 @@ curl --location --request POST "https://api.apillon.io/storage/buckets" \ | Name | Type | Description | Required | | ----------- | -------- | -------------------------------------------------------------------------------------- | -------- | | files | `array` | Array of files metadata. Maximum 200 items. | true | -| sessionUuid | `string` | Session unique key, which has to be specified to add more uploads to existing session. | true | +| sessionUuid | `string` | Session unique key, which has to be specified to add more uploads to existing session. | false | Each file metadata object in `files` array, contain below properties. @@ -350,11 +350,11 @@ curl --location --request POST "https://api.apillon.io/storage/:bucketUuid/uploa ### List bucket content -> Gets directories and files in bucket. More about listing requests can be found [here](3-apillon-api.md#listing-requests) +> List bucket directories and files in folder structure. Endpoint lists files and directories in single directory, if `directoryUuid` is not present, endpoint lists items in bucket root directory. More about listing requests can be found [here](3-apillon-api.md#listing-requests) **Note: This endpoint returns files from ended sessions. I.e. files with [fileStatus](#file-statuses) 2, 3 or 4.** -
GET /storage/:bucketUuid/content
+
GET /storage/buckets/:bucketUuid/content
@@ -371,7 +371,8 @@ All query parameters from [listing request](3-apillon-api.md#listing-requests) p | Name | Description | Required | | ------------- | --------------------------------------- | -------- | -| directoryUuid | Gets files inside a specific directory. | false | +| directoryUuid | Gets items inside a specific directory. | false | +| search | Search items by name | false | #### Possible errors @@ -381,8 +382,6 @@ All query parameters from [listing request](3-apillon-api.md#listing-requests) p #### Response fields -The `Data` property of API response contains two properties: `items` (records that match the current query) and `total` (number of all records. This information should be used for pagination: Round up (`total` / `limit`) = number of pages. - Properties of each item: | Field | Type | Description | @@ -406,7 +405,7 @@ Properties of each item: ```sh -curl --location --request GET "https://api.apillon.io/storage/:bucketUuid/content" \ +curl --location --request GET "https://api.apillon.io/storage/buckets/:bucketUuid/content" \ --header "Authorization: Basic :credentials" ``` @@ -414,7 +413,7 @@ curl --location --request GET "https://api.apillon.io/storage/:bucketUuid/conten ```sh -curl --location --request GET "https://api.apillon.io/storage/:bucketUuid/content?orderBy=name&desc=false&limit=5&page=1" \ +curl --location --request GET "https://api.apillon.io/storage/buckets/:bucketUuid/content?orderBy=name&desc=false&limit=5&page=1" \ --header "Authorization: Basic :credentials" ``` @@ -468,6 +467,124 @@ curl --location --request GET "https://api.apillon.io/storage/:bucketUuid/conten
+### List files + +> List files inside bucket. This endpoint returns all files in flat structure and each file has a `path` property. More about listing requests can be found [here](3-apillon-api.md#listing-requests) + +**Note: This endpoint returns files from ended sessions. I.e. files with [fileStatus](#file-statuses) 2, 3 or 4.** + +
GET /storage/buckets/:bucketUuid/files
+ +
+
+ +#### URL parameters + +| Name | Description | Required | +| ---------- | -------------------------------------------------------------- | -------- | +| bucketUuid | Unique key of bucket. Key is displayed on developer dashboard. | true | + +#### Query parameters + +All query parameters from [listing request](3-apillon-api.md#listing-requests) plus: + +| Name | Description | Required | +| ------ | --------------------------------------- | -------- | +| search | Search files by full path (path + name) | false | + +#### Possible errors + +| Code | Description | +| -------- | ---------------------- | +| 40406002 | Bucket does not exist. | + +#### Response fields + +Properties of each item: + +| Field | Type | Description | +| ----------- | ---------- | ----------------------------------------------------------------- | +| createTime | `DateTime` | File create time | +| updateTime | `DateTime` | File last update time | +| fileUuid | `string` | File UUID property | +| CID | `string` | File content identifier - label used to point to content in IPFS. | +| CIDv1 | `string` | CID version 1 | +| name | `string` | File name | +| contentType | `string` | File content type. Value is taken from file upload request | +| path | `integer` | Full path to file | +| size | `integer` | File size in bytes | +| fileStatus | `number` | File statuses are described in below table | +| link | `string` | Link on IPFS gateway. | + +
+
+
+ + + +```sh +curl --location --request GET "https://api.apillon.io/storage/buckets/:bucketUuid/files" \ +--header "Authorization: Basic :credentials" +``` + + + + +```sh +curl --location --request GET "https://api.apillon.io/storage/buckets/:bucketUuid/files?search=Hello.txt" \ +--header "Authorization: Basic :credentials" +``` + + + + + + +```json +{ + "id": "c8c50b3b-91ff-42c7-b0af-f866ce23f18a", + "status": 200, + "data": { + "items": [ + ... + { + "createTime": "2023-10-12T12:20:54.000Z", + "updateTime": "2023-10-13T06:08:00.000Z", + "fileUuid": "120afe0e-b146-45a5-82e0-52d2125df294", + "CID": "QmXKvPVY6jJ7e4oL3QcYjKFw6Bg7EKzzJAXCgXYjuCSyq5", + "CIDv1": "bafybeiefrfkhkevhdvacfjds7gw7mh2wlnuo66aeyffrik7wao5tlvfy3q", + "name": "Hello.txt", + "contentType": "", + "path": "Folder 1/", + "size": 11, + "fileStatus": 3, + "link": "https://ipfs-dev.apillon.io/ipfs/QmXKvPVY6jJ7e4oL3QcYjKFw6Bg7EKzzJAXCgXYjuCSyq5" + }, + { + "createTime": "2023-10-12T12:17:19.000Z", + "updateTime": "2023-10-12T12:17:42.000Z", + "fileUuid": "63ace39b-ec7c-4889-8d94-83a2ad7fb154", + "CID": "QmaufbAR2dX62TSiYYJUS5sV9KNFZLnxgP4ZMkKFoJhSAM", + "CIDv1": "bafybeif2yft3qu7wfadsdaorhcfewz74skcsosqb7lrk3ac3doeb7kbbgi", + "name": "My file.txt", + "contentType": "", + "path": null, + "size": 6, + "fileStatus": 3, + "link": "https://ipfs-dev.apillon.io/ipfs/QmaufbAR2dX62TSiYYJUS5sV9KNFZLnxgP4ZMkKFoJhSAM" + } + ... + ], + "total": 10 + } +} +``` + + + +
+
+ ### Get file details > Gets details of a specific file inside a bucket. diff --git a/build/5-hosting-api.md b/build/5-hosting-api.md index e0734be9..141b0db2 100644 --- a/build/5-hosting-api.md +++ b/build/5-hosting-api.md @@ -1,6 +1,7 @@ # Hosting API -Hosting API provides endpoints, that can be used to implement [CI/CD](https://en.wikipedia.org/wiki/CI/CD). +Hosting API provides endpoints for listing, creation and deployment of websites. +API can be used to implement [CI/CD](https://en.wikipedia.org/wiki/CI/CD). To deploy page through Apillon API, follow below steps: 1. Upload website files to Apillon cloud server. @@ -24,18 +25,21 @@ In all cURL examples, parameters with a colon as a prefix should be replaced wit
-#### Response fields +#### Response fields (website) -Each item is an instance of website DTO, with below properties: +Each item is an instance of website class, with below properties: -| Field | Type | Description | -| ----------- | ---------- | ------------------------------------------------------------------------------------------------------------------------ | -| websiteUuid | `string` | Website unique identifier | -| name | `string` | Website name | -| description | `string` | Website description | -| domain | `string` | Website domain. This property needs to be specified, so that Apillon is able to create SSL Certificates for IPFS gateway | -| createTime | `DateTime` | Item create time | -| updateTime | `DateTime` | Item last update time | +| Field | Type | Description | +| -------------- | ---------- | ------------------------------------------------------------------------------------------------------------------------ | +| websiteUuid | `string` | Website unique identifier | +| name | `string` | Website name | +| description | `string` | Website description | +| domain | `string` | Website domain. This property needs to be specified, so that Apillon is able to create SSL Certificates for IPFS gateway | +| bucketUuid | `string` | Uuid of bucket for file upload | +| ipnsStaging | `string` | Staging IPNS. Set if deployment to staging environment exists | +| ipnsProduction | `string` | Production IPNS. | +| createTime | `DateTime` | Item create time | +| updateTime | `DateTime` | Item last update time |
@@ -69,12 +73,15 @@ curl --location --request GET "https://api.apillon.io/storage/buckets?search=My "items": [ ... { - "websiteUuid": "851595b6-ac6d-11ed-96a4-02420a000705", + "createTime": "2023-10-11T10:51:13.000Z", + "updateTime": "2023-10-11T10:51:13.000Z", + "websiteUuid": "5fc7df41-f311-410d-8cb3-998198999a48", "name": "My website", "description": null, - "domain": "https://www.website.si", - "createTime": "2023-01-27T12:31:34.000Z", - "updateTime": "2023-02-14T13:43:10.000Z" + "domain": null, + "bucketUuid": "1938a45c-3a54-43ee-af08-3abe90265f46", + "ipnsStaging": null, + "ipnsProduction": null } ... ], @@ -99,10 +106,13 @@ curl --location --request GET "https://api.apillon.io/storage/buckets?search=My #### Body fields -| Name | Type | Description | Required | -| ----------- | -------- | -------------------- | -------- | -| name | `string` | Website name. | true | -| description | `string` | Website description. | false | +| Name | Type | Description | Required | +| ----------- | -------- | ------------------------------------------------------------------------------------------------------------------------------ | -------- | +| name | `string` | Website name. | true | +| description | `string` | Website description. | false | +| domain | `string` | Domain, where website will be accessible. If this is not specified in this API call, it can be later set in developer console. | false | + +#### Possible errors | Code | Description | | -------- | --------------------------------------- | @@ -110,7 +120,7 @@ curl --location --request GET "https://api.apillon.io/storage/buckets?search=My #### Response -Response is an instance of website DTO, described above. +Response is an instance of [website class](#response-fields-website), described above.
@@ -123,7 +133,9 @@ curl --location --request POST "https://api.apillon.io/hosting/websites" \ --header "Authorization: Basic :credentials" \ --header "Content-Type: application/json" \ --data "{ - \"name\": \"My website\" + \"name\": \"My awesome website\", + \"description\": \"My unstoppable website\", + \"domain\": \"example-domain.io\" }" ``` @@ -134,16 +146,16 @@ curl --location --request POST "https://api.apillon.io/hosting/websites" \ ```json { - "id": "489f33ac-eef7-4599-b9c7-d6022f3dbf6b", + "id": "e37749a4-b6b1-47ce-8eaf-3a6a9da15be7", "status": 201, "data": { - "createTime": "2023-10-10T20:36:08.782Z", - "updateTime": "2023-10-10T20:36:08.782Z", - "websiteUuid": "5b8d1943-afd9-4eb7-ba88-bd73af1445fb", - "name": "My website", - "description": null, - "domain": null, - "bucketUuid": "9c9aec59-8ea1-4522-bfe0-37a69284c294", + "createTime": "2023-10-13T07:41:30.931Z", + "updateTime": "2023-10-13T07:41:30.931Z", + "websiteUuid": "1a15d258-bbc9-459f-b83f-97710da6b983", + "name": "My awesome website", + "description": "My unstoppable website", + "domain": "example-domain.io", + "bucketUuid": "cd299839-dae6-47d0-8fdc-40143163e156", "ipnsStaging": null, "ipnsProduction": null } @@ -179,15 +191,7 @@ curl --location --request POST "https://api.apillon.io/hosting/websites" \ #### Response fields -| Field | Type | Description | -| -------------- | -------- | ------------------------------------------------------------------------ | -| websiteUuid | `string` | Website unique identifier | -| name | `string` | Website name | -| description | `string` | Website description | -| domain | `string` | Domain for production environment | -| bucketUuid | `string` | UUID of bucket, for file upload | -| ipnsStaging | `string` | IPNS name of staging version. Use this to access website on IPFS gateway | -| ipnsProduction | `string` | IPNS name of production version | +Response is an instance of [website class](#response-fields-website), described above.
@@ -207,16 +211,18 @@ curl --location --request GET "https://api.apillon.io/hosting/websites/:websiteU ```json { - "id": "0eb223ce-51c0-4a9b-96ce-331a1cd99603", + "id": "a299ed8f-b682-4411-9fd9-eb3a3da31887", "status": 200, "data": { - "websiteUuid": "a1d90d2c-f167-4889-8620-204862833851", - "name": "My test page", - "description": null, - "domain": "", - "bucketUuid": "57aef0fc-84cb-4564-9af2-0f7bfc0ef729", - "ipnsStaging": "k2k4r8p6fvcyq5qogaqdtvmqn5vyvyy3khut1llkrz13ls16ocp4gojx", - "ipnsProduction": "k2k4r8ng8nqexubrmbwnhsuu1d6n4ebgnxsbdcu9gxk8uv3l67098hge" + "createTime": "2023-10-13T07:41:30.000Z", + "updateTime": "2023-10-13T07:41:30.000Z", + "websiteUuid": "1a15d258-bbc9-459f-b83f-97710da6b983", + "name": "My awesome website", + "description": "My unstoppable website", + "domain": "example-domain.io", + "bucketUuid": "cd299839-dae6-47d0-8fdc-40143163e156", + "ipnsStaging": null, + "ipnsProduction": null } } ``` @@ -243,9 +249,10 @@ curl --location --request GET "https://api.apillon.io/hosting/websites/:websiteU #### Body fields -| Name | Type | Description | Required | -| ----- | ------- | ------------------------ | -------- | -| files | `array` | Array of files metadata. | true | +| Name | Type | Description | Required | +| ----------- | -------- | ------------------------------------------------------------------------------------------------------------------------- | -------- | +| files | `array` | Array of files metadata. | true | +| sessionUuid | `string` | Session unique key. If not specified, API generates new one. It is possible to use same sessionUuid in multiple requests. | false | Each file metadata object in `files` array, contain below properties. @@ -262,15 +269,14 @@ Each file metadata object in `files` array, contain below properties. | 40406010 | Website does not exists | | 42200040 | Request body is missing a `files` field. | | 42200008 | Request body file object is missing a `fileName` field. | -| 40006002 | Website has reached max size limit. | | 50006003 | Internal error - Apillon was unable to generate upload URL. | #### Response -| Name | Type | Description | -| ----------- | -------- | ----------------------------------------------------------------------------------- | -| sessionUuid | `string` | Session unique key, which is later used to end upload and transfer files ti website | -| files | `array` | Array of files metadata. | +| Name | Type | Description | +| ----------- | -------- | ------------------------------------------------------------------------------------ | +| sessionUuid | `string` | Session unique key, which is later used to end upload and transfer files to website. | +| files | `array` | Array of files metadata. | Files in request body are returned in response `data.files` property. Each file is equipped with `url` and `fileUuid`. All properties are displayed below. @@ -382,10 +388,10 @@ curl --location --request PUT "https://sync-to-ipfs-queue.s3.eu-west-1.amazonaws #### URL parameters -| Name | Description | Required | -| ----------- | ------------------------------------------------------------------------------------- | -------- | -| websiteUuid | Unique key of website. Key is displayed in developer dashboard. | true | -| sessionUuid | Session uuid, recieved in [get URL for upload request](#post-storagebucketuuidupload) | true | +| Name | Description | Required | +| ----------- | ----------------------------------------------------------------------------------------------- | -------- | +| websiteUuid | Unique key of website. | true | +| sessionUuid | Session uuid, passed or recieved in [get URL for upload request](#post-storagebucketuuidupload) | true | #### Possible errors @@ -408,9 +414,6 @@ Api respond with status `200 OK` , if operation is successfully executed. curl --location --request POST "https://api.apillon.io/hosting/websites/:websiteUuid/upload/:sessionUuid/end" \ --header "Authorization: Basic :credentials" \ --header "Content-Type: application/json" \ ---data-raw "{ - \"directSync\": true -}" ``` @@ -456,7 +459,7 @@ curl --location --request POST "https://api.apillon.io/hosting/websites/:website | Status | Description | | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| 1 | Uploaded files are deployed to staging environment. Website will be available through staging IPNS link | +| 1 | Uploaded files are deployed to staging(preview) environment. Website will be available through staging IPNS link | | 2 | Files from current staging environment are deployed to production environment. Website is pinned to CRUST, replicated and available through production IPNS link | | 3 | Same as `2`, only that the source are uploaded files, not files in staging environment. | @@ -480,14 +483,17 @@ In `production`, this CID is pinned to CRUST and replicated to other nodes. ##### Deployment fields -| Field | Type | Description | -| ---------------- | -------- | --------------------------------------------------------------------------------------------- | -| id | `number` | Deployment internal number | -| environment | `number` | Environment to where website will be deployed | -| deploymentStatus | `number` | Current status of deployment. Possible values are listed below. | -| cid | `string` | When deployment is successful, CID points to directory on IPFS, where this page is accessible | -| size | `number` | Size of website | -| number | `number` | Deployment serial number - for this environment | +| Field | Type | Description | +| ---------------- | ---------- | --------------------------------------------------------------------------------------------- | +| deploymentUuid | `string` | Deployment unique identifier | +| environment | `number` | Environment to where website will be deployed | +| deploymentStatus | `number` | Current status of deployment. Possible values are listed below. | +| cid | `string` | When deployment is successful, CID points to directory on IPFS, where this page is accessible | +| cidv1 | `string` | CID version 1 | +| size | `number` | Size of website | +| number | `number` | Deployment serial number - for this environment | +| createTime | `DateTime` | Deployment create time | +| updateTime | `DateTime` | Deployment last update time | ##### Website deployment statuses @@ -522,17 +528,18 @@ curl --location --request POST "https://api.apillon.io/hosting/websites/:website ```json { - "id": "32eff81a-6b0b-4a92-a5cb-e5cebf6d6c28", + "id": "dfe79ed9-e2fe-4195-b829-053dee1e6fd1", "status": 200, "data": { - "id": 91, - "createTime": "2023-10-11T19:06:55.347Z", - "updateTime": "2023-10-11T19:06:55.347Z", + "createTime": "2023-10-13T12:23:51.721Z", + "updateTime": "2023-10-13T12:23:51.721Z", + "deploymentUuid": "583790dc-7b56-4563-8a33-d88243eed11e", "environment": 1, "deploymentStatus": 0, "cid": null, + "cidv1": null, "size": null, - "number": 5 + "number": 1 } } ``` @@ -560,7 +567,7 @@ curl --location --request POST "https://api.apillon.io/hosting/websites/:website #### Response fields -Each item in list is a [deployment DTO](#deployment-fields) instance. +Each item in list is a [deployment](#deployment-fields) instance.
@@ -594,24 +601,26 @@ curl --location --request GET "https://api.apillon.io/hosting/websites/:websiteU "items": [ ... { - "id": 90, - "createTime": "2023-10-11T19:04:40.000Z", - "updateTime": "2023-10-11T19:05:06.000Z", - "environment": 1, - "deploymentStatus": 100, - "cid": null, - "size": 11, - "number": 4 + "createTime": "2023-10-13T12:28:39.000Z", + "updateTime": "2023-10-13T12:29:15.000Z", + "deploymentUuid": "12b47aef-6a01-4799-a4da-79ea7595237d", + "environment": 2, + "deploymentStatus": 10, + "cid": "QmTF31ediusaBTNn2Z1Jtr5fF1iVp9oDA8EWz9my6aVx8V", + "cidv1": "bafybeici3ivncsgfszf7tbmttayyjk6hs25354zs5nczujv44rco4qiv7y", + "size": 41, + "number": 1 }, { - "id": 91, - "createTime": "2023-10-11T19:06:55.000Z", - "updateTime": "2023-10-11T19:07:20.000Z", + "createTime": "2023-10-13T12:23:51.000Z", + "updateTime": "2023-10-13T12:24:17.000Z", + "deploymentUuid": "583790dc-7b56-4563-8a33-d88243eed11e", "environment": 1, "deploymentStatus": 10, - "cid": "QmeY1amT7yUcSzjehwH7LcEwKNdTZnZnSYLXPnABTzUq8d", - "size": 11, - "number": 5 + "cid": "QmTF31ediusaBTNn2Z1Jtr5fF1iVp9oDA8EWz9my6aVx8V", + "cidv1": "bafybeici3ivncsgfszf7tbmttayyjk6hs25354zs5nczujv44rco4qiv7y", + "size": 41, + "number": 1 } ... ], @@ -629,17 +638,17 @@ curl --location --request GET "https://api.apillon.io/hosting/websites/:websiteU > Endpoint to get deployment. -
GET /hosting/websites/:websiteUuid/deployments/:deploymentId
+
GET /hosting/websites/:websiteUuid/deployments/:deployment_uuid
#### URL parameters -| Name | Description | Required | -| ------------ | ------------------------------------------------------------------- | -------- | -| websiteUuid | Website UUID, visible in developer console website overview | true | -| deploymentId | Deployment internal number, returned from `deploy` website endpoint | true | +| Name | Description | Required | +| --------------- | --------------------------------------------------------------------- | -------- | +| websiteUuid | Website UUID, visible in developer console website overview | true | +| deployment_uuid | Deployment unique identifier, returned from `deploy` website endpoint | true | #### Possible errors @@ -649,16 +658,7 @@ curl --location --request GET "https://api.apillon.io/hosting/websites/:websiteU #### Response fields -`Data` property is a [deployment DTO](#deployment-fields) instance. - -Deployment goes through different stages and each stage updates `deploymentStatus`. Possible deployment statuses: - -| Status | Description | -| ------ | --------------------- | -| 0 | Deployment initiated | -| 1 | Deploying | -| 10 | Deployment successful | -| 100 | Deployment failed | +`Data` property is a [deployment](#deployment-fields) instance.
@@ -681,14 +681,15 @@ curl --location --request GET "https://api.apillon.io/hosting/websites/:websiteU "id": "2d7d1b0c-15b1-4816-9aec-857182c7b617", "status": 200, "data": { - "id": 91, - "createTime": "2023-10-11T19:06:55.000Z", - "updateTime": "2023-10-11T19:07:20.000Z", + "createTime": "2023-10-13T12:23:51.000Z", + "updateTime": "2023-10-13T12:24:17.000Z", + "deploymentUuid": "583790dc-7b56-4563-8a33-d88243eed11e", "environment": 1, "deploymentStatus": 10, - "cid": "QmeY1amT7yUcSzjehwH7LcEwKNdTZnZnSYLXPnABTzUq8d", - "size": 11, - "number": 5 + "cid": "QmTF31ediusaBTNn2Z1Jtr5fF1iVp9oDA8EWz9my6aVx8V", + "cidv1": "bafybeici3ivncsgfszf7tbmttayyjk6hs25354zs5nczujv44rco4qiv7y", + "size": 41, + "number": 1 } } ``` From a7f5b082b606fbee4400e3f4ebd3607331af2c35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vinko=20=C5=A0mid?= Date: Tue, 17 Oct 2023 09:28:56 +0200 Subject: [PATCH 5/7] Removed concurring content in storage docs. --- build/4-storage-api.md | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/build/4-storage-api.md b/build/4-storage-api.md index a9f39b16..3caa60d1 100644 --- a/build/4-storage-api.md +++ b/build/4-storage-api.md @@ -11,23 +11,13 @@ In all cURL examples, parameters with a colon as a prefix should be replaced wit ### List buckets -> API to list all buckets in project. Items are paginated and can be filtered and ordered through query parameters. +> API to list all buckets in project. Items are paginated and can be filtered and ordered through query parameters. This is a [listing request](3-apillon-api.md#listing-requests). #### GET /storage/buckets
-#### Query parameters - -| Name | Description | Required | -| ------- | ------------------------------------------------------------------------------------------------- | -------- | -| search | Search by bucket name. | false | -| page | Buckets are paginated by default. This parameter is used to get collections from a specific page. | false | -| limit | Number of items on a page (default: 20). | false | -| orderBy | One or multiple properties, separated by a comma, used to order data. | false | -| desc | `Boolean` values, mapped to the index of the `orderBy` parameter. Defaults to false. | false | - #### Response fields (bucket) Each item is an instance of bucket model, with below properties: @@ -40,7 +30,7 @@ Each item is an instance of bucket model, with below properties: | bucketType | `integer` | Item type with possible values `1`(storage bucket), `2`(website bucket) and `3`(nft bucket) | | name | `string` | Bucket name | | description | `string` | Bucket description | -| size | `integer` | Size of bucket | +| size | `integer` | Size of bucket in bytes |
@@ -690,21 +680,19 @@ curl --location --request GET "https://api.apillon.io/storage/buckets/:bucketUui | Name | Description | required | | ---------- | -------------------------------------------------------------- | -------- | | bucketUuid | Unique key of bucket. Key is displayed on developer dashboard. | true | -| fileUuid | File internal ID, UUID, or CID. | true | +| fileUuid | File unique identifier. | true | #### Possible errors -| Code | Description | -| -------- | ---------------------------- | -| 40406005 | File does not exist. | -| 40006009 | File is marked for deletion. | +| Code | Description | +| -------- | ------------------------------------ | +| 40406005 | File does not exist. | +| 40006009 | File is already marked for deletion. | #### Response fields The response of delete function is a boolean value, depends if deletion was successful. -**Note:** The `status` property of file is 8. This means the file is marked for deletion and will be deleted after a certain period. -

From 6cde6ac80e79bb8fb257ff5cec082682b064fa14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vinko=20=C5=A0mid?= Date: Tue, 24 Oct 2023 09:18:55 +0200 Subject: [PATCH 6/7] Docs for wrapping files to IPFS CID. --- build/4-storage-api.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/build/4-storage-api.md b/build/4-storage-api.md index 3caa60d1..64b844cd 100644 --- a/build/4-storage-api.md +++ b/build/4-storage-api.md @@ -285,6 +285,8 @@ curl --location --request PUT "https://sync-to-ipfs-queue.s3.eu-west-1.amazonaws > Once files are uploaded to cloud server via received URL, trigger sync of files to IPFS and CRUST. +\*\*Note: Files in session can be wrapped to CID on IPFS via `wrapWithDirectory` body field. This means that directory gets it's own CID and it's content cannot be modified afterwards. +
POST /storage/:bucketUuid/upload/:sessionUuid/end
@@ -297,6 +299,13 @@ curl --location --request PUT "https://sync-to-ipfs-queue.s3.eu-west-1.amazonaws | bucketUuid | Unique key of bucket. Key is displayed in developer dashboard. | true | | sessionUuid | Session uuid, recieved in [upload to bucket](#upload-to-bucket) | true | +#### Body fields + +| Name | Type | Description | Required | +| ----------------- | --------- | --------------------------------------- | -------- | +| wrapWithDirectory | `boolean` | Wrap uploaded files to IPFS directory | false | +| directoryPath | `string` | Path to wrapped directory inside bucket | false | + #### Possible errors | Code | Description | From 20820e9124b4f45c257d0bc5ee040b59cdf4c9b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vinko=20=C5=A0mid?= Date: Tue, 7 Nov 2023 13:55:49 +0100 Subject: [PATCH 7/7] Added documentation for query parameters in GET storage/buckets endpoint. --- build/4-storage-api.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/build/4-storage-api.md b/build/4-storage-api.md index 64b844cd..bf4b27df 100644 --- a/build/4-storage-api.md +++ b/build/4-storage-api.md @@ -18,6 +18,14 @@ In all cURL examples, parameters with a colon as a prefix should be replaced wit
+#### Query parameters + +All query parameters from [listing request](3-apillon-api.md#listing-requests) plus: + +| Name | Description | Required | +| ---------- | ----------------------------------------------------------------------------- | -------- | +| bucketType | Type of bucket: `1`(storage bucket), `2`(website bucket) and `3`(nft bucket). | false | + #### Response fields (bucket) Each item is an instance of bucket model, with below properties: