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.
openapi: 3.2.0
info:
title: harvis.dev Files API
version: '1'
description: Everything an account can control, over HTTP. This document is generated from lib/api/contract.ts, which is also what the dashboard's server actions call — so what the harvis CLI can do and what the web app can do are the same list by construction. Do not edit this file by hand; run `bun run api:generate`.
servers:
- url: https://harvis.dev
tags:
- name: Files
description: The files of one site.
paths:
/api/v1/sites/{id}/files:
get:
operationId: files.list
summary: Every file a site is serving
description: Paths are relative to the site root. To read a file's contents, fetch it from the site's own URL — it is a public web page.
tags:
- Files
security:
- apiKey: []
- session: []
parameters:
- name: id
in: path
required: true
schema:
type: string
responses:
'200':
description: Every file a site is serving.
content:
application/json:
schema:
$ref: '#/components/schemas/SiteFileList'
'401':
description: '`unauthorized`'
content:
application/json:
schema:
$ref: '#/components/schemas/ApiError'
'403':
description: '`suspended`'
content:
application/json:
schema:
$ref: '#/components/schemas/ApiError'
'404':
description: '`siteNotFound`'
content:
application/json:
schema:
$ref: '#/components/schemas/ApiError'
post:
operationId: files.add
summary: Add or overwrite individual files, leaving the rest of the site alone
description: 'Unlike sites.deploy, paths are taken exactly as given: nothing is stripped and nothing is deleted. Use this to change one page; use sites.deploy to publish a rebuilt folder.'
tags:
- Files
security:
- apiKey: []
- session: []
parameters:
- name: id
in: path
required: true
schema:
type: string
requestBody:
required: true
content:
multipart/form-data:
schema:
$ref: '#/components/schemas/AddFilesInput'
responses:
'200':
description: Add or overwrite individual files, leaving the rest of the site alone.
content:
application/json:
schema:
$ref: '#/components/schemas/AddFilesResult'
'400':
description: '`invalidRequest`, `noFiles`'
content:
application/json:
schema:
$ref: '#/components/schemas/ApiError'
'401':
description: '`unauthorized`'
content:
application/json:
schema:
$ref: '#/components/schemas/ApiError'
'403':
description: '`suspended`'
content:
application/json:
schema:
$ref: '#/components/schemas/ApiError'
'404':
description: '`siteNotFound`'
content:
application/json:
schema:
$ref: '#/components/schemas/ApiError'
'413':
description: '`tooLarge`, `tooManyFiles`'
content:
application/json:
schema:
$ref: '#/components/schemas/ApiError'
components:
schemas:
Site:
type: object
properties:
id:
type: string
name:
type: string
subdomain:
type: string
url:
description: Where the site is served, e.g. https://sunny-otter-42.harvis.page.
type: string
entrypoint:
description: The file served at the site's root.
type: string
fileCount:
type: integer
minimum: -9007199254740991
maximum: 9007199254740991
totalSize:
description: Bytes stored, summed over every file.
type: integer
minimum: -9007199254740991
maximum: 9007199254740991
createdAt:
format: date-time
type: string
updatedAt:
format: date-time
type: string
required:
- id
- name
- subdomain
- url
- entrypoint
- fileCount
- totalSize
- createdAt
- updatedAt
additionalProperties: false
SiteFileList:
type: object
properties:
files:
type: array
items:
$ref: '#/components/schemas/SiteFile'
required:
- files
additionalProperties: false
SiteFile:
type: object
properties:
path:
description: Relative to the site root, e.g. assets/app.css.
type: string
contentType:
type: string
size:
type: integer
minimum: -9007199254740991
maximum: 9007199254740991
required:
- path
- contentType
- size
additionalProperties: false
AddFilesResult:
type: object
properties:
site:
$ref: '#/components/schemas/Site'
added:
type: integer
minimum: -9007199254740991
maximum: 9007199254740991
required:
- site
- added
additionalProperties: false
AddFilesInput:
type: object
properties:
files:
type: array
items:
type: string
format: binary
contentEncoding: binary
paths:
description: One per file, same order — the path relative to the site root.
type: array
items:
type: string
required:
- files
- paths
additionalProperties: false
ApiError:
type: object
properties:
error:
type: object
properties:
code:
description: A stable machine code — see docs/api.md for the full list.
type: string
message:
description: English prose, for a human reading a log.
type: string
required:
- code
- message
additionalProperties: false
required:
- error
additionalProperties: false
securitySchemes:
apiKey:
type: http
scheme: bearer
bearerFormat: hvs_…
description: An account key, created at https://harvis.dev/dashboard/keys and shown once.
session:
type: apiKey
in: cookie
name: better-auth.session_token
description: The dashboard's own sign-in cookie. Listed because the browser calls these same endpoints; a CLI or a server should use apiKey instead.