Files

846 lines
22 KiB
YAML

openapi: 3.1.0
info:
title: Box Manifest API
version: 0.0.0
description: >-
Pre-release API for the Box Manifest universal node tree. Breaking changes
are allowed until a compatibility policy is adopted.
servers:
- url: /
paths:
/api/node-types:
get:
operationId: listNodeTypes
summary: List user-defined node types
responses:
"200":
description: Node types ordered by name
content:
application/json:
schema:
type: array
items: { $ref: "#/components/schemas/NodeType" }
default: { $ref: "#/components/responses/Error" }
post:
operationId: createNodeType
summary: Create a node type
requestBody:
required: true
content:
application/json:
schema: { $ref: "#/components/schemas/NodeTypeWrite" }
responses:
"201":
description: Node type created
content:
application/json:
schema: { $ref: "#/components/schemas/NodeType" }
default: { $ref: "#/components/responses/Error" }
/api/node-types/{typeId}:
parameters:
- name: typeId
in: path
required: true
schema: { type: string }
put:
operationId: updateNodeType
summary: Replace a node type
requestBody:
required: true
content:
application/json:
schema: { $ref: "#/components/schemas/NodeTypeWrite" }
responses:
"200":
description: Node type updated
content:
application/json:
schema: { $ref: "#/components/schemas/NodeType" }
default: { $ref: "#/components/responses/Error" }
delete:
operationId: deleteNodeType
summary: Delete a type and leave assigned nodes untyped
responses:
"204": { description: Node type deleted }
default: { $ref: "#/components/responses/Error" }
/api/tags:
get:
operationId: listTags
summary: List tags
responses:
"200":
description: Tags ordered by name
content:
application/json:
schema:
type: array
items: { $ref: "#/components/schemas/Tag" }
default: { $ref: "#/components/responses/Error" }
post:
operationId: createTag
summary: Create a tag
requestBody:
required: true
content:
application/json:
schema: { $ref: "#/components/schemas/TagWrite" }
responses:
"201":
description: Tag created
content:
application/json:
schema: { $ref: "#/components/schemas/Tag" }
default: { $ref: "#/components/responses/Error" }
/api/tags/{tagId}:
parameters:
- name: tagId
in: path
required: true
schema: { type: string }
put:
operationId: updateTag
summary: Replace a tag
requestBody:
required: true
content:
application/json:
schema: { $ref: "#/components/schemas/TagWrite" }
responses:
"200":
description: Tag updated
content:
application/json:
schema: { $ref: "#/components/schemas/Tag" }
default: { $ref: "#/components/responses/Error" }
delete:
operationId: deleteTag
summary: Delete a tag and remove its node assignments
responses:
"204": { description: Tag deleted }
default: { $ref: "#/components/responses/Error" }
/api/tree:
get:
operationId: getTree
summary: Get the complete node tree
responses:
"200":
description: The tree beginning at Root
content:
application/json:
schema:
$ref: "#/components/schemas/TreeNode"
default:
$ref: "#/components/responses/Error"
/api/imports/tree/preview:
post:
operationId: previewTreeImport
summary: Validate and preview a nested tree import
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/TreeImportPreviewRequest"
responses:
"200":
description: Normalized import plan ready for review
content:
application/json:
schema:
$ref: "#/components/schemas/TreeImportPreview"
default:
$ref: "#/components/responses/Error"
/api/imports/tree/commit:
post:
operationId: commitTreeImport
summary: Atomically commit a reviewed tree import plan
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/TreeImportCommitRequest"
responses:
"201":
description: Entire tree imported
content:
application/json:
schema:
$ref: "#/components/schemas/TreeImportCommitResponse"
default:
$ref: "#/components/responses/Error"
/api/nodes:
post:
operationId: createNode
summary: Create a node
description: A missing parentId places the new node beneath Unsorted.
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/CreateNodeRequest"
responses:
"201":
description: Node created
content:
application/json:
schema:
$ref: "#/components/schemas/Node"
default:
$ref: "#/components/responses/Error"
/api/nodes/bulk:
post:
operationId: createNodesBulk
summary: Create multiple sibling nodes atomically
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/CreateNodesBulkRequest"
responses:
"201":
description: All nodes created in request order
content:
application/json:
schema:
$ref: "#/components/schemas/CreateNodesBulkResponse"
default:
$ref: "#/components/responses/Error"
/api/nodes/bulk/move:
post:
operationId: moveNodesBulk
summary: Move sibling nodes atomically
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/MoveNodesBulkRequest"
responses:
"200":
description: All selected nodes moved
content:
application/json:
schema:
$ref: "#/components/schemas/MoveNodesBulkResponse"
default:
$ref: "#/components/responses/Error"
/api/nodes/bulk/delete:
post:
operationId: deleteNodesBulk
summary: Delete empty nodes atomically
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/DeleteNodesBulkRequest"
responses:
"204":
description: All selected nodes deleted
default:
$ref: "#/components/responses/Error"
/api/nodes/bulk/combine:
post:
operationId: combineNodes
summary: Combine empty sibling nodes into one quantity-tracked node
description: >-
The retained node keeps its UUID and lookup code. Other selected nodes
and their lookup identities are deleted atomically.
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/CombineNodesRequest"
responses:
"200":
description: Combined quantity-tracked node
content:
application/json:
schema:
$ref: "#/components/schemas/Node"
default:
$ref: "#/components/responses/Error"
/api/nodes/bulk/classification:
post:
operationId: classifyNodesBulk
summary: Atomically assign a type and add or remove tags on multiple nodes
requestBody:
required: true
content:
application/json:
schema: { $ref: "#/components/schemas/BulkClassificationRequest" }
responses:
"204": { description: Classification updated }
default: { $ref: "#/components/responses/Error" }
/api/nodes/{nodeId}:
parameters:
- $ref: "#/components/parameters/NodeId"
get:
operationId: getNode
summary: Get one node
responses:
"200":
description: Node found
content:
application/json:
schema:
$ref: "#/components/schemas/Node"
default:
$ref: "#/components/responses/Error"
patch:
operationId: updateNode
summary: Update a node's name or quantity
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/UpdateNodeRequest"
responses:
"200":
description: Node updated
content:
application/json:
schema:
$ref: "#/components/schemas/Node"
default:
$ref: "#/components/responses/Error"
delete:
operationId: deleteNode
summary: Delete an empty node
description: Root, Unsorted, and nodes with children cannot be deleted.
responses:
"204":
description: Node deleted
"409":
description: The node is protected or is not empty
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
default:
$ref: "#/components/responses/Error"
/api/nodes/by-code/{lookupCode}:
get:
operationId: getNodeByLookupCode
summary: Resolve a printed lookup code to its node
parameters:
- name: lookupCode
in: path
required: true
schema:
type: string
pattern: "^[A-Z2-7]{6}$"
responses:
"200":
description: Node found
content:
application/json:
schema:
$ref: "#/components/schemas/Node"
default:
$ref: "#/components/responses/Error"
/api/nodes/{nodeId}/move:
parameters:
- $ref: "#/components/parameters/NodeId"
post:
operationId: moveNode
summary: Move a node
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/MoveNodeRequest"
responses:
"200":
description: Node moved
content:
application/json:
schema:
$ref: "#/components/schemas/Node"
"409":
description: The move is forbidden or would create a cycle
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
default:
$ref: "#/components/responses/Error"
/api/nodes/{nodeId}/individualize:
parameters:
- $ref: "#/components/parameters/NodeId"
post:
operationId: individualizeNode
summary: Turn an empty quantity node into individually tracked siblings
description: >-
The original node becomes the first unit and retains its UUID and lookup
code. The supplied names must match the existing quantity.
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/IndividualizeNodeRequest"
responses:
"200":
description: Individually tracked nodes in unit order
content:
application/json:
schema:
$ref: "#/components/schemas/CreateNodesBulkResponse"
default:
$ref: "#/components/responses/Error"
/api/nodes/{nodeId}/classification:
parameters:
- $ref: "#/components/parameters/NodeId"
put:
operationId: classifyNode
summary: Replace a node's optional type and complete tag set
requestBody:
required: true
content:
application/json:
schema: { $ref: "#/components/schemas/ClassificationRequest" }
responses:
"200":
description: Classified node
content:
application/json:
schema: { $ref: "#/components/schemas/Node" }
default: { $ref: "#/components/responses/Error" }
components:
parameters:
NodeId:
name: nodeId
in: path
required: true
schema:
type: string
responses:
Error:
description: Request failed
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
schemas:
Node:
type: object
additionalProperties: false
required:
- id
- lookupCode
- parentId
- name
- description
- quantity
- typeId
- tagIds
properties:
id:
type: string
lookupCode:
type: string
description: Stable human-enterable lookup key; not the internal identity.
pattern: "^[A-Z2-7]{6}$"
parentId:
type:
- string
- "null"
description: Null only for Root.
name:
type: string
minLength: 1
description:
type:
- string
- "null"
quantity:
type:
- integer
- "null"
minimum: 0
typeId:
type: [string, "null"]
tagIds:
type: array
uniqueItems: true
items: { type: string }
ImportNode:
type: object
additionalProperties: false
required:
- name
properties:
name:
type: string
minLength: 1
description:
type: string
quantity:
type:
- integer
- "null"
minimum: 0
children:
type: array
items:
$ref: "#/components/schemas/ImportNode"
TreeImportManifest:
type: object
additionalProperties: false
required:
- nodes
properties:
nodes:
type: array
minItems: 1
maxItems: 10000
items:
$ref: "#/components/schemas/ImportNode"
TreeImportSummary:
type: object
additionalProperties: false
required:
- nodes
- maximumDepth
properties:
nodes:
type: integer
minimum: 1
maximumDepth:
type: integer
minimum: 1
maximum: 64
TreeImportPreviewRequest:
type: object
additionalProperties: false
required:
- parentId
- manifest
properties:
parentId:
type: string
manifest:
$ref: "#/components/schemas/TreeImportManifest"
TreeImportPreview:
type: object
additionalProperties: false
required:
- planId
- summary
- warnings
- manifest
properties:
planId:
type: string
summary:
$ref: "#/components/schemas/TreeImportSummary"
warnings:
type: array
items:
type: string
manifest:
$ref: "#/components/schemas/TreeImportManifest"
TreeImportCommitRequest:
type: object
additionalProperties: false
required:
- planId
properties:
planId:
type: string
TreeImportCommitResponse:
type: object
additionalProperties: false
required:
- created
properties:
created:
$ref: "#/components/schemas/TreeImportSummary"
TreeNode:
type: object
additionalProperties: false
required:
- id
- lookupCode
- parentId
- name
- description
- quantity
- typeId
- tagIds
- children
properties:
id:
type: string
lookupCode:
type: string
pattern: "^[A-Z2-7]{6}$"
parentId:
type:
- string
- "null"
description: Null only for Root.
name:
type: string
minLength: 1
description:
type:
- string
- "null"
quantity:
type:
- integer
- "null"
minimum: 0
typeId:
type: [string, "null"]
tagIds:
type: array
uniqueItems: true
items: { type: string }
children:
type: array
items:
$ref: "#/components/schemas/TreeNode"
CreateNodeRequest:
type: object
additionalProperties: false
required:
- name
properties:
parentId:
type: string
description: Omit to place the node beneath Unsorted.
name:
type: string
minLength: 1
description:
type:
- string
- "null"
quantity:
type:
- integer
- "null"
minimum: 0
CreateNodesBulkRequest:
type: object
additionalProperties: false
required:
- parentId
- names
properties:
parentId:
type: string
names:
type: array
minItems: 1
items:
type: string
minLength: 1
description:
type:
- string
- "null"
CreateNodesBulkResponse:
type: object
additionalProperties: false
required:
- nodes
properties:
nodes:
type: array
items:
$ref: "#/components/schemas/Node"
MoveNodesBulkRequest:
type: object
additionalProperties: false
required:
- nodeIds
- targetParentId
properties:
nodeIds:
type: array
minItems: 1
uniqueItems: true
items:
type: string
targetParentId:
type: string
childHandling:
type: string
enum:
- WITH_SUBTREE
- PROMOTE_CHILDREN
- CHILDREN_TO_UNSORTED
default: WITH_SUBTREE
MoveNodesBulkResponse:
type: object
additionalProperties: false
required:
- nodes
properties:
nodes:
type: array
items:
$ref: "#/components/schemas/Node"
DeleteNodesBulkRequest:
type: object
additionalProperties: false
required:
- nodeIds
properties:
nodeIds:
type: array
minItems: 1
uniqueItems: true
items:
type: string
IndividualizeNodeRequest:
type: object
additionalProperties: false
required:
- names
properties:
names:
type: array
minItems: 2
maxItems: 1000
items:
type: string
minLength: 1
CombineNodesRequest:
type: object
additionalProperties: false
required:
- nodeIds
- retainedNodeId
- name
properties:
nodeIds:
type: array
minItems: 2
uniqueItems: true
items:
type: string
retainedNodeId:
type: string
description: A member of nodeIds whose UUID and lookup code survive.
name:
type: string
minLength: 1
UpdateNodeRequest:
type: object
additionalProperties: false
minProperties: 1
properties:
name:
type: string
minLength: 1
description:
type:
- string
- "null"
quantity:
type:
- integer
- "null"
minimum: 0
NodeType:
type: object
additionalProperties: false
required: [id, name, description, iconKey, color]
properties:
id: { type: string }
name: { type: string, minLength: 1 }
description: { type: [string, "null"] }
iconKey: { type: [string, "null"] }
color: { type: [string, "null"] }
NodeTypeWrite:
type: object
additionalProperties: false
required: [name]
properties:
name: { type: string, minLength: 1 }
description: { type: [string, "null"] }
iconKey: { type: [string, "null"] }
color: { type: [string, "null"] }
Tag:
type: object
additionalProperties: false
required: [id, name, color]
properties:
id: { type: string }
name: { type: string, minLength: 1 }
color: { type: [string, "null"] }
TagWrite:
type: object
additionalProperties: false
required: [name]
properties:
name: { type: string, minLength: 1 }
color: { type: [string, "null"] }
ClassificationRequest:
type: object
additionalProperties: false
required: [typeId, tagIds]
properties:
typeId: { type: [string, "null"] }
tagIds:
type: array
uniqueItems: true
items: { type: string }
BulkClassificationRequest:
type: object
additionalProperties: false
required: [nodeIds, setType, typeId, addTagIds, removeTagIds]
properties:
nodeIds:
type: array
minItems: 1
uniqueItems: true
items: { type: string }
setType: { type: boolean }
typeId: { type: [string, "null"] }
addTagIds:
type: array
uniqueItems: true
items: { type: string }
removeTagIds:
type: array
uniqueItems: true
items: { type: string }
MoveNodeRequest:
type: object
additionalProperties: false
required:
- targetParentId
properties:
targetParentId:
type: string
childHandling:
type: string
enum:
- WITH_SUBTREE
- PROMOTE_CHILDREN
- CHILDREN_TO_UNSORTED
default: WITH_SUBTREE
Error:
type: object
additionalProperties: false
required:
- code
- message
properties:
code:
type: string
message:
type: string