API
Deploy from CI or a script. Pages, domains and forms over HTTPS, with a token instead of a login.
Tokens
Create a token from the API tokens section of your account page. It is shown once, right after you create it — store it as a secret in your CI, and if you lose it, revoke it and make another.
A token acts as your account for pages, domains and forms. It cannot log in, create more tokens or change two-factor; those stay in the dashboard. The account page shows when each token was last used, so a stale one is easy to spot and revoke.
Send it as a bearer token to https://api.majinode.com:
curl -H "Authorization: Bearer $MAJINODE_TOKEN" https://api.majinode.com/auth/me Deploy a Page
Create the page once, from the dashboard or with the API:
curl -H "Authorization: Bearer $MAJINODE_TOKEN" -H "Content-Type: application/json" -d '{"name":"my-site"}' https://api.majinode.com/pages Then upload a .zip, .tar or .tar.gz of your build output. Each upload
replaces everything the page served before. If the archive wraps everything in
one top-level directory, its contents are served from the root. Archives over
64 MiB are rejected with a 413.
Upload a build
zip -r dist.zip dist && curl --fail-with-body -H "Authorization: Bearer $MAJINODE_TOKEN" -F file=@dist.zip https://api.majinode.com/pages/my-site/upload --fail-with-body makes curl exit non-zero on an error, so a failed deploy
fails the job rather than passing silently.
GitHub Actions
Add the token as a repository secret named MAJINODE_TOKEN, then deploy after
your build step:
- name: Deploy to majinode
run: |
zip -r dist.zip dist
curl --fail-with-body \
-H "Authorization: Bearer ${{ secrets.MAJINODE_TOKEN }}" \
-F file=@dist.zip \
https://api.majinode.com/pages/my-site/upload
Endpoints
Requests and responses are JSON, except the upload, which takes a multipart
file. Errors come back with a detail explaining what went wrong.
| Method | Path | What it does |
|---|---|---|
GET | /auth/me | The account the token belongs to |
GET | /pages | List your pages |
POST | /pages | Create a page: {"name": "my-site"} |
GET | /pages/{name} | Page detail, including its files |
POST | /pages/{name}/upload | Replace the page’s files with an archive |
GET | /pages/{name}/logs | Recent requests to the page |
DELETE | /pages/{name} | Delete the page, its files and its domains |
GET | /pages/{name}/domains | List custom domains |
POST | /pages/{name}/domains | Claim a domain: {"domain": "mysite.com"} |
POST | /pages/{name}/domains/{domain}/verify | Check the TXT record and go live |
DELETE | /pages/{name}/domains/{domain} | Remove a domain |
GET | /forms | List your forms |
POST | /forms | Create a form: {"name": "Contact", "notify": true} |
GET | /forms/{id}/submissions | Newest first, ?limit= (up to 100) and &offset= |
DELETE | /forms/{id} | Delete a form and its submissions |