Skip to content
velt

The API

Twelve routes and one header

Everything a key can do, on one page. If you are here to be told when something happens rather than to ask, webhooks are the other half and are usually what people actually want.

Authenticating

A bearer token, and nothing else. Keys are made on your files, where you also choose what each one may do.

curl https://velt.lol/api/v1/me \
  -H "Authorization: Bearer vk_live_…"

A key carries scopes, and a request outside them is a 403 rather than a quiet no-op. That is the point of them: a capture tool’s config file sitting on a shared machine should not be able to delete your short links.

The routes

  • GET/api/v1/meread

    Who the key belongs to, and what it may do.

  • GET/api/v1/uploadsread

    Your files, newest first.

  • GET/api/v1/uploads/:slugread

    One file.

  • DELETE/api/v1/uploads/:slugdelete

    Remove a file.

  • POST/api/v1/uploadupload

    Send a file. Multipart, and what the capture tools use.

  • GET/api/v1/linksread

    Your short links.

  • POST/api/v1/linksshorten

    Shorten one. Screened exactly as the form screens it.

  • DELETE/api/v1/links/:slugshorten

    Remove a short link.

  • GET/api/v1/pastesread

    Your pastes.

  • POST/api/v1/pastespaste

    Publish one.

  • DELETE/api/v1/pastes/:slugpaste

    Remove a paste.

  • GET/api/v1/statsread

    Your numbers, and the daily series behind them.

Two examples

Shortening a link:

curl -X POST https://velt.lol/api/v1/links \
  -H "Authorization: Bearer vk_live_…" \
  -H "Content-Type: application/json" \
  -d '{"target":"https://example.com/a/long/address","slug":"docs"}'

{
  "slug": "docs",
  "url": "https://velt.lol/s/docs",
  "target": "https://example.com/a/long/address",
  "safety": "clean"
}

A shell alias that pastes whatever you pipe into it:

velt() {
  jq -Rs --arg t "${1:-untitled}" '{content: ., title: $t}' \
  | curl -sS -X POST https://velt.lol/api/v1/pastes \
      -H "Authorization: Bearer $VELT_KEY" \
      -H "Content-Type: application/json" -d @- \
  | jq -r .url
}

$ cat crash.log | velt "the crash"
https://velt.lol/p/k3f9ptq

When something is wrong

Every failure is JSON with a code that is safe to switch on. The message beside it is for a person reading a log and may be reworded; the code will not be.

{ "error": { "code": "forbidden_scope", "message": "That key does not carry …" } }
401 no_key
No Authorization header.
401 bad_key
Not a key, revoked, or expired. The three are one answer on purpose.
403 forbidden_scope
A real key, without the scope this route needs.
404 not_found
No such thing — or it is somebody else’s, which is the same answer.
409 preserved
A reported file, frozen until it has been looked at. Not deletable by anybody.
422 blocked_target
A link we followed and will not forward people to.
429 rate_limited
Per key, not per address. Retry-After says how long.

Two things worth knowing

  • A 404 for somebody else’s thing. Asking for a slug that exists but is not yours answers exactly as if it did not exist. Anything else is a way to find out what other people have.
  • The view count is the same number the page shows, and there is no other one. No raw request total to fall back on — a second, larger, better-looking number is how the honest one stops being the one anybody quotes. How velt counts.