ainote Sync API

The sync API from ainote — 10 operation(s) for sync.

Operations 10

POST /api/mcp/tools/sync_push Push a markdown file into the primary vault. #
POST /api/mcp/tools/sync_push_batch Push MANY files into the primary vault in ONE call. #
POST /api/mcp/tools/sync_pull Legacy alias for pulling files from the primary vault. #
POST /api/mcp/tools/sync_list Legacy alias for listing files in the primary vault. #
POST /api/mcp/tools/sync_changes Read changes from the primary vault in sequence order, including deletions. #
POST /api/mcp/tools/sync_delete Delete a file from the primary vault. #
POST /api/mcp/tools/sync_merge Compute a stateless 3-way merge for a vault file. #
POST /api/mcp/tools/sync_diff Return the unified diff (and raw remote text) of a vault file. #
POST /api/mcp/tools/sync_pending_conflicts List unresolved vault_conflicts rows for the authenticated user's primary vault. #
POST /api/mcp/tools/sync_audit_layer5 Record the result of a client-side Layer 5 codex review (sync.py merge gate) as… #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • 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.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/ainote-dev:ainote-dev-sync-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API 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 Specification

ainote-dev-sync-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: ainote MCP — OpenAPI mirror Sync API
  version: 1.3.0
  description: OpenAPI 3.1 surface auto-generated from ainote's MCP tool registry. Use this with OpenAI Custom GPT Actions, LangChain remote tools, AutoGen, or any HTTP-first agent runtime that consumes OpenAPI. The native MCP (JSON-RPC) endpoint at POST /api/mcp remains the recommended path for Claude/Cursor/Windsurf. Tool semantics (annotations, idempotency, destructiveness) are identical across both surfaces — see x-mcp-annotations.
  contact:
    name: ainote
    url: https://docs.ainote.dev
  license:
    name: MIT
servers:
- url: https://api.ainote.dev
security:
- McpKeyAuth: []
tags:
- name: Sync
paths:
  /api/mcp/tools/sync_push:
    post:
      operationId: tool_sync_push
      summary: Push a markdown file into the primary vault.
      description: 'Push a markdown file into the primary vault. Optional CAS via base_sha to detect concurrent multi-PC writes (Layer 3 of multi-PC sync plan). WAF-bypass tip: large bodies (~10KB+) that get false-positive blocked at Cloudflare can be sent via `content_b64` (base64-encoded) OR `content` prefixed with `__B64__:` instead. When the push CREATES a new .md file, the response may carry `dedup_candidates` — existing memory files that look similar (keyword + title similarity, no LLM). It is an advisory, not a rejection: YOU decide to merge into one of them (re-push that path), drop this write as a duplicate (skip), or keep it as a new memory (store).'
      tags:
      - Sync
      x-mcp-annotations:
        readOnlyHint: false
        destructiveHint: true
        idempotentHint: true
        openWorldHint: false
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                path:
                  type: string
                  description: Relative file path (e.g., 'global/MEMORY.md', 'launchcrew/firebase.md'). No leading slash, no '..'.
                content:
                  type: string
                  description: Full file content (markdown text). Alternatively prefix with '__B64__:' followed by base64 payload for WAF bypass.
                content_b64:
                  type: string
                  description: 'Optional: base64-encoded file content (use INSTEAD of `content`). For WAF-bypass on large bodies. Server decodes before storing. If both supplied, content_b64 wins.'
                base_sha:
                  type: string
                  description: 'Optional: git_sha the client last observed for this path. When present, server compares with current git_sha and returns -32009 conflict on mismatch (with current content for 3-way diff). Omit for legacy LWW behavior (response will include a `warning` field nudging clients to upgrade).'
                device_id:
                  type: string
                  description: 'Optional: client device identifier (e.g., from ~/.claude/ainote-sync/device.id). Stored on FileIndex so future conflict responses can report which device last wrote the path.'
                force:
                  type: boolean
                  description: 'Optional: when true, skip CAS check even if base_sha is supplied. Use only for intentional overwrites; presence is auditable via warning logs.'
                resolves_conflict_id:
                  type: string
                  description: 'Optional: UUID of a vault_conflicts row this push resolves. When supplied, server validates ownership/unresolved/path/sha and atomically marks the conflict as resolution=clean inside the same transaction as the file_indices write. Validation failure rolls back the whole push and returns -32009 stale_conflict_id.'
                supports_superseded:
                  type: boolean
                  description: Optional capability opt-in. When true AND resolves_conflict_id points at an already-resolved conflict whose (path, remote_sha) matches this push, the server returns a NORMAL 200 with resource_data {status:'superseded', reason:'resolved_elsewhere', applied:false, git_sha:<current remote>} instead of a -32009 error, so the client pulls to converge. Omit (default) to keep the legacy -32009 contract.
              required:
              - path
      responses:
        '200':
          description: Tool executed successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ToolSuccessResponse'
        '400':
          description: Invalid arguments or business-rule violation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ToolErrorResponse'
        '401':
          description: Missing or invalid McpKey
  /api/mcp/tools/sync_push_batch:
    post:
      operationId: tool_sync_push_batch
      summary: Push MANY files into the primary vault in ONE call.
      description: 'Push MANY files into the primary vault in ONE call. Use this instead of looping sync_push whenever you have more than a couple of changed paths — the cost of sync_push is round trips, not bytes. Per-item semantics are identical to sync_push (Layer 3 base_sha CAS, superseded contract, content_b64 WAF fallback). Partial success is normal and returns HTTP 200: read `results[]` and match entries by `path`, NOT by position. A conflict result always carries `remote_sha` + `conflict_reason` so you can go straight to sync_merge. Request-level failures (duplicate paths in one batch, idempotency key reused with a different payload, >200 items, >4MB) return 4xx and apply NOTHING. Each item MUST carry `content_sha` (SHA1 hex of the decoded body, same algorithm as git_sha) — it powers both the integrity check and the retry-safe `skipped_identical` result. Newly created .md items may carry `dedup_candidates` (same merge/skip/store advisory as sync_push); a batch creating more than 10 new files skips the check entirely and reports `dedup_skipped: "bulk"`.'
      tags:
      - Sync
      x-mcp-annotations:
        readOnlyHint: false
        destructiveHint: true
        idempotentHint: true
        openWorldHint: false
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                items:
                  type: array
                  description: Up to 200 push items, 4MB total, one entry per unique path. Duplicate paths reject the whole batch.
                  items:
                    type: object
                    properties:
                      path:
                        type: string
                        description: Relative file path. No leading slash, no '..'.
                      content:
                        type: string
                        description: Full file content. May use the '__B64__:' prefix like sync_push.
                      content_b64:
                        type: string
                        description: Optional base64 body (use INSTEAD of content) for WAF bypass. Wins over content if both are present.
                      content_sha:
                        type: string
                        description: REQUIRED. SHA1 hex of the decoded content. Mismatch fails this item only (status 'error'); equality with the current remote git_sha yields 'skipped_identical' instead of a conflict, which is what makes a crashed batch safe to retry.
                      base_sha:
                        type: string
                        description: 'Same tri-state semantics as sync_push: omit for legacy LWW, null to assert the path does not exist yet, or the last observed git_sha for CAS.'
                      resolves_conflict_id:
                        type: string
                        description: Optional vault_conflicts UUID this item closes. Requires a non-null base_sha and force=false.
                      force:
                        type: boolean
                        description: Optional per-item CAS bypass (audited). Suppresses the skipped_identical short-circuit.
                      device_id:
                        type: string
                        description: Optional per-item device id; falls back to the batch-level device_id.
                    required:
                    - path
                    - content_sha
                idempotency_key:
                  type: string
                  description: 'REQUIRED. Opaque client-generated UUID, one per batch ATTEMPT-SET: reuse the same key when retrying the same items after a timeout (the server replays the stored results instead of re-applying), and generate a NEW key whenever the items change. Reusing a key with a different payload is a 400 collision, never a silent replay. Do not derive it from paths or content.'
                device_id:
                  type: string
                  description: Optional batch-level device identifier; per-item device_id overrides it.
                supports_superseded:
                  type: boolean
                  description: Same capability opt-in as sync_push, applied to every item in the batch.
              required:
              - items
              - idempotency_key
      responses:
        '200':
          description: Tool executed successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ToolSuccessResponse'
        '400':
          description: Invalid arguments or business-rule violation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ToolErrorResponse'
        '401':
          description: Missing or invalid McpKey
  /api/mcp/tools/sync_pull:
    post:
      operationId: tool_sync_pull
      summary: Legacy alias for pulling files from the primary vault.
      description: 'Legacy alias for pulling files from the primary vault. Paginated: default 25 files per call, follow `next_cursor` for the rest. To fetch specific files, pass `paths` (up to 100 exact paths in one call) instead of pulling their whole directory.'
      tags:
      - Sync
      x-mcp-annotations:
        readOnlyHint: true
        destructiveHint: false
        idempotentHint: true
        openWorldHint: false
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                since:
                  type: string
                  description: ISO 8601 timestamp. Only return files updated after this time. Omit to start from the first page. Deletions are not reported.
                path:
                  type: string
                  description: 'Optional filter: a directory (everything under it, e.g. ''global'') or an exact file path (e.g. ''global/MEMORY.md''). A trailing slash is ignored.'
                paths:
                  type: array
                  items:
                    type: string
                  description: Up to 100 exact file paths fetched in ONE call. Absent paths are listed in `missing`. Cannot be combined with path/since/cursor.
                limit:
                  type: integer
                  description: Max files per page. Default 25, max 100.
                cursor:
                  type: string
                  description: Pass `next_cursor` from the previous response to fetch the next page.
      responses:
        '200':
          description: Tool executed successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ToolSuccessResponse'
        '400':
          description: Invalid arguments or business-rule violation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ToolErrorResponse'
        '401':
          description: Missing or invalid McpKey
  /api/mcp/tools/sync_list:
    post:
      operationId: tool_sync_list
      summary: Legacy alias for listing files in the primary vault.
      description: 'Legacy alias for listing files in the primary vault. Paginated: default 200 entries per call, follow `next_cursor` for the rest.'
      tags:
      - Sync
      x-mcp-annotations:
        readOnlyHint: true
        destructiveHint: false
        idempotentHint: true
        openWorldHint: false
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                path:
                  type: string
                  description: A directory to list (everything under it, e.g. 'global') or an exact file path (e.g. 'global/MEMORY.md'). A trailing slash is ignored. Omit to list from the first page.
                since:
                  type: string
                  description: ISO 8601 timestamp. Only list files updated strictly after this time. Deletions are not reported — diff a full list against your local copy to find them.
                limit:
                  type: integer
                  description: Max entries per page. Default 200, max 1000.
                cursor:
                  type: string
                  description: Pass `next_cursor` from the previous response to fetch the next page.
      responses:
        '200':
          description: Tool executed successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ToolSuccessResponse'
        '400':
          description: Invalid arguments or business-rule violation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ToolErrorResponse'
        '401':
          description: Missing or invalid McpKey
  /api/mcp/tools/sync_changes:
    post:
      operationId: tool_sync_changes
      summary: Read changes from the primary vault in sequence order, including deletions.
      description: Read changes from the primary vault in sequence order, including deletions. Start with since_seq=0 for a full listing; then pass next_seq and feed_epoch on each page. Default limit 500, max 1000. On reset_required, discard the cursor and restart from 0 without an epoch. On feed_unavailable, fall back to sync_list. Fetch changed content with sync_pull(paths:).
      tags:
      - Sync
      x-mcp-annotations:
        readOnlyHint: true
        destructiveHint: false
        idempotentHint: true
        openWorldHint: false
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                since_seq:
                  type: integer
                  minimum: 0
                  default: 0
                  description: Last applied sequence; 0 starts a full listing.
                feed_epoch:
                  type: string
                  description: Epoch from the previous response; a mismatch requires a full reset.
                limit:
                  type: integer
                  minimum: 1
                  maximum: 1000
                  default: 500
                  description: Max combined file and deletion entries per page.
      responses:
        '200':
          description: Tool executed successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ToolSuccessResponse'
        '400':
          description: Invalid arguments or business-rule violation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ToolErrorResponse'
        '401':
          description: Missing or invalid McpKey
  /api/mcp/tools/sync_delete:
    post:
      operationId: tool_sync_delete
      summary: Delete a file from the primary vault.
      description: 'Delete a file from the primary vault. Optional CAS via base_sha to detect concurrent multi-PC writes. Protected paths (global/memory/, global/skills/, global/planning/, global/intent/, global/claude-config/, handoffs/) require base_sha or explicit force:true (audited). Idempotent: deleting a non-existent path returns success with deleted:false.'
      tags:
      - Sync
      x-mcp-annotations:
        readOnlyHint: false
        destructiveHint: true
        idempotentHint: true
        openWorldHint: false
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                path:
                  type: string
                  description: Relative file path to delete (e.g., 'global/_waf_probe.md'). No leading slash, no '..'.
                base_sha:
                  type: string
                  description: 'Optional: git_sha the client last observed for this path. When present, server compares with current git_sha and returns -32009 conflict on mismatch (with current content for 3-way diff).'
                device_id:
                  type: string
                  description: 'Optional: client device identifier for audit log (e.g., from ~/.claude/ainote-sync/device.id).'
                force:
                  type: boolean
                  description: 'Optional: when true, skip CAS check even if base_sha is supplied. Use only for intentional overwrites; presence is auditable via warning logs.'
              required:
              - path
      responses:
        '200':
          description: Tool executed successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ToolSuccessResponse'
        '400':
          description: Invalid arguments or business-rule violation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ToolErrorResponse'
        '401':
          description: Missing or invalid McpKey
  /api/mcp/tools/sync_merge:
    post:
      operationId: tool_sync_merge
      summary: Compute a stateless 3-way merge for a vault file.
      description: Compute a stateless 3-way merge for a vault file. Server runs `git merge-file --diff3 --stdout` over (base_text, local_text, current remote from file_indices) and returns the merged text plus the exact remote_sha it merged against. NO database mutation — to commit the result, follow up with sync_push(content=merged_text, base_sha=merged_against.remote_sha, resolves_conflict_id=conflict_id).
      tags:
      - Sync
      x-mcp-annotations:
        readOnlyHint: true
        destructiveHint: false
        idempotentHint: true
        openWorldHint: false
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                path:
                  type: string
                  description: Relative vault path (e.g., 'global/MEMORY.md').
                base_text:
                  type: string
                  description: 'Common ancestor text — what the client had cached when it started editing. Source: client state.json baseline. Required.'
                base_sha:
                  type: string
                  description: 'Optional: git_sha the client believes is the merge base. When supplied, server verifies (informational; merge still runs).'
                local_text:
                  type: string
                  description: Current local text on the client (post-edit). Required.
                device_id:
                  type: string
                  description: 'Optional: client device identifier. Recorded on any vault_conflict row created downstream.'
              required:
              - path
              - base_text
              - local_text
      responses:
        '200':
          description: Tool executed successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ToolSuccessResponse'
        '400':
          description: Invalid arguments or business-rule violation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ToolErrorResponse'
        '401':
          description: Missing or invalid McpKey
  /api/mcp/tools/sync_diff:
    post:
      operationId: tool_sync_diff
      summary: Return the unified diff (and raw remote text) of a vault file.
      description: Return the unified diff (and raw remote text) of a vault file. Useful for surfacing what `sync_merge` would conflict on, or for the client to render a `git diff` view before pushing. NO database mutation. Server has no history — base_text must be supplied by the caller if a 3-way view is needed; otherwise this returns remote_text only.
      tags:
      - Sync
      x-mcp-annotations:
        readOnlyHint: true
        destructiveHint: false
        idempotentHint: true
        openWorldHint: false
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                path:
                  type: string
                  description: Relative vault path.
                local_text:
                  type: string
                  description: 'Optional: client''s current text. When supplied, response includes unified diff (remote → local).'
                base_text:
                  type: string
                  description: 'Optional: client''s baseline (last-known remote). When supplied along with local_text, response includes both diffs (base → remote, base → local) so the client can render a 3-way view.'
              required:
              - path
      responses:
        '200':
          description: Tool executed successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ToolSuccessResponse'
        '400':
          description: Invalid arguments or business-rule violation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ToolErrorResponse'
        '401':
          description: Missing or invalid McpKey
  /api/mcp/tools/sync_pending_conflicts:
    post:
      operationId: tool_sync_pending_conflicts
      summary: List unresolved vault_conflicts rows for the authenticated user's primary vault.
      description: List unresolved vault_conflicts rows for the authenticated user's primary vault. Used by clients (e.g. SessionStart hook) to surface conflicts that need merge attention. Returns up to `limit` rows ordered by most recent first.
      tags:
      - Sync
      x-mcp-annotations:
        readOnlyHint: true
        destructiveHint: false
        idempotentHint: true
        openWorldHint: false
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                limit:
                  type: integer
                  description: 'Optional: max rows to return (default 50, max 200).'
                path:
                  type: string
                  description: 'Optional: filter to a specific path.'
      responses:
        '200':
          description: Tool executed successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ToolSuccessResponse'
        '400':
          description: Invalid arguments or business-rule violation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ToolErrorResponse'
        '401':
          description: Missing or invalid McpKey
  /api/mcp/tools/sync_audit_layer5:
    post:
      operationId: tool_sync_audit_layer5
      summary: Record the result of a client-side Layer 5 codex review (sync.py merge gate) as…
      description: 'Record the result of a client-side Layer 5 codex review (sync.py merge gate) as a vault_events row. Body of the review is NOT stored — only an HMAC digest of the summary so operators can correlate without exposing review content. Opt-in: server skips writes (still returns success) unless ENV[''AINOTE_LAYER5_AUDIT'']=''on'' AND a versioned HMAC secret is configured. Used by the sync.py SessionStart hook + merge command to surface ''why was this blocked?'' across multi-PC sessions.'
      tags:
      - Sync
      x-mcp-annotations:
        readOnlyHint: false
        destructiveHint: false
        idempotentHint: false
        openWorldHint: false
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                path:
                  type: string
                  description: Vault path the review covered.
                verdict:
                  type: string
                  description: 'One of: pass, flag, block, error.'
                summary:
                  type: string
                  description: Free-form codex output summary. Server HMACs this; raw text is NEVER stored.
                chunk_count:
                  type: integer
                  description: 'Optional: number of diff chunks the client fed to codex.'
                duration_ms:
                  type: integer
                  description: 'Optional: wall-clock time of the codex review on the client.'
              required:
              - path
              - verdict
      responses:
        '200':
          description: Tool executed successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ToolSuccessResponse'
        '400':
          description: Invalid arguments or business-rule violation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ToolErrorResponse'
        '401':
          description: Missing or invalid McpKey
components:
  schemas:
    ToolSuccessResponse:
      type: object
      description: 'Successful tool invocation. `content` mirrors the MCP `tools/call` result shape: an array of content blocks (text and optionally a structured resource payload).'
      properties:
        content:
          type: array
          items:
            type: object
            properties:
              type:
                type: string
                enum:
                - text
                - resource
              text:
                type: string
    ToolErrorResponse:
      type: object
      description: Uniform error shape emitted by ainote MCP tool handlers.
      properties:
        error:
          type: object
          properties:
            code:
              type: integer
              description: JSON-RPC error code (-32xxx range)
            message:
              type: string
          required:
          - code
          - message
  securitySchemes:
    McpKeyAuth:
      type: apiKey
      in: header
      name: Authorization
      description: Send `McpKey <YOUR_MCP_KEY>`. Issue an MCP key at /settings/mcp or via `npx @ainote/mcp signup`.
x-ainote-meta:
  generator: Api::Mcp::OpenapiController
  generated_at: '2026-11-01T14:35:55Z'
  tools_count: 56
  native_mcp_endpoint: https://api.ainote.dev/api/mcp
  agent_compatibility_doc: https://github.com/ainote-dev/ainote-mcp#agent-compatibility