├── .github
└── workflows
│ ├── json-schema.yml
│ └── markdown.yml
├── LICENSE
├── README.md
├── brand
├── icon_cube.pdf
├── icon_cube.png
├── icon_cube.svg
├── icon_unfolded.pdf
├── icon_unfolded.png
├── icon_unfolded.svg
├── info.pdf
├── info.png
├── logo_square_dark.pdf
├── logo_square_dark.png
├── logo_square_dark.svg
├── logo_square_light.pdf
├── logo_square_light.png
├── logo_square_light.svg
├── logo_wide_dark.pdf
├── logo_wide_dark.png
├── logo_wide_dark.svg
├── logo_wide_light.pdf
├── logo_wide_light.png
└── logo_wide_light.svg
├── json-schema
├── datablock
│ ├── asset_list_query.json
│ ├── authors.json
│ ├── branding.json
│ ├── dimensions.json
│ ├── fetch.download.json
│ ├── fetch.from_archive.json
│ ├── format.blend.json
│ ├── format.json
│ ├── format.obj.json
│ ├── handle.archive.json
│ ├── handle.loose_environment_map.json
│ ├── handle.loose_material_map.json
│ ├── handle.native.json
│ ├── implementation_list_query.json
│ ├── keywords.json
│ ├── license.json
│ ├── link.loose_material.json
│ ├── link.mtlx_material.json
│ ├── next_query.json
│ ├── preview_image_supplemental.json
│ ├── preview_image_thumbnail.json
│ ├── provider_configuration.json
│ ├── provider_reconfiguration.json
│ ├── response_statistics.json
│ ├── store.json
│ ├── text.json
│ ├── unlock_balance.json
│ ├── unlock_queries.json
│ ├── user.json
│ └── web_references.json
├── endpoint
│ ├── asset_list.json
│ ├── auto.json
│ ├── connection_status.json
│ ├── implementation_list.json
│ ├── initialization.json
│ └── unlock.json
└── template
│ ├── fixed_query.json
│ ├── meta.json
│ └── variable_query.json
└── spec.md
/.github/workflows/json-schema.yml:
--------------------------------------------------------------------------------
1 | name: JSON Schema Validation
2 | on: [pull_request]
3 | jobs:
4 | validate-json-schema:
5 | name: JSON Schema Check
6 | runs-on: ubuntu-latest
7 | steps:
8 | - uses: actions/checkout@v4
9 | - name: Check if json schema was changed
10 | id: check-for-changed-schemas
11 | uses: tj-actions/changed-files@v41
12 | with:
13 | files: |
14 | json-schema/*/*.json
15 | - name: Validate JSON Schema files
16 | if: steps.check-for-changed-schemas.outputs.any_changed == 'true'
17 | uses: cardinalby/schema-validator-action@v3
18 | with:
19 | file: "json-schema/*/*.json"
20 | schema: https://json-schema.org/draft/2020-12/schema
21 |
--------------------------------------------------------------------------------
/.github/workflows/markdown.yml:
--------------------------------------------------------------------------------
1 | name: Markdown Link Validation
2 | on: [pull_request]
3 | jobs:
4 | markdown-link-check:
5 | name: Markdown Link Check
6 | runs-on: ubuntu-latest
7 | steps:
8 | - uses: actions/checkout@v4
9 | - name: Check if spec.md was changed
10 | id: check-for-changed-spec
11 | uses: tj-actions/changed-files@v41
12 | with:
13 | files: |
14 | spec.md
15 | - name: Validate Markdown Links
16 | uses: gaurav-nelson/github-action-markdown-link-check@v1
17 | if: steps.check-for-changed-spec.outputs.any_changed == 'true'
18 | with:
19 | use-quiet-mode: "yes"
20 | use-verbose-mode: "yes"
21 | config-file: "mlc_config.json"
22 | file-path: ./spec.md
23 | max-depth: 3
24 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 AssetFetch
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | # The AssetFetch Specification
6 |
7 | **AssetFetch** is an HTTP- and JSON-based system for browsing, retrieving and handling/importing digital assets for media creation.
8 | The AssetFetch Protocol aims to provide a standardized way for artists to browse libraries of downloadable assets offered by providers *outside* their current production environment/pipeline, such as those of commercial or free 3D asset vendors, marketplaces or other repositories of models, textures or adjacent kinds of digital assets.
9 |
10 | It aims to create an artist experience similar to existing proprietary import plugins with less development overhead in order to increase interoperability between vendors and applications and allow more vendors - especially smaller ones - to offer their assets to artists right in the applications where they need them.
11 |
12 | # Features
13 |
14 | - Header-based Authentication.
15 | - Browsing assets with thumbnails, server-side searching and filtering, license data, author data and more.
16 | - Support for multiple resolutions, quality levels or any other kind of variation of assets.
17 | - Support for zipped downloads: Providers can still send metadata for individual asset files, even if the actual download arrives in just one zip file.
18 | - Ways for checking compatibility with different open or vendor-native formats: The provider offers metadata for multiple versions of the same asset which the client can use to judge whether it will be able to actually import the file BEFORE downloading it, as best as possible (100% certainty will be impossible).
19 | - Purchasing assets (even composite assets that require multiple purchases) through an "asset unlocking" system. The actual payment isn't handled by AF, users still need to sign up on the provider's website.
20 | - Ways of linking loose files together to cover "loose materials" to make the distribution of PBR materials and HDRIs easier.
21 | - Theming and branding options for providers with banner images, if the client chooses to display those.
22 | - Custom metadata for common file formats.
23 |
24 | # This is a Work-In-Progress
25 | Everything here at the moment should be regarded as a starting-off point for future testing and discussion about how the transfer of 3D assets from vendors to clients can be made made more open and interoperable.
26 | There are still numerous milestones to hit before a version 1.0 can be released:
27 |
28 | - Create better examples for basically everything. This includes examples for every element of the specification as well as more general examples and user stories to better illustrate what AssetFetch is, how it works and the value it delivers both for asset vendors and users.
29 |
30 | - Create proof-of-concept implementations both for the provider- and the client-side in order to demonstrate the viability of the entire system. This will also inevitably lead to changes and clarifications in the spec as problems are encountered and (hopefully) solved.
31 |
32 | - Create more extension-specific datablock definitions for many more formats, both open and application-specific ones (`max`(3DSMax),`ma/mb`(Maya),`uasset`(Unreal Engine),`usda/c/z` (OpenUSD), `gltf/b`(GLTF),...)
33 |
34 | - ...
35 |
36 | # JSON Schema
37 |
38 | JSON-Schemas for AssetFetch are provided in the `/json-schema` subdirectory of this repository.
39 |
40 | # Contributing
41 |
42 | The best way to contribute at this stage is by opening issues with questions, contradictions in the specifications, suggestions for datablocks or any other thoughts about the specification.
43 |
44 | The specification document is written in markdown and therefore easily editable with any text editor.
45 | However, the recommended environment for editing `spec.md` is Visual Studio Code with the following extensions:
46 |
47 | - Markdown Preview Mermaid Support (`bierner.markdown-mermaid`)
48 | - Markdown All-In-One (`yzhang.markdown-all-in-one`)
49 |
50 | To maintain proper document structure, the commands "Format Document" and "Markdown-All-In-One: Add/Update section Numbers" should be used.
51 | All PRs are tested for dead markdown links and syntax issues in the JSON schema.
52 |
--------------------------------------------------------------------------------
/brand/icon_cube.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AssetFetch/spec/397ed9499887a25c46a33e9b2d68fe2c1d96913b/brand/icon_cube.pdf
--------------------------------------------------------------------------------
/brand/icon_cube.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AssetFetch/spec/397ed9499887a25c46a33e9b2d68fe2c1d96913b/brand/icon_cube.png
--------------------------------------------------------------------------------
/brand/icon_cube.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
14 |
--------------------------------------------------------------------------------
/brand/icon_unfolded.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AssetFetch/spec/397ed9499887a25c46a33e9b2d68fe2c1d96913b/brand/icon_unfolded.pdf
--------------------------------------------------------------------------------
/brand/icon_unfolded.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AssetFetch/spec/397ed9499887a25c46a33e9b2d68fe2c1d96913b/brand/icon_unfolded.png
--------------------------------------------------------------------------------
/brand/icon_unfolded.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
23 |
--------------------------------------------------------------------------------
/brand/info.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AssetFetch/spec/397ed9499887a25c46a33e9b2d68fe2c1d96913b/brand/info.pdf
--------------------------------------------------------------------------------
/brand/info.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AssetFetch/spec/397ed9499887a25c46a33e9b2d68fe2c1d96913b/brand/info.png
--------------------------------------------------------------------------------
/brand/logo_square_dark.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AssetFetch/spec/397ed9499887a25c46a33e9b2d68fe2c1d96913b/brand/logo_square_dark.pdf
--------------------------------------------------------------------------------
/brand/logo_square_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AssetFetch/spec/397ed9499887a25c46a33e9b2d68fe2c1d96913b/brand/logo_square_dark.png
--------------------------------------------------------------------------------
/brand/logo_square_dark.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
55 |
--------------------------------------------------------------------------------
/brand/logo_square_light.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AssetFetch/spec/397ed9499887a25c46a33e9b2d68fe2c1d96913b/brand/logo_square_light.pdf
--------------------------------------------------------------------------------
/brand/logo_square_light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AssetFetch/spec/397ed9499887a25c46a33e9b2d68fe2c1d96913b/brand/logo_square_light.png
--------------------------------------------------------------------------------
/brand/logo_square_light.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
55 |
--------------------------------------------------------------------------------
/brand/logo_wide_dark.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AssetFetch/spec/397ed9499887a25c46a33e9b2d68fe2c1d96913b/brand/logo_wide_dark.pdf
--------------------------------------------------------------------------------
/brand/logo_wide_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AssetFetch/spec/397ed9499887a25c46a33e9b2d68fe2c1d96913b/brand/logo_wide_dark.png
--------------------------------------------------------------------------------
/brand/logo_wide_dark.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
55 |
--------------------------------------------------------------------------------
/brand/logo_wide_light.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AssetFetch/spec/397ed9499887a25c46a33e9b2d68fe2c1d96913b/brand/logo_wide_light.pdf
--------------------------------------------------------------------------------
/brand/logo_wide_light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AssetFetch/spec/397ed9499887a25c46a33e9b2d68fe2c1d96913b/brand/logo_wide_light.png
--------------------------------------------------------------------------------
/brand/logo_wide_light.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
55 |
--------------------------------------------------------------------------------
/json-schema/datablock/asset_list_query.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json-schema.org/draft/2020-12/schema",
3 | "title": "Datablock: asset_list_query",
4 | "$id": "af.datablock.asset_list_query",
5 | "description": "Describes the variable query for fetching the list of available assets from a provider.",
6 | "$ref": "../template/variable_query.json"
7 | }
--------------------------------------------------------------------------------
/json-schema/datablock/authors.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json-schema.org/draft/2020-12/schema",
3 | "title": "AF Datablock: authors",
4 | "$id": "af.datablock.authors",
5 | "description": "Is used communicate the author(s) of a particular asset.",
6 | "type": "array",
7 | "additionalProperties":false,
8 | "items": {
9 | "type": "object",
10 | "additionalProperties": false,
11 | "properties": {
12 | "name": {
13 | "type": "string"
14 | },
15 | "uri": {
16 | "type": [
17 | "string",
18 | "null"
19 | ],
20 | "format": "uri"
21 | },
22 | "role": {
23 | "type": [
24 | "string",
25 | "null"
26 | ]
27 | }
28 | },
29 | "required": [
30 | "name"
31 | ]
32 | }
33 | }
--------------------------------------------------------------------------------
/json-schema/datablock/branding.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json-schema.org/draft/2020-12/schema",
3 | "title": "AF Datablock: branding",
4 | "$id": "af.datablock.branding",
5 | "description": "Contains brand information about the provider, MAY be used by the client to customize the user interface.",
6 | "type": "object",
7 | "properties": {
8 | "color_accent": {
9 | "type": [
10 | "string",
11 | "null"
12 | ],
13 | "pattern": "[0-9a-f]{6}"
14 | },
15 | "logo_square_uri": {
16 | "type": [
17 | "string",
18 | "null"
19 | ],
20 | "format": "uri"
21 | },
22 | "logo_wide_uri": {
23 | "type": [
24 | "string",
25 | "null"
26 | ],
27 | "format": "uri"
28 | },
29 | "banner_uri": {
30 | "type": [
31 | "string",
32 | "null"
33 | ],
34 | "format": "uri"
35 | }
36 | },
37 | "required": [],
38 | "additionalProperties": false
39 | }
--------------------------------------------------------------------------------
/json-schema/datablock/dimensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json-schema.org/draft/2020-12/schema",
3 | "title": "Datablock: dimensions",
4 | "$id": "af.datablock.dimensions",
5 | "description": "Contains general information about the physical dimensions of an asset.",
6 | "type": "object",
7 | "properties": {
8 | "width_m": {
9 | "type": [
10 | "number",
11 | "null"
12 | ]
13 | },
14 | "height_m": {
15 | "type": [
16 | "number",
17 | "null"
18 | ]
19 | },
20 | "depth_m": {
21 | "type": [
22 | "number",
23 | "null"
24 | ]
25 | }
26 | },
27 | "required": [],
28 | "additionalProperties": false
29 | }
--------------------------------------------------------------------------------
/json-schema/datablock/fetch.download.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json-schema.org/draft/2020-12/schema",
3 | "title": "Datablock: fetch.download",
4 | "$id": "af.datablock.fetch.download",
5 | "description": "Describes how a component file can be downloaded via HTTP.",
6 | "properties": {
7 | "unlock_query_id": {
8 | "type": [
9 | "string",
10 | "null"
11 | ]
12 | },
13 | "download_query": {
14 | "$ref": "../template/fixed_query.json"
15 | }
16 | },
17 | "additionalProperties": false
18 | }
--------------------------------------------------------------------------------
/json-schema/datablock/fetch.from_archive.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json-schema.org/draft/2020-12/schema",
3 | "title": "Datablock: fetch.from_archive",
4 | "$id": "af.datablock.fetch.from_archive",
5 | "description": "This datablock indicates that this component represents a file from within an archive that needs to be downloaded separately.",
6 | "type": "object",
7 | "properties": {
8 | "archive_component_id": {
9 | "type": "string"
10 | },
11 | "component_sub_path": {
12 | "type": "string"
13 | }
14 | },
15 | "required": [
16 | "archive_component_id",
17 | "component_sub_path"
18 | ],
19 | "additionalProperties": false
20 | }
--------------------------------------------------------------------------------
/json-schema/datablock/format.blend.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json-schema.org/draft/2020-12/schema",
3 | "title": "Datablock: format.blend",
4 | "$id": "af.datablock.format.blend",
5 | "description": "Information about files with the extension `.blend`.",
6 | "type": "object",
7 | "properties": {
8 | "version": {
9 | "type": [
10 | "string",
11 | "null"
12 | ],
13 | "pattern": "^[0-9]+(\\.[0-9]+)?(\\.[0-9]+)?$"
14 | },
15 | "is_asset": {
16 | "type": [
17 | "boolean",
18 | "null"
19 | ]
20 | },
21 | "targets": {
22 | "type": [
23 | "array",
24 | "null"
25 | ],
26 | "items": {
27 | "type": "object",
28 | "required": [
29 | "kind",
30 | "names"
31 | ],
32 | "properties": {
33 | "kind": {
34 | "type": "string",
35 | "enum": [
36 | "actions",
37 | "armatures",
38 | "brushes",
39 | "cache_files",
40 | "cameras",
41 | "collections",
42 | "curves",
43 | "fonts",
44 | "grease_pencils",
45 | "hair_curves",
46 | "images",
47 | "lattices",
48 | "lightprobes",
49 | "lights",
50 | "linestyles",
51 | "masks",
52 | "materials",
53 | "meshes",
54 | "metaballs",
55 | "movieclips",
56 | "node_groups",
57 | "objects",
58 | "paint_curves",
59 | "palettes",
60 | "particles",
61 | "pointclouds",
62 | "scenes",
63 | "screens",
64 | "simulations",
65 | "sounds",
66 | "speakers",
67 | "texts",
68 | "textures",
69 | "volumes",
70 | "workspaces",
71 | "worlds"
72 | ]
73 | },
74 | "names": {
75 | "type": "array",
76 | "items": {
77 | "type": "string"
78 | }
79 | }
80 | }
81 | }
82 | }
83 | },
84 | "required": []
85 | }
--------------------------------------------------------------------------------
/json-schema/datablock/format.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json-schema.org/draft/2020-12/schema",
3 | "title": "Datablock: format",
4 | "$id": "af.datablock.format",
5 | "description": "This is the default format datablock for all file formats that do not have their own dedicated `format.*` datablock.",
6 | "type": "object",
7 | "properties": {
8 | "extension": {
9 | "type": "string",
10 | "pattern": "^\\..*"
11 | },
12 | "mediatype": {
13 | "type": [
14 | "string",
15 | "null"
16 | ]
17 | }
18 | },
19 | "required": [
20 | "extension"
21 | ],
22 | "additionalProperties": false
23 | }
--------------------------------------------------------------------------------
/json-schema/datablock/format.obj.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json-schema.org/draft/2020-12/schema",
3 | "title": "Datablock: format.obj",
4 | "$id": "af.datablock.format.obj",
5 | "type": "object",
6 | "properties": {
7 | "up_axis": {
8 | "type": "string",
9 | "enum": [
10 | "+x",
11 | "-x",
12 | "+y",
13 | "-y",
14 | "+z",
15 | "-z"
16 | ]
17 | },
18 | "front_axis": {
19 | "type": "string",
20 | "enum": [
21 | "+x",
22 | "-x",
23 | "+y",
24 | "-y",
25 | "+z",
26 | "-z"
27 | ]
28 | }
29 | },
30 | "additionalProperties": false,
31 | "required": []
32 | }
--------------------------------------------------------------------------------
/json-schema/datablock/handle.archive.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json-schema.org/draft/2020-12/schema",
3 | "title": "Datablock: handle.archive",
4 | "$id": "af.datablock.handle.archive",
5 | "description": "This datablock indicates that this component represents an archive, containing other component files.",
6 | "type": "object",
7 | "properties": {
8 | "local_directory_path": {
9 | "type": [
10 | "string",
11 | "null"
12 | ],
13 | "pattern": "^\\\/$|^[^\\.|\\\/|\\\\]((?!\\.\\.\\\/|\\\\).)*\\\/$"
14 | },
15 | "extract_fully": {
16 | "type": "boolean"
17 | }
18 | },
19 | "required": [
20 | "extract_fully"
21 | ],
22 | "if": {
23 | "properties": {
24 | "extract_fully": {
25 | "const": true
26 | }
27 | }
28 | },
29 | "then": {
30 | "properties": {
31 | "local_directory_path": {
32 | "type": "string"
33 | }
34 | },
35 | "required": [
36 | "local_directory_path"
37 | ]
38 | },
39 | "additionalProperties": false
40 | }
--------------------------------------------------------------------------------
/json-schema/datablock/handle.loose_environment_map.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json-schema.org/draft/2020-12/schema",
3 | "title": "Datablock: role.loose_environment_map",
4 | "$id": "af.datablock.role.loose_environment_map",
5 | "description": "Marks a component as an environment map.",
6 | "type": "object",
7 | "additionalProperties": false,
8 | "properties": {
9 | "environment_name": {
10 | "type": [
11 | "string",
12 | "null"
13 | ]
14 | },
15 | "projection": {
16 | "type": [
17 | "string",
18 | "null"
19 | ],
20 | "enum": [
21 | "equirectangular",
22 | "mirror_ball"
23 | ]
24 | }
25 | }
26 | }
--------------------------------------------------------------------------------
/json-schema/datablock/handle.loose_material_map.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json-schema.org/draft/2020-12/schema",
3 | "title": "Datablock: role.loose_material_map",
4 | "$id": "af.datablock.role.loose_material",
5 | "description": "Indicates that this component is part of a loose material as a material map.",
6 | "type": "object",
7 | "additionalProperties": false,
8 | "properties": {
9 | "material_name": {
10 | "type": "string"
11 | },
12 | "map": {
13 | "type": "string",
14 | "enum": [
15 | "albedo",
16 | "roughness",
17 | "metallic",
18 | "diffuse",
19 | "glossiness",
20 | "specular",
21 | "height",
22 | "normal+y",
23 | "normal-y",
24 | "opacity",
25 | "ambient_occlusion",
26 | "emission"
27 | ]
28 | }
29 | },
30 | "required": [
31 | "material_name",
32 | "map"
33 | ]
34 | }
--------------------------------------------------------------------------------
/json-schema/datablock/handle.native.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json-schema.org/draft/2020-12/schema",
3 | "title": "Datablock: role.native",
4 | "$id": "af.datablock.role.native",
5 | "description": "This datablock indicates that this file should be handled by the host application's native import functionality.",
6 | "type": "object",
7 | "properties": {},
8 | "additionalProperties": false
9 | }
--------------------------------------------------------------------------------
/json-schema/datablock/implementation_list_query.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json-schema.org/draft/2020-12/schema",
3 | "title": "Datablock: implemementation_list_query",
4 | "$id": "af.datablock.implementation_list_query",
5 | "description": "Describes the variable query for fetching the list of available implementations for an asset from a provider.",
6 | "$ref": "../template/variable_query.json"
7 | }
--------------------------------------------------------------------------------
/json-schema/datablock/keywords.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json-schema.org/draft/2020-12/schema",
3 | "title": "Datablock: keywords",
4 | "$id": "af.datablock.keywords",
5 | "description": "Contains keywords or tags that the client MAY use for local asset organization.",
6 | "type": "array",
7 | "items": {
8 | "type": "string"
9 | }
10 | }
--------------------------------------------------------------------------------
/json-schema/datablock/license.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json-schema.org/draft/2020-12/schema",
3 | "title": "License Datablock",
4 | "$id": "af.datablock.license",
5 | "description": "Contains license information.",
6 | "type": "object",
7 | "additionalProperties": false,
8 | "properties": {
9 | "license_spdx": {
10 | "type": [
11 | "string",
12 | "null"
13 | ]
14 | },
15 | "license_uri": {
16 | "type": [
17 | "string",
18 | "null"
19 | ],
20 | "format": "uri"
21 | }
22 | },
23 | "required": []
24 | }
--------------------------------------------------------------------------------
/json-schema/datablock/link.loose_material.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json-schema.org/draft/2020-12/schema",
3 | "title": "Datablock: link.loose_material",
4 | "$id": "af.datablock.link.loose_material",
5 | "description": "Indicates that this component uses one or multiple materials defined using `handle.loose_material_map` datablocks.",
6 | "additionalItems": false,
7 | "type": "object",
8 | "additionalProperties": false,
9 | "properties": {
10 | "material_name": {
11 | "type": "string"
12 | }
13 | },
14 | "required": [
15 | "material_name"
16 | ]
17 | }
--------------------------------------------------------------------------------
/json-schema/datablock/link.mtlx_material.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json-schema.org/draft/2020-12/schema",
3 | "title": "Datablock: link.mtlx_material",
4 | "$id": "af.datablock.link.mtlx_material",
5 | "description": "Indicates that this component makes use of a material defined in a mtlx document represented by another component.",
6 | "type": "object",
7 | "properties": {
8 | "mtlx_component_id": {
9 | "type": "string"
10 | },
11 | "mtlx_material": {
12 | "type": "string"
13 | }
14 | },
15 | "required": [
16 | "mtlx_component"
17 | ],
18 | "additionalProperties": false
19 | }
--------------------------------------------------------------------------------
/json-schema/datablock/next_query.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json-schema.org/draft/2020-12/schema",
3 | "title": "Datablock: next_query",
4 | "$id": "af.datablock.next_query",
5 | "description": "This datablock describes how to fetch more results for the current query.",
6 | "$ref": "../template/fixed_query.json"
7 | }
--------------------------------------------------------------------------------
/json-schema/datablock/preview_image_supplemental.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json-schema.org/draft/2020-12/schema",
3 | "title": "Datablock: preview_image_supplemental",
4 | "$id": "af.datablock.preview_image_supplemental",
5 | "description": "Contains a list of preview images associated to an asset.",
6 | "type": "array",
7 | "items": {
8 | "type": "object",
9 | "additionalProperties": false,
10 | "properties": {
11 | "alt": {
12 | "type": "string"
13 | },
14 | "uri": {
15 | "type": "string",
16 | "format": "uri"
17 | }
18 | },
19 | "required": [
20 | "uri"
21 | ]
22 | }
23 | }
--------------------------------------------------------------------------------
/json-schema/datablock/preview_image_thumbnail.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json-schema.org/draft/2020-12/schema",
3 | "title": "Datablock: preview_image_thumbnail",
4 | "$id": "af.datablock.preview_image_thumbnail",
5 | "description": "Contains information about a thumbnail image for an asset.",
6 | "type": "object",
7 | "additionalProperties": false,
8 | "properties": {
9 | "alt": {
10 | "type": "string"
11 | },
12 | "uris": {
13 | "properties": {},
14 | "patternProperties": {
15 | "[0-9]+": {
16 | "type": "string",
17 | "format": "uri"
18 | }
19 | },
20 | "additionalProperties": false,
21 | "minProperties": 1
22 | }
23 | },
24 | "required": [
25 | "uris"
26 | ]
27 | }
--------------------------------------------------------------------------------
/json-schema/datablock/provider_configuration.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json-schema.org/draft/2020-12/schema",
3 | "title": "Datablock: provider_configuration",
4 | "$id": "af.datablock.provider_configuration",
5 | "description": "Describes which headers the provider expects to receive from the client on every subsequent request.",
6 | "type": "object",
7 | "additionalProperties": false,
8 | "properties": {
9 | "acquisition_uri": {
10 | "type": "string",
11 | "format": "uri"
12 | },
13 | "acquisition_uri_title": {
14 | "type": "string"
15 | },
16 | "headers": {
17 | "type": "array",
18 | "items": {
19 | "type": "object",
20 | "properties": {
21 | "name": {
22 | "type": "string"
23 | },
24 | "default": {
25 | "type": "string"
26 | },
27 | "is_required": {
28 | "type": "boolean"
29 | },
30 | "is_sensitive": {
31 | "type": "boolean"
32 | },
33 | "prefix": {
34 | "type": "string"
35 | },
36 | "suffix": {
37 | "type": "string"
38 | },
39 | "title": {
40 | "type": "string"
41 | },
42 | "encoding": {
43 | "type": "string",
44 | "enum": [
45 | "plain",
46 | "base64"
47 | ]
48 | }
49 | },
50 | "additionalProperties": false,
51 | "required": [
52 | "name",
53 | "is_sensitive",
54 | "is_required"
55 | ]
56 | }
57 | },
58 | "connection_status_query": {
59 | "$ref": "../template/fixed_query.json"
60 | }
61 | },
62 | "required": [
63 | "headers",
64 | "connection_status_query"
65 | ]
66 | }
--------------------------------------------------------------------------------
/json-schema/datablock/provider_reconfiguration.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json-schema.org/draft/2020-12/schema",
3 | "title": "Datablock: provider_reconfiguration",
4 | "$id": "af.datablock.provider_reconfiguration",
5 | "description": "This datablock can be sent by the provider to reconfigure which headers the client should send to the provider.",
6 | "type": "object",
7 | "properties": {
8 | "headers": {
9 | "type": "object",
10 | "additionalProperties": {
11 | "type": "string"
12 | }
13 | }
14 | },
15 | "additionalProperties": false,
16 | "required": [
17 | "headers"
18 | ]
19 | }
--------------------------------------------------------------------------------
/json-schema/datablock/response_statistics.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json-schema.org/draft/2020-12/schema",
3 | "title": "Datablock: response_statistics",
4 | "$id": "af.datablock.response_statistics",
5 | "description": "Contains statistics about the current response.",
6 | "type": "object",
7 | "properties": {
8 | "result_count_total": {
9 | "type": "integer",
10 | "minimum": 0
11 | }
12 | },
13 | "additionalProperties": false
14 | }
--------------------------------------------------------------------------------
/json-schema/datablock/store.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json-schema.org/draft/2020-12/schema",
3 | "title": "Datablock: store",
4 | "$id": "af.datablock.store",
5 | "description": "Contains information about how/where to store a component file locally.",
6 | "type": "object",
7 | "properties": {
8 | "local_file_path": {
9 | "type": "string",
10 | "pattern": "^[^\\.|\\\/|\\\\]((?!\\.\\.\\\/|\\\\).)*[^\\.|\\\/|\\\\]$"
11 | },
12 | "bytes": {
13 | "type": [
14 | "integer",
15 | "null"
16 | ]
17 | }
18 | },
19 | "required": [
20 | "local_file_path",
21 | "bytes"
22 | ],
23 | "additionalProperties": false
24 | }
--------------------------------------------------------------------------------
/json-schema/datablock/text.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json-schema.org/draft/2020-12/schema",
3 | "title": "Datablock: text",
4 | "$id": "af.datablock.text",
5 | "description": "Contains general text information to be displayed to the user.",
6 | "type": "object",
7 | "additionalProperties": false,
8 | "properties": {
9 | "title": {
10 | "type": "string"
11 | },
12 | "description": {
13 | "type": "string"
14 | }
15 | },
16 | "required": [
17 | "title"
18 | ]
19 | }
--------------------------------------------------------------------------------
/json-schema/datablock/unlock_balance.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json-schema.org/draft/2020-12/schema",
3 | "title": "Datablock: unlock_balance",
4 | "$id": "af.datablock.unlock_balance",
5 | "description": "Information about the user's current account balance.",
6 | "type": "object",
7 | "additionalProperties": false,
8 | "properties": {
9 | "balance_unit": {
10 | "type": "string"
11 | },
12 | "balance": {
13 | "type": "number"
14 | },
15 | "balance_refill_uri": {
16 | "type": "string",
17 | "format": "uri"
18 | }
19 | },
20 | "required": [
21 | "balance_unit",
22 | "balance"
23 | ]
24 | }
--------------------------------------------------------------------------------
/json-schema/datablock/unlock_queries.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json-schema.org/draft/2020-12/schema",
3 | "title": "Datablock: unlock_queries",
4 | "$id": "af.datablock.unlock_queries",
5 | "description": "Contains the query or queries required to unlock all or some of the components in this implementation list.",
6 | "type": "array",
7 | "items": {
8 | "type": "object",
9 | "additionalProperties": false,
10 | "properties": {
11 | "id": {
12 | "type": "string"
13 | },
14 | "unlocked": {
15 | "type": "boolean"
16 | },
17 | "price": {
18 | "type": "number"
19 | },
20 | "query": {
21 | "$ref": "../template/fixed_query.json"
22 | },
23 | "child_query_ids": {
24 | "type": "array",
25 | "items": {
26 | "type": "string"
27 | }
28 | },
29 | "query_fallback_uri": {
30 | "type": [
31 | "string",
32 | "null"
33 | ],
34 | "format": "uri"
35 | }
36 | },
37 | "required": [
38 | "id",
39 | "unlocked"
40 | ],
41 | "if": {
42 | "properties": {
43 | "unlocked": {
44 | "const": false
45 | }
46 | }
47 | },
48 | "then": {
49 | "required": [
50 | "price",
51 | "query"
52 | ]
53 | }
54 | }
55 | }
--------------------------------------------------------------------------------
/json-schema/datablock/user.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json-schema.org/draft/2020-12/schema",
3 | "title": "Datablock: user",
4 | "$id": "af.datablock.user",
5 | "description": "This datablock describes the current user, as seen by the provider.",
6 | "type": "object",
7 | "additionalProperties": false,
8 | "properties": {
9 | "display_name": {
10 | "type": [
11 | "string",
12 | "null"
13 | ]
14 | },
15 | "display_tier": {
16 | "type": [
17 | "string",
18 | "null"
19 | ]
20 | },
21 | "display_icon_uri": {
22 | "type": [
23 | "string",
24 | "null"
25 | ],
26 | "format": "uri"
27 | }
28 | },
29 | "required": []
30 | }
--------------------------------------------------------------------------------
/json-schema/datablock/web_references.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json-schema.org/draft/2020-12/schema",
3 | "title": "Datablock: web_references",
4 | "$id": "af.datablock.web_references",
5 | "description": "References to external websites for documentation or support.",
6 | "type": "array",
7 | "additionalItems": false,
8 | "items": {
9 | "properties": {
10 | "title": {
11 | "type": [
12 | "string",
13 | "null"
14 | ]
15 | },
16 | "uri": {
17 | "type": "string",
18 | "format": "uri"
19 | },
20 | "icon_uri": {
21 | "type": [
22 | "string",
23 | "null"
24 | ],
25 | "format": "uri"
26 | }
27 | }
28 | },
29 | "minItems": 1
30 | }
--------------------------------------------------------------------------------
/json-schema/endpoint/asset_list.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json-schema.org/draft/2020-12/schema",
3 | "title": "Endpoint: asset_list",
4 | "$id": "af.endpoint.asset_list",
5 | "description": "This endpoint is used to query assets.",
6 | "type": "object",
7 | "properties": {
8 | "meta": {
9 | "$ref": "../template/meta.json",
10 | "properties": {
11 | "meta": {
12 | "properties": {
13 | "kind": {
14 | "const": "asset_list"
15 | }
16 | }
17 | }
18 | }
19 | },
20 | "data": {
21 | "type": "object",
22 | "additionalProperties": false,
23 | "properties": {
24 | "next_query": {
25 | "$ref": "../datablock/next_query.json"
26 | },
27 | "response_statistics": {
28 | "$ref": "../datablock/response_statistics.json"
29 | }
30 | }
31 | },
32 | "assets": {
33 | "type": "array",
34 | "maxItems": 100,
35 | "items": {
36 | "type": "object",
37 | "additionalProperties": false,
38 | "required": [
39 | "id",
40 | "data"
41 | ],
42 | "properties": {
43 | "id": {
44 | "type": "string",
45 | "pattern": "[a-zA-Z0-9\\._]+"
46 | },
47 | "data": {
48 | "type": "object",
49 | "properties": {
50 | "implementation_list_query": {
51 | "$ref": "../datablock/implementation_list_query.json"
52 | },
53 | "text": {
54 | "$ref": "../datablock/text.json"
55 | },
56 | "dimensions": {
57 | "$ref": "../datablock/dimensions.json"
58 | },
59 | "preview_image_supplemental": {
60 | "$ref": "../datablock/preview_image_supplemental.json"
61 | },
62 | "preview_image_thumbnail": {
63 | "$ref": "../datablock/preview_image_thumbnail.json"
64 | },
65 | "web_references": {
66 | "$ref": "../datablock/web_references.json"
67 | },
68 | "license": {
69 | "$ref": "../datablock/license.json"
70 | },
71 | "authors": {
72 | "$ref": "../datablock/authors.json"
73 | },
74 | "keywords": {
75 | "$ref": "../datablock/keywords.json"
76 | }
77 | },
78 | "required": [
79 | "implementation_list_query"
80 | ]
81 | }
82 | }
83 | }
84 | }
85 | },
86 | "required": [
87 | "meta",
88 | "data",
89 | "assets"
90 | ]
91 | }
--------------------------------------------------------------------------------
/json-schema/endpoint/auto.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json-schema.org/draft/2020-12/schema",
3 | "title": "Endpoint: (automatic)",
4 | "$id": "af.endpoint.auto",
5 | "description": "This schema validates against all possible AF endpoint types at once.",
6 | "$comment": "The 'oneOf' section ensures that the right schema is fulfilled.",
7 | "oneOf": [
8 | {
9 | "$ref": "./asset_list.json"
10 | },
11 | {
12 | "$ref": "./connection_status.json"
13 | },
14 | {
15 | "$ref": "./implementation_list.json"
16 | },
17 | {
18 | "$ref": "./initialization.json"
19 | },
20 | {
21 | "$ref": "./unlock.json"
22 | }
23 | ]
24 | }
--------------------------------------------------------------------------------
/json-schema/endpoint/connection_status.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json-schema.org/draft/2020-12/schema",
3 | "title": "Endpoint: connection_status",
4 | "$id": "af.endpoint.connection_status",
5 | "description": "This endpoint can be used to gather data about the current connection status.",
6 | "type": "object",
7 | "additionalProperties": false,
8 | "properties": {
9 | "meta": {
10 | "$ref": "../template/meta.json",
11 | "properties": {
12 | "meta": {
13 | "properties": {
14 | "kind": {
15 | "const": "connection_status"
16 | }
17 | }
18 | }
19 | }
20 | },
21 | "data": {
22 | "type": "object",
23 | "additionalProperties": false,
24 | "properties": {
25 | "unlock_balance": {
26 | "$ref": "../datablock/unlock_balance.json"
27 | },
28 | "user": {
29 | "$ref": "../datablock/user.json"
30 | },
31 | "provider_reconfiguration": {
32 | "$ref": "../datablock/provider_reconfiguration.json"
33 | }
34 | }
35 | }
36 | }
37 | }
--------------------------------------------------------------------------------
/json-schema/endpoint/implementation_list.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json-schema.org/draft/2020-12/schema",
3 | "title": "Endpoint: implementation_list",
4 | "$id": "af.endpoint.implementation_list",
5 | "description": "This endpoint gets the list of possible implementations for a specific asset.",
6 | "type": "object",
7 | "additionalProperties": false,
8 | "properties": {
9 | "meta": {
10 | "$ref": "../template/meta.json",
11 | "properties": {
12 | "meta": {
13 | "properties": {
14 | "kind": {
15 | "const": "implementation_list"
16 | }
17 | }
18 | }
19 | }
20 | },
21 | "data": {
22 | "type": "object",
23 | "additionalProperties": false,
24 | "properties": {
25 | "unlock_queries": {
26 | "$ref": "../datablock/unlock_queries.json"
27 | }
28 | }
29 | },
30 | "implementations": {
31 | "type": "array",
32 | "items": {
33 | "type": "object",
34 | "additionalProperties": false,
35 | "properties": {
36 | "id": {
37 | "type": "string",
38 | "pattern": "[a-zA-Z0-9\\._]+"
39 | },
40 | "data": {
41 | "type": "object",
42 | "text": {
43 | "$ref": "../datablock/text.json"
44 | }
45 | },
46 | "components": {
47 | "type": "array",
48 | "items": {
49 | "type": "object",
50 | "properties": {
51 | "id": {
52 | "type": "string",
53 | "pattern": "[a-zA-Z0-9\\._]+"
54 | },
55 | "data": {
56 | "type": "object",
57 | "additionalProperties": false,
58 | "properties": {
59 | "fetch.from_archive": {
60 | "$ref": "../datablock/fetch.from_archive.json"
61 | },
62 | "fetch.download": {
63 | "$ref": "../datablock/fetch.download.json"
64 | },
65 | "handle.loose_material_map": {
66 | "$ref": "../datablock/handle.loose_material_map.json"
67 | },
68 | "handle.loose_environment_map": {
69 | "$ref": "../datablock/handle.loose_environment_map.json"
70 | },
71 | "handle.native": {
72 | "$ref": "../datablock/handle.native.json"
73 | },
74 | "handle.archive": {
75 | "$ref": "../datablock/handle.archive.json"
76 | },
77 | "format": {
78 | "$ref": "../datablock/format.json"
79 | },
80 | "format.obj": {
81 | "$ref": "../datablock/format.obj.json"
82 | },
83 | "format.blend": {
84 | "$ref": "../datablock/format.blend.json"
85 | },
86 | "link.loose_material": {
87 | "$ref": "../datablock/link.loose_material.json"
88 | },
89 | "link.mtlx_material": {
90 | "$ref": "../datablock/link.mtlx_material.json"
91 | },
92 | "text": {
93 | "$ref": "../datablock/text.json"
94 | },
95 | "store": {
96 | "$ref": "../datablock/store.json"
97 | }
98 | },
99 | "allOf": [
100 | {
101 | "required": [
102 | "store"
103 | ]
104 | },
105 | {
106 | "oneOf": [
107 | {
108 | "required": [
109 | "fetch.from_archive"
110 | ]
111 | },
112 | {
113 | "required": [
114 | "fetch.download"
115 | ]
116 | }
117 | ]
118 | },
119 | {
120 | "oneOf": [
121 | {
122 | "required": [
123 | "format"
124 | ]
125 | },
126 | {
127 | "required": [
128 | "format.obj"
129 | ]
130 | },
131 | {
132 | "required": [
133 | "format.blend"
134 | ]
135 | }
136 | ]
137 | },
138 | {
139 | "if": {
140 | "anyOf": [
141 | {
142 | "required": [
143 | "link.loose_material"
144 | ]
145 | },
146 | {
147 | "required": [
148 | "link.mtlx_material"
149 | ]
150 | }
151 | ]
152 | },
153 | "then": {
154 | "oneOf": [
155 | {
156 | "required": [
157 | "link.loose_material"
158 | ]
159 | },
160 | {
161 | "required": [
162 | "link.mtlx_material"
163 | ]
164 | }
165 | ]
166 | }
167 | },
168 | {
169 | "if": {
170 | "anyOf": [
171 | {
172 | "required": [
173 | "handle.native"
174 | ]
175 | },
176 | {
177 | "required": [
178 | "handle.archive"
179 | ]
180 | },
181 | {
182 | "required": [
183 | "handle.loose_environment_map"
184 | ]
185 | },
186 | {
187 | "required": [
188 | "handle.loose_material_map"
189 | ]
190 | }
191 | ]
192 | },
193 | "then": {
194 | "oneOf": [
195 | {
196 | "required": [
197 | "handle.native"
198 | ]
199 | },
200 | {
201 | "required": [
202 | "handle.archive"
203 | ]
204 | },
205 | {
206 | "required": [
207 | "handle.loose_environment_map"
208 | ]
209 | },
210 | {
211 | "required": [
212 | "handle.loose_material_map"
213 | ]
214 | }
215 | ]
216 | }
217 | }
218 | ]
219 | }
220 | }
221 | }
222 | }
223 | }
224 | }
225 | }
226 | },
227 | "required": [
228 | "meta",
229 | "data",
230 | "implementations"
231 | ]
232 | }
--------------------------------------------------------------------------------
/json-schema/endpoint/initialization.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json-schema.org/draft/2020-12/schema",
3 | "title": "Endpoint: initialization",
4 | "$id": "af.endpoint.initialization",
5 | "description": "This is the initialization endpoint which the client first connects with.",
6 | "type": "object",
7 | "additionalProperties": false,
8 | "properties": {
9 | "meta": {
10 | "$ref": "../template/meta.json",
11 | "properties": {
12 | "meta": {
13 | "properties": {
14 | "kind": {
15 | "const": "initialization"
16 | }
17 | }
18 | }
19 | }
20 | },
21 | "id": {
22 | "type": "string",
23 | "pattern": "[a-z0-9-\\.]"
24 | },
25 | "data": {
26 | "type": "object",
27 | "additionalProperties": false,
28 | "properties": {
29 | "text": {
30 | "$ref": "../datablock/text.json"
31 | },
32 | "asset_list_query": {
33 | "$ref": "../datablock/asset_list_query.json"
34 | },
35 | "provider_configuration": {
36 | "$ref": "../datablock/provider_configuration.json"
37 | },
38 | "web_references": {
39 | "$ref": "../datablock/web_references.json"
40 | },
41 | "branding": {
42 | "$ref": "../datablock/branding.json"
43 | },
44 | "license": {
45 | "$ref": "../datablock/license.json"
46 | },
47 | "authors": {
48 | "$ref": "../datablock/authors.json"
49 | }
50 | },
51 | "required": [
52 | "asset_list_query"
53 | ]
54 | }
55 | },
56 | "required": [
57 | "meta",
58 | "data",
59 | "id"
60 | ]
61 | }
--------------------------------------------------------------------------------
/json-schema/endpoint/unlock.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json-schema.org/draft/2020-12/schema",
3 | "title": "Endpoint: unlock",
4 | "$id": "af.endpoint.unlock",
5 | "description": "This is an endpoint for unlocking components.",
6 | "type": "object",
7 | "additionalProperties":false,
8 | "properties": {
9 | "meta": {
10 | "$ref": "../template/meta.json",
11 | "properties": {
12 | "meta": {
13 | "properties": {
14 | "kind": {
15 | "const": "unlock"
16 | }
17 | }
18 | }
19 | }
20 | },
21 | "data": {
22 | "type": "object",
23 | "additionalProperties": false,
24 | "properties": {
25 | "text": {
26 | "$ref": "../datablock/text.json"
27 | }
28 | }
29 | }
30 | }
31 | }
--------------------------------------------------------------------------------
/json-schema/template/fixed_query.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json-schema.org/draft/2020-12/schema",
3 | "title": "template: Fixed Query",
4 | "$id": "af.template.fixed_query",
5 | "description": "This template represents a fixed query.",
6 | "type": "object",
7 | "additionalProperties": false,
8 | "properties": {
9 | "uri": {
10 | "type": "string",
11 | "format": "uri"
12 | },
13 | "method": {
14 | "type": "string",
15 | "enum": [
16 | "get",
17 | "post"
18 | ]
19 | },
20 | "payload": {
21 | "type": [
22 | "object",
23 | "null"
24 | ],
25 | "additionalProperties": {
26 | "type": "string"
27 | }
28 | }
29 | },
30 | "required": [
31 | "uri",
32 | "method",
33 | "payload"
34 | ]
35 | }
--------------------------------------------------------------------------------
/json-schema/template/meta.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json-schema.org/draft/2020-12/schema",
3 | "title": "Template: Meta",
4 | "$id": "af.template.meta",
5 | "description": "This template contains metadata for every endpoint.",
6 | "type": "object",
7 | "additionalProperties": false,
8 | "properties": {
9 | "response_id": {
10 | "type": [
11 | "string",
12 | "null"
13 | ]
14 | },
15 | "version": {
16 | "type": "string",
17 | "pattern": "[0-9]+\\.[0-9]+"
18 | },
19 | "kind": {
20 | "type": "string",
21 | "enum": [
22 | "asset_list",
23 | "connection_status",
24 | "implementation_list",
25 | "initialization",
26 | "unlock"
27 | ]
28 | },
29 | "message": {
30 | "type": [
31 | "string",
32 | "null"
33 | ]
34 | }
35 | },
36 | "required": [
37 | "kind",
38 | "version"
39 | ]
40 | }
--------------------------------------------------------------------------------
/json-schema/template/variable_query.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json-schema.org/draft/2020-12/schema",
3 | "title": "Template:Variable Query",
4 | "$id": "af.template.variable_query",
5 | "description": "This template describes a variable HTTP query that is configurable by the user.",
6 | "type": "object",
7 | "additionalProperties": false,
8 | "properties": {
9 | "uri": {
10 | "type": "string",
11 | "format": "uri"
12 | },
13 | "method": {
14 | "type": "string",
15 | "enum": [
16 | "get",
17 | "post"
18 | ]
19 | },
20 | "parameters": {
21 | "type": "array",
22 | "items": {
23 | "type": "object",
24 | "additionalProperties": false,
25 | "properties": {
26 | "type": {
27 | "type": "string",
28 | "enum": [
29 | "text",
30 | "boolean",
31 | "fixed",
32 | "select"
33 | ]
34 | },
35 | "id": {
36 | "type": "string"
37 | },
38 | "title": {
39 | "type": [
40 | "string",
41 | "null"
42 | ]
43 | },
44 | "default": {
45 | "type": [
46 | "string",
47 | "null"
48 | ]
49 | },
50 | "choices": {
51 | "type": [
52 | "array",
53 | "null"
54 | ]
55 | }
56 | },
57 | "$comment": "This if-clause ensures that the 'choices' array is required only if 'select' mode is used.",
58 | "if": {
59 | "properties": {
60 | "type": {
61 | "const": "select"
62 | }
63 | }
64 | },
65 | "then": {
66 | "properties": {
67 | "choices": {
68 | "type": "array",
69 | "minItems": 1,
70 | "items": {
71 | "type": "object",
72 | "additionalProperties": false,
73 | "properties": {
74 | "value": {
75 | "type": "string"
76 | },
77 | "title": {
78 | "type": "string"
79 | }
80 | },
81 | "required": [
82 | "value",
83 | "title"
84 | ]
85 | }
86 | }
87 | },
88 | "required": [
89 | "choices"
90 | ]
91 | },
92 | "else": {
93 | "properties": {
94 | "choices": {
95 | "type": "null"
96 | }
97 | }
98 | },
99 | "required": [
100 | "type",
101 | "id"
102 | ]
103 | }
104 | }
105 | },
106 | "required": [
107 | "uri",
108 | "method",
109 | "parameters"
110 | ]
111 | }
--------------------------------------------------------------------------------
/spec.md:
--------------------------------------------------------------------------------
1 | This document specifies **AssetFetch v0.4**, an HTTP- and JSON-based system for 3D asset discovery, retrieval and handling/import inside of Digital Content Creation (DCC) apps.
2 | The AssetFetch Protocol aims to provide a standardized way for artists to browse libraries of downloadable assets offered by providers *outside* their current production environment or pipeline, such as those of commercial or non-profit 3D asset vendors, marketplaces or other repositories of models, textures or other kinds of assets for digital media production.
3 |
4 | - [1. Introduction](#1-introduction)
5 | - [1.1. Motivation](#11-motivation)
6 | - [1.2. Vision](#12-vision)
7 | - [1.3. Goals](#13-goals)
8 | - [1.4. Non-Goals](#14-non-goals)
9 | - [2. Terminology](#2-terminology)
10 | - [2.1. Provider](#21-provider)
11 | - [2.2. Client](#22-client)
12 | - [2.3. Host Application](#23-host-application)
13 | - [2.4. User](#24-user)
14 | - [2.5. Asset](#25-asset)
15 | - [2.6. (Asset-)Implementation](#26-asset-implementation)
16 | - [2.6.1. Implementation Directory](#261-implementation-directory)
17 | - [2.7. (Implementation-)Component](#27-implementation-component)
18 | - [2.7.1. Component "Activeness"](#271-component-activeness)
19 | - [2.8. Datablock](#28-datablock)
20 | - [2.9. Component Unlocking](#29-component-unlocking)
21 | - [3. General Operation](#3-general-operation)
22 | - [3.1. Overview](#31-overview)
23 | - [3.2. Initialization](#32-initialization)
24 | - [3.3. Authentication \& Connection Status (optional)](#33-authentication--connection-status-optional)
25 | - [3.4. Browsing Assets](#34-browsing-assets)
26 | - [3.4.1. Asset Filtering](#341-asset-filtering)
27 | - [3.4.2. Asset Selection](#342-asset-selection)
28 | - [3.5. Implementation Negotiation](#35-implementation-negotiation)
29 | - [3.5.1. Implementation Filtering](#351-implementation-filtering)
30 | - [3.5.2. Implementation Selection](#352-implementation-selection)
31 | - [3.6. Component Unlocking (optional)](#36-component-unlocking-optional)
32 | - [3.7. Downloading](#37-downloading)
33 | - [3.8. Handling](#38-handling)
34 | - [3.9. Sequence Diagram](#39-sequence-diagram)
35 | - [3.9.1. Simple Version](#391-simple-version)
36 | - [3.9.2. Complete Version](#392-complete-version)
37 | - [4. HTTP Communication](#4-http-communication)
38 | - [4.1. Request Payloads](#41-request-payloads)
39 | - [4.2. Response Payloads](#42-response-payloads)
40 | - [4.3. User-Agent](#43-user-agent)
41 | - [4.4. Variable and Fixed Queries](#44-variable-and-fixed-queries)
42 | - [4.4.1. Variable Query](#441-variable-query)
43 | - [4.4.1.1. Variable Query Parameters](#4411-variable-query-parameters)
44 | - [4.4.2. Fixed Query](#442-fixed-query)
45 | - [4.5. HTTP Codes and Error Handling](#45-http-codes-and-error-handling)
46 | - [5. Endpoints](#5-endpoints)
47 | - [5.1. About Endpoints](#51-about-endpoints)
48 | - [5.2. Response Data Templates](#52-response-data-templates)
49 | - [5.2.1. The `meta` Template](#521-the-meta-template)
50 | - [5.2.2. The `datablock_collection` Template](#522-the-datablock_collection-template)
51 | - [5.2.2.1. Example](#5221-example)
52 | - [5.3. Endpoint: Initialization (`initialization`)](#53-endpoint-initialization-initialization)
53 | - [5.4. Endpoint: Asset List (`asset_list`)](#54-endpoint-asset-list-asset_list)
54 | - [5.4.1. `asset` Structure](#541-asset-structure)
55 | - [5.5. Endpoint: Implementation List (`implementation_list`)](#55-endpoint-implementation-list-implementation_list)
56 | - [5.5.1. `implementation` Structure](#551-implementation-structure)
57 | - [5.5.2. `component` Structure](#552-component-structure)
58 | - [5.6. Endpoint: Unlocking (`unlock`)](#56-endpoint-unlocking-unlock)
59 | - [5.7. Endpoint: Connection Status (`connection_status`)](#57-endpoint-connection-status-connection_status)
60 | - [6. Datablocks](#6-datablocks)
61 | - [6.1. Datablock Names](#61-datablock-names)
62 | - [6.2. Datablock Value Templates](#62-datablock-value-templates)
63 | - [6.2.1. `variable_query`](#621-variable_query)
64 | - [6.2.1.1. `parameter` Structure](#6211-parameter-structure)
65 | - [6.2.1.2. `choice` Structure](#6212-choice-structure)
66 | - [6.2.2. `fixed_query`](#622-fixed_query)
67 | - [7. Datablock Index](#7-datablock-index)
68 | - [7.1. Configuration and authentication-related datablocks](#71-configuration-and-authentication-related-datablocks)
69 | - [7.1.1. `provider_configuration`](#711-provider_configuration)
70 | - [7.1.1.1. `header` structure](#7111-header-structure)
71 | - [7.1.2. `provider_reconfiguration`](#712-provider_reconfiguration)
72 | - [7.1.3. `user`](#713-user)
73 | - [7.2. Browsing-related Datablocks](#72-browsing-related-datablocks)
74 | - [7.2.1. `asset_list_query`](#721-asset_list_query)
75 | - [7.2.2. `implementation_list_query`](#722-implementation_list_query)
76 | - [7.2.3. `next_query`](#723-next_query)
77 | - [7.2.4. `response_statistics`](#724-response_statistics)
78 | - [7.3. Display-related Datablocks](#73-display-related-datablocks)
79 | - [7.3.1. `text`](#731-text)
80 | - [7.3.2. `web_references`](#732-web_references)
81 | - [7.3.3. `branding`](#733-branding)
82 | - [7.3.4. `license`](#734-license)
83 | - [7.3.5. `authors`](#735-authors)
84 | - [7.3.6. `dimensions`](#736-dimensions)
85 | - [7.3.7. `preview_image_supplemental`](#737-preview_image_supplemental)
86 | - [7.3.8. `preview_image_thumbnail`](#738-preview_image_thumbnail)
87 | - [7.3.8.1. `uris` Structure](#7381-uris-structure)
88 | - [7.3.9. `keywords`](#739-keywords)
89 | - [7.4. Unlocking-related Datablocks](#74-unlocking-related-datablocks)
90 | - [7.4.1. `unlock_balance`](#741-unlock_balance)
91 | - [7.4.2. `unlock_queries`](#742-unlock_queries)
92 | - [7.4.2.1. `unlock_query` structure](#7421-unlock_query-structure)
93 | - [7.5. Format-related Datablocks](#75-format-related-datablocks)
94 | - [7.5.1. `format`](#751-format)
95 | - [7.5.1.1. `extension` rules](#7511-extension-rules)
96 | - [7.5.1.2. `mediatype` rules](#7512-mediatype-rules)
97 | - [7.5.2. `format.blend`](#752-formatblend)
98 | - [7.5.2.1. `target` Structure](#7521-target-structure)
99 | - [7.5.3. `format.obj`](#753-formatobj)
100 | - [7.6. Fetching- and Storage-related Datablocks](#76-fetching--and-storage-related-datablocks)
101 | - [7.6.1. `fetch.download`](#761-fetchdownload)
102 | - [7.6.2. `fetch.from_archive`](#762-fetchfrom_archive)
103 | - [7.6.3. `store`](#763-store)
104 | - [7.6.3.1. `local_file_path` rules](#7631-local_file_path-rules)
105 | - [7.7. Handling/Processing-related Datablocks](#77-handlingprocessing-related-datablocks)
106 | - [7.7.1. `handle.native`](#771-handlenative)
107 | - [7.7.2. `handle.archive`](#772-handlearchive)
108 | - [7.7.2.1. `local_directory_path` rules](#7721-local_directory_path-rules)
109 | - [7.7.3. `handle.loose_environment_map`](#773-handleloose_environment_map)
110 | - [7.7.4. `handle.loose_material_map`](#774-handleloose_material_map)
111 | - [7.8. Linking-related Datablocks](#78-linking-related-datablocks)
112 | - [7.8.1. `link.loose_material`](#781-linkloose_material)
113 | - [7.8.2. `link.mtlx_material`](#782-linkmtlx_material)
114 | - [8. Working With Asset Implementations](#8-working-with-asset-implementations)
115 | - [8.1. Overview](#81-overview)
116 | - [8.2. Implementation Analysis](#82-implementation-analysis)
117 | - [8.3. Performing Unlock Queries](#83-performing-unlock-queries)
118 | - [8.4. Choosing a Local Directory](#84-choosing-a-local-directory)
119 | - [8.5. Downloading and Storing Files](#85-downloading-and-storing-files)
120 | - [8.5.1. Storing All Component Files Based on `store` Datablock](#851-storing-all-component-files-based-on-store-datablock)
121 | - [8.5.2. Interacting With Archives (components with `handle.archive` datablock)](#852-interacting-with-archives-components-with-handlearchive-datablock)
122 | - [8.5.2.1. Handling for `extract_fully=true`](#8521-handling-for-extract_fullytrue)
123 | - [8.5.2.2. Handling for `extract_fully=false`](#8522-handling-for-extract_fullyfalse)
124 | - [8.5.2.3. Deleting Archives](#8523-deleting-archives)
125 | - [8.6. Handling Component Files](#86-handling-component-files)
126 | - [8.6.1. Handling For Components Without a `handle.*` Datablock](#861-handling-for-components-without-a--handle-datablock)
127 | - [8.6.2. Handling based on the native handling datablock (`handle.native`)](#862-handling-based-on-the-native-handling-datablock-handlenative)
128 | - [8.6.3. Handling a Loose Material Map (`handle.loose_material_map`)](#863-handling-a-loose-material-map-handleloose_material_map)
129 | - [8.6.4. Handling a Loose Environment Map (`handle.loose_environment_map`)](#864-handling-a-loose-environment-map-handleloose_environment_map)
130 | - [8.7. Handling Component Links](#87-handling-component-links)
131 | - [8.7.1. Handling MTLX Material Links (`link.mtlx_material`)](#871-handling-mtlx-material-links-linkmtlx_material)
132 | - [8.7.2. Handling loose Material Links (`link.loose_material`)](#872-handling-loose-material-links-linkloose_material)
133 | - [9. Security Considerations](#9-security-considerations)
134 | - [9.1. Storing Sensitive Headers](#91-storing-sensitive-headers)
135 | - [9.2. Avoiding Relative Paths in Local Path Fields](#92-avoiding-relative-paths-in-local-path-fields)
136 | - [9.3. Self-referential Archive Components](#93-self-referential-archive-components)
137 |
138 |
139 | # 1. Introduction
140 |
141 | ## 1.1. Motivation
142 |
143 | Acquiring pre-made assets for use in a project usually involves visiting the website of a vendor offering 3D models, material or other resources and downloading one or multiple files to local storage.
144 | These asset files are then manually imported into the desired DCC application, a process which often involves additional steps for unpacking, file organization and adjustments after the initial import such as manually setting up a material from texture maps that came with a model file.
145 |
146 | When trying to work with a large volume of third-party assets this workflow can become rather laborious, even more so when trying to experiment with multiple assets to see which works best in a scene.
147 | Recognizing this issue, multiple vendors have started creating bespoke solutions that allow artists to browse an individual vendor's asset library in a much more integrated fashion, for example through an additional window or panel integrated into the graphical user interface in a 3D suite.
148 | This vastly improves the user experience of browsing, downloading and importing assets and helps artists to focus on their core creative objective.
149 |
150 | However, these solutions are usually implemented using addons/plugins and are hard-coded to work with one 3D suite and one vendor, which creates a new set of issues:
151 |
152 | Vendors wanting to offer this improved user experience for their customers find themselves needing to build and maintain multiple pieces of software with limited opportunities for code reuse as every new plugin must be built within the language, framework and constraints presented by the host application.
153 |
154 | In light of this, many vendors choose to only offer a native integration for one or two applications or no native integrations at all.
155 | This may be because they don't have the resources and skills required or because development of such systems is not justifiable from a business perspective.
156 |
157 | Conversely, large vendors who can afford to develop and continuously maintain native integrations for many different DCC applications can benefit from a lock-in effect as only they can provide the convenience and speed that artists are accustomed to - limiting artist's choices.
158 |
159 | ## 1.2. Vision
160 |
161 | The AssetFetch system aims to create an artist experience similar to the existing native integrations with less development overhead in order to increase interoperability between vendors and DCC applications to allow more vendors - especially smaller ones - to offer their assets to artists right in the DCC applications where they need them.
162 |
163 | ## 1.3. Goals
164 |
165 | These are the goals of the AssetFetch specification, outlined in this document:
166 |
167 | - Describe a flexible, extensible way of discovering, filtering and previewing assets.
168 | - Facilitate the *one-time and one-directional transfer* of an asset with all its files from a provider to a client.
169 | - Allow providers to describe the structure of their assets (i.e. how the files they provide should work together) in a machine-readable way that allows for semi- or fully-automated handling of assets on the client-side with the smallest possible amount of manual adjustments.
170 |
171 | - Work without custom code that is specific for one vendor-application combination.
172 | - Make offering assets a low-threshold process for implementors on the provider side.
173 | - Allow implementors on the client side (for whom the implementation is likely harder) to easily get to an MVP-stage and gradually build out their implementations from there.
174 |
175 | ## 1.4. Non-Goals
176 |
177 | In order to maintain focus and make the implementation achievable with a reasonable amount of effort AssetFetch does not want to:
178 |
179 | - Act as a full asset management system for project- or studio-internal use, i.e. one that permanently tracks potentially evolving assets within an ongoing production. AssetFetch shares some ideas and data structures from [OpenAssetIO](https://openassetio.org/) but is not meant as a competitor or replacement for it, rather as a supplementary system. It might even be possible to run AssetFetch on top of OpenAssetIO in future versions.
180 | - Act as a new file format for describing complex 3D scenes in great detail. This is left to [OpenUSD](https://openusd.org) or [MaterialX](https://materialx.org/). Instead, the focus lies on describing the interactions and relationships between files with existing, well-known file formats.
181 |
182 | # 2. Terminology
183 |
184 | This section describes several key terms that will be used throughout this document.
185 |
186 | ## 2.1. Provider
187 | >The actor that offers assets by hosting an AssetFetch-compliant HTTP(S)-Endpoint.
188 |
189 | This provider can be a commercial platform that is offering 3D assets for sale or an open repository providing content for free.
190 | The provider hosts the AssetFetch API as an HTTP(s)-based service.
191 |
192 |
193 | ## 2.2. Client
194 | >A piece of software built to interact with the AssetFetch-API of a provider in order to receive resources from it.
195 |
196 | ## 2.3. Host Application
197 | >An application into which the client is integrated.
198 |
199 | A client can be a standalone application but in most implementation scenarios it will likely be integrated into another host application, like a 3D suite or other DCC application, in the form of a plugin/addon.
200 | The crucial difference to existing provider-specific plugins/addons is that only one implementation needs to be developed and maintained per application, instead of one per provider-application pairing.
201 | In reality there may of course still be multiple client plugins developed for the same application, but the choice for one of them should have less of an impact.
202 |
203 | ## 2.4. User
204 | >The human who uses an AssetFetch client.
205 |
206 |
207 | ## 2.5. Asset
208 | >A reusable *logical* media element in the context of a digital project.
209 |
210 | The emphasis is put on the term "logical" to indicate that one asset does not necessarily represent a single file.
211 | It might be composed of one or multiple meshes, textures, bones, particle systems, simulation data, etc. that are kept in multiple files.
212 |
213 | - A model of a chair with its mesh and textures is considered one asset.
214 | - An HDRI environment map is considered one asset.
215 | - A character model with textures and a rig is considered one asset.
216 |
217 | ## 2.6. (Asset-)Implementation
218 | > A concrete collection of components (files) that represents an asset in exactly one way for one specific use case, potentially even just for one specific application.
219 |
220 | When describing the transfer of assets from a provider to a client it is common for the provider to have the same asset available in many different variations.
221 |
222 | These variations may be:
223 | - Small semantic variations, like different colors or design alterations that do not change the nature of the asset so much that it becomes a new asset.
224 | - Quality variations, like multiple texture resolutions or LODs (Levels of Detail) for a mesh.
225 | - Purely technical variations, like offering the same asset with the same general level of technical fidelity in multiple file formats and file-arrangements for different applications.
226 |
227 | Some vendors allow their users to control these parameters with great precision so that they only need to download the asset in exactly the format and quality that is desired.
228 | This exact choice - or rather the collection of files with metadata that is a result of it - is considered an "**implementation** of an asset".
229 |
230 | - An OBJ file containing the LOD1 mesh of a chair along with a set of TIFF texture maps measuring 512x512 pixels each is considered one implementation of the chair asset. Using the LOD0 version instead would be considered a *new implementation* of the *same chair asset*.
231 | - An EXR image with a resolution of 8192x4096 pixels in an equirectangular projection is considered one implementation of an HDRI environment.
232 | - A BLEND file containing a character model, its rig and all its textures (again with a specific resolution) all packed into it is considered one implementation.
233 | - A UASSET file containing the same character set up for Unreal Engine instead of Blender is considered a different implementation of the same character asset.
234 |
235 | ### 2.6.1. Implementation Directory
236 | Every asset implementation has its own directory in which all component files for it are stored by the client after downloading them.
237 | This is referred to as the "implementation directory".
238 | A new one is created for every asset implementation that the client downloads.
239 |
240 | ## 2.7. (Implementation-)Component
241 | > A piece of digital information, generally a file, that is part of an asset implementation.
242 |
243 | - The 512px TIFF roughness map of the aforementioned chair implementation is one component.
244 | - The EXR file containing the panoramic environment is a component. It happens to be the only component in the implementation of that environment.
245 | - The BLEND file with the character model and textures packed into it is also considered one component since the BLEND file is a black box for any program except Blender.
246 | - When working with archives, the archive itself as well as its contents are considered components.
247 | A ZIP archive with the chair model as an FBX file and its textures as PNG files is represented as one component for the ZIP archive and then one component for each file in it (with some exceptions when using specific archive unpacking configurations).
248 |
249 | ### 2.7.1. Component "Activeness"
250 | Not all components of an implementation must be actively processed by the client in order to use them and are instead handled implicitly by the host application.
251 |
252 | - When trying to import an implementation consisting of an OBJ-file, an MTL-file and several material maps into a DCC application, then it is generally sufficient to invoke the application's native OBJ import functionality with the OBJ-file as the target.
253 | The references made inside OBJ-file will prompt the application to handle the MTL-file which then loads the supplemental texture maps without any further explicit invocation.
254 | - Some formats like [OpenUSD](https://openusd.org/) allow for more complex references between files. This way an entire scene can be represented by one "root" file which contains references to other files which in turn reference even more files.
255 |
256 | In both of the given examples, only one file would need to be "actively" handled by the user (or by a client trying to automate the user's work) with the remaining work getting delegated to the host application.
257 |
258 | When a client instructs its host to load a component and this component causes multiple other components to be loaded (for example a mesh file referencing two textures) then the first component would be called "active" (because from the client's perspective it needed active handling) whereas the components referenced by it are called "passive" (because the AssetFetch client did not need to handle them directly).
259 |
260 | ## 2.8. Datablock
261 | > A piece of metadata of a certain type and structure that can be attached to most other datastructures defined by AssetFetch.
262 |
263 | Datablocks are flexible and sometimes reusable pieces of metadata that enable the communication a broad range of metadata:
264 |
265 | - Attributes of providers, assets, implementations or other resources
266 | - Instructions for parsing or otherwise handling specific data
267 | - Relationships between resources
268 |
269 | ## 2.9. Component Unlocking
270 | > Performing a query from the client to the provider to request access to a specific component of an implementation.
271 | > The provider acknowledges the query and then grants access to the requested component(s), possibly along with a side-effect in the provider's back-end system, such as a charging the user for a purchase.
272 |
273 | The standard operating mode of an AssetFetch provider is to freely distribute the component files for any asset implementation that the client.
274 |
275 | However, the provider can configure access limitations for all or some components to require payment, impose usage quotas, or add other limitations to control distribution.
276 | To accommodate this, providers are able to define an additional endpoint to perform "unlocking" queries against.
277 | The pattern by which components are unlocked (for example on a per-asset, per-implementation or even per-component basis) can be controlled with a high degree of flexibility, accommodating many patterns commonly used by digital asset stores.
278 |
279 | **AssetFetch does not concern itself with any actual monetary transactions, users still need to perform any required account- and payment setup with the provider through external means, usually through the provider's website.**
280 |
281 | See [3.6](#36-component-unlocking-optional) and [7.4](#74-unlocking-related-datablocks) for details.
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 | # 3. General Operation
292 |
293 | This section describes the steps by which AssetFetch operates in general terms.
294 | The following sections will then describe the exact implementation by defining the exact HTTP parameters and (JSON-) datastructures.
295 |
296 | ## 3.1. Overview
297 |
298 | AssetFetch models interactions between a provider and a client (controlled by a user).
299 | Generally, the following interactions are modeled:
300 |
301 | - **Initialization:** Client and provider exchange metadata to communicate basic properties and establish that an interaction can occur.
302 | - **Connection checking (optional):** If the provider requires authentication from the client, then an additional step is performed to confirm that the connection has been established and that the user has been logged in successfully.
303 | - **Browsing assets:** The client receives a list of available assets from the provider and displays it to the user. This list can be influenced using parameters to implement common filtering techniques, such as keyword- or category-based searching. The user chooses an asset they with to obtain.
304 | - **Implementation negotiation:** The client receives a list of available implementations for the chosen asset. This list can again be controlled using parameters to implement common per-asset choices like resolution or level-of-detail. The client then determines based on the metadata which of the implementations offered by the provider are viable for its environment/host application and chooses one implementation, possibly with manual support of the user.
305 | - **Component Unlocking (optional):** If the provider requires component unlocking, then the relevant information was already included in the implementation metadata. The client uses this data to inform the user about the upcoming charges and (if requested) performs the required unlocking queries to the provider. With the queries made, the provider will actually allow the download during the next step. If component unlocking is not required by the provider then this step can be skipped entirely.
306 | - **Downloading and arranging**: The client uses the download information it obtained together with the other implementation metadata to download the component files via HTTP and arrange them in a local file system directory or similar storage location.
307 | - **Local handling**: Finally, the client "handles" the files it downloaded along with aid from the implementation metadata. This "handling" is again controlled by implementation metadata can vary between clients developed for different host applications, but it usually involves importing the downloaded resources into the currently open project/scene or placing the data in a local repository, such as an application's proprietary asset management solution.
308 |
309 | ## 3.2. Initialization
310 |
311 | The first point of contact between a client and a provider is the initialization URI which the user enters into the client, comparable to the URI of an RSS feed.
312 | This URI is communicated from the provider to the user via external channels, such as the provider's website.
313 |
314 | The client establishes an initial connection to the provider by making an HTTP query to the initialization endpoint.
315 | This initialization endpoint MUST be accessible via HTTP GET without any prior communication between client and provider.
316 | It and communicates key information for further usage of the provider's AssetFetch interface, such as:
317 |
318 | - The provider's name and other general metadata.
319 | - Whether the provider requires the client to authenticate itself through additional HTTP headers.
320 | - The endpoint through which assets can be queried and its parameters.
321 |
322 | ## 3.3. Authentication & Connection Status (optional)
323 | As mentioned in the previous section, the provider MAY require custom authentication headers, in which case the client MUST send these headers along with every request it performs to that provider, unless the request is directed at the initialization endpoint.
324 |
325 | Which headers the client needs to send is communicated by the provider in the initialization data.
326 |
327 | The client obtains the required header values, such as passwords or randomly generated access tokens, from the user through a GUI, from a cache or through other mechanisms.
328 | See [9. Security considerations](#9-security-considerations) for more details about credential handling.
329 |
330 | If the provider uses authentication, then it MUST offer a connection status endpoint in the initialization data.
331 | Before attempting to perform any other actions using the credentials entered by the user, the client SHOULD contact the connection status endpoint at least once after initialization to verify the correctness of the values entered by the user.
332 |
333 | The connection status endpoint has two primary uses:
334 |
335 | - If available, the provider SHOULD respond with user-specific metadata, such as a username or account details which the client SHOULD display to the user to confirm that they are properly connected to the provider.
336 | - If the provider implements component unlocking using a prepaid balance system, then it SHOULD use this endpoint to communicate the user's remaining account balance. See [7.4](#74-unlocking-related-datablocks).
337 |
338 | ## 3.4. Browsing Assets
339 | After successful initialization (and possibly authentication) the client is ready to browse assets.
340 |
341 | ### 3.4.1. Asset Filtering
342 | The provider might send a static, unchanging list of available assets, but it MAY also require specific parameters for generating a dynamic asset list.
343 | In that case, the names and kinds of parameters were defined by the provider during the initialization step.
344 | Parameters can come in different formats, such as simple text strings or selections from a set of options, similar to what can be represented with a `