Hjarni Files API

Attaching files to notes.

GitHub OpenAPI

Operations 1

POST /notes/{note_id}/files Attach a file to a note from a URL #

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/hjarni-com:hjarni-com-files-api"
All apis
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.

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

hjarni-com-files-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Hjarni REST Files API
  version: 1.0.0
  description: Hjarni is a Markdown knowledge base that AI assistants and people share; this API reads and writes the same notes, folders (called containers) and tags that its MCP server exposes. Requests go to https://hjarni.com/api/v1 with a bearer token in the Authorization header, send and receive JSON, and list endpoints page with `page` and `per_page` and report totals in the `X-Total-Count`, `X-Page` and `X-Per-Page` headers. Requests are limited to 100 a minute per account across all of its tokens, and going over answers 429 with a `Retry-After` header.
  termsOfService: https://hjarni.com/terms
  contact:
    name: Hjarni
    email: evert@hjarni.com
    url: https://hjarni.com/docs/api
servers:
- url: https://hjarni.com/api/v1
security:
- bearerAuth: []
tags:
- name: Files
  description: Attaching files to notes.
paths:
  /notes/{note_id}/files:
    parameters:
    - $ref: '#/components/parameters/NoteIdForFiles'
    post:
      operationId: attachFileFromUrl
      summary: Attach a file to a note from a URL
      description: Hjarni downloads `url` (http or https, up to 3 redirects, no private or internal addresses, 25 MB at most) and attaches the result to the note, answering 201. Personal notes only, for agent tokens too. On the Free plan, personal attachments are limited to 20 MB and five files; going over is refused with 403 and an `upgrade_url`. A URL that cannot be fetched answers 422 with the reason.
      tags:
      - Files
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - url
              properties:
                url:
                  type: string
                  format: uri
                  description: The file to fetch. Missing or blank answers 422 with `{"error":"url is required"}`.
                filename:
                  type: string
                  description: Overrides the name taken from the URL's path (`download` when it has none).
                content_type:
                  type: string
                  description: Overrides the type from the response's Content-Type (`application/octet-stream` when absent).
                description:
                  type: string
                  description: Shown with the attachment.
            example:
              url: https://example.com/slides.pdf
              description: Slide deck
      responses:
        '201':
          description: The attached file.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreatedNoteFile'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
        '429':
          $ref: '#/components/responses/TooManyRequests'
components:
  responses:
    UnprocessableEntity:
      description: The request was understood but not applied. Model validations answer with an `errors` array of messages; parameter checks (an unknown note key, a surgical edit whose anchor does not match, a missing file `url`, `ordered_ids` that do not match the folders in scope, a URL that could not be fetched) answer with an `errors` array or a single `error` string, as noted on each endpoint.
      content:
        application/json:
          schema:
            anyOf:
            - $ref: '#/components/schemas/ValidationErrors'
            - $ref: '#/components/schemas/Error'
          examples:
            validation:
              summary: Model validation
              value:
                errors:
                - Title can't be blank
            parameterCheck:
              summary: Parameter check
              value:
                error: ordered_ids must contain exactly all containers in this scope
    TooManyRequests:
      description: Over the rate limit of 100 requests a minute per account, counted across all of its tokens (counters are kept per server process, so the ceiling actually enforced can be somewhat higher). Wait the number of seconds in `Retry-After`. The body has `error` only.
      headers:
        Retry-After:
          $ref: '#/components/headers/Retry-After'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: Rate limit exceeded. Retry after 12 seconds.
    NotFound:
      description: No record with that id that this token can reach (including notes and folders in the Trash, except where an endpoint says otherwise), or no endpoint for this method and path. A revision that does not exist answers with `error` only.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            status: 404
            error: Not Found
            code: not_found
            message: No endpoint matches this method and path, or the record is not one this token can reach. Every endpoint is listed in https://hjarni.com/openapi.json.
            docs_url: https://hjarni.com/docs/api#errors
    BadRequest:
      description: The body could not be read (malformed JSON), or a required wrapper or parameter such as `note`, `container`, `tag` or `ordered_ids` is missing or empty.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            status: 400
            error: Bad Request
            code: bad_request
            message: The ordered_ids parameter is missing or empty. Each endpoint's request body is in https://hjarni.com/openapi.json.
            docs_url: https://hjarni.com/docs/api#errors
    Forbidden:
      description: 'Refused, for one of three reasons. (1) A plan limit: the Free plan''s note limit on create or restore, the Free file allowance on an attachment, or an account that is read-only because it holds more notes than its plan carries. The body has `error` and an `upgrade_url`, and the personal note-limit refusal also a `team_url`. (2) An agent token outside its grants: reading or writing where it was not given access, writing where it only reads, or calling an endpoint agent tokens cannot use. The body has `error` "Forbidden: outside token scope" with `code` `out_of_scope`, `message` and `docs_url`, and no `upgrade_url`. (3) A team folder where the person''s role is below editor: `error` only, "You don''t have permission to do that (editor required)."'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            outOfScope:
              summary: Agent token outside its grants
              value:
                error: 'Forbidden: outside token scope'
                code: out_of_scope
                message: This token cannot do this. An agent token reaches only the folders it was given, at the level it was given, and never manages tags, personal instructions or folder order; those need a full-access token. A token's access is set in Settings > Connections.
                docs_url: https://hjarni.com/docs/agent-tokens
            noteLimit:
              summary: Free plan note limit reached
              value:
                error: You've reached the 25 personal note limit on the Free plan. Upgrade to Pro for unlimited notes, or start a shared team knowledge base if this should live with your teammates.
                upgrade_url: /checkout/new?reason=note_limit&ref=paywall_note_limit&t=CHECKOUT_TOKEN
                team_url: /teams/new?ref=paywall_note_limit
            editorRequired:
              summary: Team role below editor
              value:
                error: You don't have permission to do that (editor required).
    Unauthorized:
      description: The bearer token is missing, unknown or expired.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: Unauthorized
            code: unauthorized
            message: 'Missing or invalid token. Send it as Authorization: Bearer <token>; tokens are created in Settings > Connections.'
            docs_url: https://hjarni.com/docs/api#auth
  parameters:
    NoteIdForFiles:
      name: note_id
      in: path
      required: true
      description: The id of the personal note to attach to.
      schema:
        type: integer
  schemas:
    CreatedNoteFile:
      type: object
      description: The attachment created by POST /notes/{note_id}/files.
      required:
      - id
      - filename
      - content_type
      - byte_size
      - description
      properties:
        id:
          type: integer
        filename:
          type: string
        content_type:
          type: string
        byte_size:
          type: integer
        description:
          type:
          - string
          - 'null'
    Error:
      type: object
      description: 'Every error response carries `error`. The generic statuses also carry `code`, `message` and `docs_url`: 401, a 403 for an agent token outside its grants, and any status answered for a raised error or an unknown endpoint (400, 404, 5xx). Plan-limit 403s carry `upgrade_url` instead. Some endpoint-specific errors carry `error` alone.'
      required:
      - error
      properties:
        status:
          type: integer
          description: The HTTP status again. Present on errors raised inside the app and on unknown endpoints (400, 404, 5xx), not on 401 or the 403s.
        error:
          type: string
          description: Human-readable message.
        errors:
          type: array
          items:
            type: string
          description: 'Only on a validation failure raised inside the app (422): one message per problem.'
        code:
          type: string
          description: 'Machine-readable code: `unauthorized` (401), `out_of_scope` (403, agent token), or for a raised error or unknown endpoint the snake_case name of the HTTP status, such as `bad_request`, `not_found`, `unprocessable_content` or `internal_server_error`.'
          examples:
          - unauthorized
          - out_of_scope
          - not_found
          - internal_server_error
        message:
          type: string
          description: What to do about it.
        docs_url:
          type: string
          format: uri
          description: The documentation page that explains this error.
        upgrade_url:
          type: string
          format: uri-reference
          description: Only on plan-limit 403s. A path on hjarni.com (relative, so prefix https://hjarni.com) to the checkout that lifts the limit.
        team_url:
          type: string
          format: uri-reference
          description: Only on the personal note-limit 403 from POST /notes. A relative path to creating a team, the other way past the personal limit.
    ValidationErrors:
      type: object
      description: The 422 model-validation shape, also used by a few 409s.
      required:
      - errors
      properties:
        errors:
          type: array
          items:
            type: string
          description: One human-readable message per problem.
  headers:
    Retry-After:
      description: Seconds until the current rate-limit window ends.
      schema:
        type: integer
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: 'An API token in `Authorization: Bearer <token>`. Tokens are created in Settings > Connections, or issued to an assistant through the OAuth flow. A new token made in Settings reaches only the folders it is given, at Read or Write per folder, unless it is made with Everything I can reach (see https://hjarni.com/docs/agent-tokens); a token issued through OAuth acts with the person''s full access. A missing, unknown or expired token answers 401.'
externalDocs:
  url: https://hjarni.com/docs/api