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: 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