Granite Folders API
Create, rename, move, and delete folders. A folder is a path prefix, there while it holds a file; moving or deleting one changes all its files in one commit.
Create, rename, move, and delete folders. A folder is a path prefix, there while it holds a file; moving or deleting one changes all its files in one commit.
Every API here is available over the APIs.io API and to AI agents over MCP.
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
find_apisBrowse and filter every API in the catalog.get_api_artifactsOne API's artifacts, grouped by type.get_openapiThe primary OpenAPI for this API.find_similar_apisAPIs that look like this one.apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.resolveTurn a domain, URL or GitHub org into the provider it belongs to.find_cohortsEvery scored population of providers in the catalog.curl "https://apis.io/api/v1/apis/granite-md:granite-md-folders-api"
curl "https://apis.io/api/v1/apis?limit=25"
Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.
Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.
A second provider on the same verified email joins the account you already have.
openapi: 3.2.0
info:
title: Granite Folders API
version: 1.0.0
summary: REST API for Granite clients, bots, and integrations.
description: 'Conventions (apply to every operation; see PLAN.md 3.2 and 3.6):
- **Base URL** `https://api.granite.md`. All public operations live under `/v1`.
After Phase 6 ships, `/v1` changes are additive only.
- **Errors** use RFC 9457 problem details (`application/problem+json`, schema `Problem`).
The `type` URI is `https://granite.md/problems/`; `code` refines it for programmatic handling.
Every response carries `X-Request-ID`, also echoed as `request_id` in problems.
- **Pagination** is cursor based. List operations accept `cursor` and `limit` and return
`{ "items": [...], "next_cursor": "..." }`. `next_cursor` is absent on the last page.
Cursors are opaque; clients must not parse or build them.
- **Idempotency**: non-idempotent `POST` operations accept an `Idempotency-Key` header
(1-255 printable ASCII). Repeating a request with the same key and body within 24 hours
returns the original response; the same key with a different body returns `409` with
code `idempotency_key_reused`.
- **IDs** are UUIDv7 strings. **Timestamps** are RFC 3339 in UTC.
- **Authentication**: `Authorization: Bearer ` with a session access token,
a personal API token (`gr_pat_...`), or an OAuth access token. Scopes are listed per operation.
- **Rate limits**: each personal API token may make 600 requests a minute. Over the limit
the API answers `429` with code `token_rate_limited` and a `Retry-After` header (seconds).'
license:
name: Proprietary
identifier: LicenseRef-Proprietary
servers:
- url: https://api.granite.md
description: Production
- url: http://localhost:8080
description: Local development
security:
- bearerAuth: []
tags:
- name: Folders
description: 'Create, rename, move, and delete folders. A folder is a path prefix, there while it
holds a file; moving or deleting one changes all its files in one commit.'
paths:
/v1/vaults/{vault_id}/folders:
parameters:
- $ref: '#/components/parameters/VaultID'
post:
operationId: createFolder
tags:
- Folders
summary: Create a folder
description: 'A folder is there while it holds a file, so a new one starts with an empty
`Untitled.md`, as in the apps. A folder that already has files answers 409
`folder_exists`. Needs `vaults:write`, `sync`, or `folders:create`.'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/FolderCreate'
responses:
'201':
description: The folder and the note it starts with.
content:
application/json:
schema:
$ref: '#/components/schemas/Folder'
default:
$ref: '#/components/responses/Error'
delete:
operationId: deleteFolder
tags:
- Folders
summary: Delete a folder
description: 'Deletes every file in the folder and its subfolders in one commit (at most 500; a
larger folder answers 400 `folder_too_large`). Each file stays in version history and
can be restored. Needs `vaults:write`, `sync`, or `folders:edit`.'
parameters:
- name: path
in: query
required: true
schema:
type: string
minLength: 1
maxLength: 1024
responses:
'200':
description: The folder and how many files were deleted.
content:
application/json:
schema:
$ref: '#/components/schemas/FolderChange'
default:
$ref: '#/components/responses/Error'
/v1/vaults/{vault_id}/folders/move:
parameters:
- $ref: '#/components/parameters/VaultID'
post:
operationId: moveFolder
tags:
- Folders
summary: Rename or move a folder
description: 'Moves every file in the folder and its subfolders to `to` (the folder''s full new
path) in one commit, so it happens entirely or not at all (at most 500 files). A file
already at a new path answers 409 `path_taken`. Links are not rewritten. Needs
`vaults:write`, `sync`, or `folders:edit`.'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/FolderMove'
responses:
'200':
description: The folder's new path and how many files moved.
content:
application/json:
schema:
$ref: '#/components/schemas/FolderChange'
default:
$ref: '#/components/responses/Error'
components:
schemas:
FolderCreate:
type: object
required:
- path
properties:
path:
type: string
minLength: 1
maxLength: 1024
Folder:
type: object
required:
- path
- note
properties:
path:
type: string
note:
$ref: '#/components/schemas/Note'
FolderMove:
type: object
required:
- from
- to
properties:
from:
type: string
minLength: 1
maxLength: 1024
to:
type: string
minLength: 1
maxLength: 1024
description: The folder's full new path.
FolderChange:
type: object
required:
- path
- files
properties:
path:
type: string
description: The folder (its new path after a move).
files:
type: integer
description: How many files were moved or deleted.
Note:
type: object
required:
- id
- path
- version_id
- size
- updated_at
properties:
id:
type: string
format: uuid
path:
type: string
version_id:
type: string
format: uuid
size:
type: integer
format: int64
updated_at:
type: string
format: date-time
content:
type: string
description: The note's text; omitted in lists and after a move.
Problem:
type: object
description: RFC 9457 problem details.
required:
- type
- title
- status
properties:
type:
type: string
format: uri
examples:
- https://granite.md/problems/conflict
title:
type: string
status:
type: integer
format: int32
detail:
type: string
instance:
type: string
code:
type: string
description: Machine-readable refinement of `type`, for example `version_conflict`.
request_id:
type: string
errors:
type: array
description: Per-field validation errors.
items:
$ref: '#/components/schemas/FieldError'
FieldError:
type: object
required:
- field
- detail
properties:
field:
type: string
description: JSON path of the invalid field, for example `ops[2].path`.
detail:
type: string
headers:
RequestID:
description: Identifier of this request, for support and log correlation.
schema:
type: string
parameters:
VaultID:
name: vault_id
in: path
required: true
schema:
type: string
format: uuid
responses:
Error:
description: Error response.
headers:
X-Request-ID:
$ref: '#/components/headers/RequestID'
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
securitySchemes:
bearerAuth:
type: http
scheme: bearer
description: Session access token, personal API token, or OAuth access token.