Granite Note Shares API
One note shared for editing with someone, by email.
One note shared for editing with someone, by email.
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-note-shares-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 Note Shares 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: note-shares
description: One note shared for editing with someone, by email.
paths:
/v1/vaults/{vault_id}/files/{file_id}/shares:
parameters:
- $ref: '#/components/parameters/VaultID'
- $ref: '#/components/parameters/FileID'
get:
operationId: listNoteShares
tags:
- note-shares
summary: People a note is shared with
responses:
'200':
description: The note's shares, oldest first.
content:
application/json:
schema:
$ref: '#/components/schemas/NoteShareList'
default:
$ref: '#/components/responses/Error'
post:
operationId: shareNote
tags:
- note-shares
summary: Share a note for editing by email
description: 'Invites someone to edit one note of a personal vault (they see nothing else in it). An
email with a link goes to the address. Needs vault admin access and a plan with note
sharing (`plan_limit_note_sharing`); the invitee needs such a plan too before the note
opens for them. Workspace vaults share through grants instead (`workspace_vault`).
Sharing again with the same address returns the existing share.'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ShareNoteRequest'
responses:
'201':
description: The share.
content:
application/json:
schema:
$ref: '#/components/schemas/NoteShare'
default:
$ref: '#/components/responses/Error'
/v1/vaults/{vault_id}/files/{file_id}/shares/{share_id}:
parameters:
- $ref: '#/components/parameters/VaultID'
- $ref: '#/components/parameters/FileID'
- name: share_id
in: path
required: true
schema:
type: string
format: uuid
delete:
operationId: unshareNote
tags:
- note-shares
summary: Stop sharing a note with someone
responses:
'204':
description: The person loses access at once (an open editor closes).
default:
$ref: '#/components/responses/Error'
/v1/me/shared-notes:
get:
operationId: listSharedWithMe
tags:
- note-shares
summary: Notes others shared with me
description: 'Notes shared with the caller''s verified email. `available` is false when a plan stands in
the way (`reason`): the caller needs to upgrade, or the owner''s plan no longer shares.'
responses:
'200':
description: Shared notes, newest first.
content:
application/json:
schema:
$ref: '#/components/schemas/SharedNoteList'
default:
$ref: '#/components/responses/Error'
components:
schemas:
NoteShareList:
type: object
required:
- items
properties:
items:
type: array
items:
$ref: '#/components/schemas/NoteShare'
SharedNoteList:
type: object
required:
- items
properties:
items:
type: array
items:
$ref: '#/components/schemas/SharedNote'
ShareNoteRequest:
type: object
required:
- email
properties:
email:
type: string
format: email
maxLength: 320
SharedNote:
type: object
required:
- id
- vault_id
- file_id
- path
- owner_name
- owner_email
- shared_at
- available
properties:
id:
type: string
format: uuid
vault_id:
type: string
format: uuid
file_id:
type: string
format: uuid
path:
type: string
owner_name:
type: string
owner_email:
type: string
shared_at:
type: string
format: date-time
available:
type: boolean
description: The note opens for the caller now.
reason:
type: string
enum:
- upgrade_required
- owner_plan
- email_unverified
description: Why it does not open (only when available is false).
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'
NoteShare:
type: object
required:
- id
- file_id
- email
- access
- created_at
properties:
id:
type: string
format: uuid
file_id:
type: string
format: uuid
email:
type: string
access:
type: string
enum:
- write
created_at:
type: string
format: date-time
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
FileID:
name: file_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.