Categorygithub.com/topi314/gobin
2.1.0
Repository: https://github.com/topi314/gobin.git
Documentation: pkg.go.dev

# README

Go Report Go Version KittyBot License KittyBot Version Server CLI Discord

gobin

gobin is a simple lightweight haste-server alternative written in Go, HTML, JS and CSS. It is aimed to be easy to use and deploy. You can find an instance running at xgob.in.

Table of Contents

Features

  • Easy to deploy and use
  • Built-in rate-limiting
  • Create, update and delete documents
  • Document update/delete webhooks
  • Syntax highlighting
  • Social Media PNG previews
  • Document expiration
  • Supports PostgreSQL or SQLite
  • One binary and config file
  • Docker image available
  • Metrics (to be implemented)
  • base16 & chroma custom themes

Installation

Server

Docker

The easiest way to deploy gobin is using docker with Docker Compose. You can find the docker image on Packages.

Create a new docker-compose.yml file with the following content:

[!Note] You should change the password in the docker-compose.yml and gobin.json file.

version: "3.8"

services:
  gobin:
    image: ghcr.io/topi314/gobin:latest
    container_name: gobin
    restart: unless-stopped
    volumes:
      - ./gobin.json:/var/lib/gobin/gobin.json
      # use this for sqlite
      - ./gobin.db:/var/lib/gobin/gobin.db
    ports:
      - 80:80

  # or use this for postgres
  postgres:
    image: postgres:latest
    container_name: postgres
    restart: unless-stopped
    volumes:
      - ./data:/var/lib/postgresql/data
    environment:
      POSTGRES_DB: gobin
      POSTGRES_USER: gobin
      POSTGRES_PASSWORD: password

For gobin.json/environment variables and database schema see Configuration.

docker-compose up -d

Manual

Requirements
  • Go 1.21 or higher
Build
git clone https://github.com/topi314/gobin.git
cd gobin
go build -o gobin github.com/topi314/gobin/v2

or

go install github.com/topi314/gobin/v2@latest
Run
gobin --config=gobin.json

CLI

Release

You can find the latest release on Releases.

Manual

Requirements
  • Go 1.21 or higher
Build
git clone https://github.com/topi314/gobin.git
cd gobin
go build -o gobin github.com/topi314/gobin/v2/cli

or

go install github.com/topi314/gobin/v2/cli@latest
# rename binary to gobin
mv $(go env GOPATH)/bin/cli $(go env GOPATH)/bin/gobin
# or move binary into /usr/local/bin
mv $(go env GOPATH)/bin/cli /usr/local/bin/gobin
# change file ownership to root 
chown 0:0 /usr/local/bin/gobin
Run
gobin help

Configuration

The database schema is automatically created when you start gobin and there is no documents table in the database.

Create a new gobin.json file with the following content:

[!Note] Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".

{
  "log": {
    // level can be -4 (debug), 0 (info), 4 (warn), 8 (error)
    "level": 0,
    // log format, either "json" or "text"
    "format": "text",
    // whether to add the source file and line to the log output
    "add_source": false,
    // whether to add color to the log output (only for text format)
    "no_color": false
  },
  // enable or disable debug profiler endpoint
  "debug": false,
  // enable or disable hot reload of templates and assets
  "dev_mode": false,
  "listen_addr": "0.0.0.0:80",
  // secret for jwt tokens, replace with a long random string
  "jwt_secret": "...",
  "database": {
    // either "postgres" or "sqlite"
    "type": "postgres",
    "debug": false,
    "expire_after": "168h",
    "cleanup_interval": "10m",
    // path to sqlite database
    // if you run gobin with docker make sure to set it to "/var/lib/gobin/gobin.db"
    "path": "gobin.db",
    // postgres connection settings
    "host": "localhost",
    "port": 5432,
    "username": "gobin",
    "password": "password",
    "database": "gobin",
    "ssl_mode": "disable"
  },
  // max character count for all files in a document combined (0 to disable)
  "max_document_size": 0,
  // max_highlight_size is the max character count for a single file in a document to be highlighted (0 to disable)
  "max_highlight_size": 0,
  // omit or set values to 0 or "0" to disable rate limit
  "rate_limit": {
    // number of requests which can be done in the duration
    "requests": 10,
    // the duration of the requests
    "duration": "1m",
    // a list of ip addresses which are exempt from rate limiting
    "whitelist": [
      "127.0.0.1"
    ],
    // a list of ip addresses which are blocked from rate limited endpoints
    "blacklist": [
      "123.456.789.0"
    ]
  },
  // settings for social media previews, omit to disable
  "preview": {
    // path to inkscape binary https://inkscape.org/
    "inkscape_path": "/usr/bin/inkscape",
    // how many lines should be shown in the preview
    "max_lines": 10,
    // how high the resolution of the preview should be, 96 is the default
    "dpi": 96,
    // how many previews should be maximally cached
    "cache_size": 1024,
    // how long should previews be cached
    "cache_duration": "1h"
  },
  // open telemetry settings, omit to disable
  "otel": {
    // the instance id of the server
    "instance_id": "1",
    // otel trace settings, omit to disable
    "trace": {
      // the address of the tempo instance
      "endpoint": "tempo:4318",
      // whether to use an insecure connection
      "insecure": true
    },
    // otel metrics settings, omit to disable
    "metrics": {
      // the address where the metrics should be exposed
      "listen_addr": ":9100"
    }
  },
  // settings for webhooks, omit to disable
  "webhook": {
    // webhook reqauest timeout
    "timeout": "10s",
    // max number of tries to send a webhook
    "max_tries": 3,
    // how long to wait before retrying a webhook
    "backoff": "1s",
    // how much the backoff should be increased after each retry
    "backoff_factor": 2,
    // max backoff time
    "max_backoff": "5m"
  },
  // load custom chroma xml or base16 yaml themes from this directory, omit to disable
  "custom_styles": "custom_styles",
  "default_style": "snazzy"
}

Alternatively you can use environment variables to configure gobin. The environment variables are prefixed with GOBIN_ and are in uppercase. For example GOBIN_DATABASE_TYPE or GOBIN_RATE_LIMIT_REQUESTS.

Here is a list of all environment variables
GOBIN_LOG_LEVEL=info
GOBIN_LOG_FORMAT=text
GOBIN_LOG_ADD_SOURCE=false

GOBIN_DEBUG=false
GOBIN_DEV_MODE=false
GOBIN_LISTEN_ADDR=0.0.0.0:80
GOBIN_JWT_SECRET=...

GOBIN_DATABASE_TYPE=postgres
GOBIN_DATABASE_DEBUG=false
GOBIN_DATABASE_EXPIRE_AFTER=168h
GOBIN_DATABASE_CLEANUP_INTERVAL=10m

GOBIN_DATABASE_PATH=gobin.db

GOBIN_DATABASE_HOST=localhost
GOBIN_DATABASE_PORT=5432
GOBIN_DATABASE_USERNAME=gobin
GOBIN_DATABASE_PASSWORD=password
GOBIN_DATABASE_DATABASE=gobin
GOBIN_DATABASE_SSL_MODE=disable

GOBIN_MAX_DOCUMENT_SIZE=0
GOBIN_MAX_HIGHLIGHT_SIZE=0

GOBIN_RATE_LIMIT_REQUESTS=10
GOBIN_RATE_LIMIT_DURATION=1m

GOBIN_PREVIEW_INKSCAPE_PATH=/usr/bin/inkscape
GOBIN_PREVIEW_MAX_LINES=10
GOBIN_PREVIEW_DPI=96
GOBIN_PREVIEW_CACHE_SIZE=1024
GOBIN_PREVIEW_CACHE_TTL=1h

GOBIN_WEBHOOK_TIMEOUT=10s
GOBIN_WEBHOOK_MAX_TRIES=3
GOBIN_WEBHOOK_BACKOFF=1s
GOBIN_WEBHOOK_BACKOFF_FACTOR=2
GOBIN_WEBHOOK_MAX_BACKOFF=5m

GOBIN_CUSTOM_STYLES=custom_styles
GOBIN_DEFAULT_STYLE=snazzy

Custom Themes

You can add your own themes to gobin by adding the custom_styles directory to the config file and adding your themes to it.

The themes have to be in the following format:

scheme: "name"
author: "author"
theme: "dark" # or "light"
base00: "282a36"
base01: "34353e"
base02: "43454f"
base03: "78787e"
base04: "a5a5a9"
base05: "e2e4e5"
base06: "eff0eb"
base07: "f1f1f0"
base08: "ff5c57"
base09: "ff9f43"
base0A: "f3f99d"
base0B: "5af78e"
base0C: "9aedfe"
base0D: "57c7ff"
base0E: "ff6ac1"
base0F: "b2643c"

See base16 for more information.

Or you can use the chroma XML themes.

Rate Limits

All POST, PATCH and DELETE endpoints are rate limited. The rate limit can be configured in the config file. The bucket is based on the IP address and the path of the request. So each of these unique combinations has its own bucket/rate limit.

It's based on a sliding window algorithm, but instead of a fixed window the window will start at the first request and end after the duration. So if you set the duration to 1 minute and send 10 requests in the first 10 seconds you will be rate limited for 50 seconds. After that you can send 10 requests again.

Gobin will return these headers to help clients keep track of the rate limit:

HeaderDescription
X-RateLimit-LimitThe maximum number of requests which can be done in the duration.
X-RateLimit-RemainingThe number of remaining requests which can be done in the duration.
X-RateLimit-ResetThe time when the rate limit will be reset in unix timestamp.
Retry-AfterThe time when the rate limit will be reset in seconds. (only when hit a 429)

API

Fields marked with ? are optional and types marked with ? are nullable.

Errors

In case of an error gobin will return the following JSON body with the corresponding HTTP status code:

{
  "message": "document not found",
  // error message
  "status": 404,
  // HTTP status code
  "path": "/documents/7df3vw",
  // request path
  "request_id": "fbe0a365387f/gVAMGuraLW-003490"
  // request id
}

Formatter Enum

Document formatting is done using chroma. The following formatters are available:

ValueDescription
terminal88-bit terminal colors
terminal1616-bit terminal colors
terminal256256-bit terminal colors
terminal16mtrue terminal colors
htmlHTML
html-standaloneStandalone HTML
svgSVG

Language Enum

The following languages are available:

Click to expand
PrefixLanguage
AABAP, ABNF, ActionScript, ActionScript 3, Ada, Angular2, ANTLR, ApacheConf, APL, AppleScript, Arduino, Awk
BBallerina, Bash, Batchfile, BibTeX, Bicep, BlitzBasic, BNF, Brainfuck, BQN
CC, C#, C++, Caddyfile, Caddyfile Directives, Cap'n Proto, Cassandra CQL, Ceylon, CFEngine3, cfstatement, ChaiScript, Chapel, Cheetah, Clojure, CMake, COBOL, CoffeeScript, Common Lisp, Coq, Crystal, CSS, Cython
DD, Dart, Diff, Django/Jinja, Docker, DTD, Dylan
EEBNF, Elixir, Elm, EmacsLisp, Erlang
FFactor, Fish, Forth, Fortran, FSharp
GGAS, GDScript, Genshi, Genshi HTML, Genshi Text, Gherkin, GLSL, Gnuplot, Go, Go HTML Template, Go Text Template, GraphQL, Groff, Groovy
HHandlebars, Haskell, Haxe, HCL, Hexdump, HLB, HLSL, HTML, HTTP, Hy
IIdris, Igor, INI, Io
JJ, Java, JavaScript, JSON, Julia, Jungle
KKotlin
LLighttpd configuration file, LLVM, Lua
MMakefile, Mako, markdown, Mason, Mathematica, Matlab, MiniZinc, MLIR, Modula-2, MonkeyC, MorrowindScript, Myghty, MySQL
NNASM, Newspeak, Nginx configuration file, Nim, Nix
OObjective-C, OCaml, Octave, OnesEnterprise, OpenEdge ABL, OpenSCAD, Org Mode
PPacmanConf, Perl, PHP, PHTML, Pig, PkgConfig, PL/pgSQL, plaintext, Pony, PostgreSQL SQL dialect, PostScript, POVRay, PowerShell, Prolog, PromQL, Properties, Protocol Buffer, PSL, Puppet, Python 2, Python
QQBasic
RR, Racket, Ragel, Raku, react, ReasonML, reg, reStructuredText, Rexx, Ruby, Rust
SSAS, Sass, Scala, Scheme, Scilab, SCSS, Sed, Smalltalk, Smarty, Snobol, Solidity, SPARQL, SQL, SquidConf, Standard ML, stas, Stylus, Svelte, Swift, SYSTEMD, systemverilog
TTableGen, TASM, Tcl, Tcsh, Termcap, Terminfo, Terraform, TeX, Thrift, TOML, TradingView, Transact-SQL, Turing, Turtle, Twig, TypeScript, TypoScript, TypoScriptCssData, TypoScriptHtmlData
VVB.net, verilog, VHDL, VHS, VimL, vue
WWDTE
XXML, Xorg
YYAML, YANG
ZZig

Create a document

You can create a document with a single file or multiple files. When creating a document with a single file you can simply POST the content to /documents. When creating a document with multiple files you have to POST the content to /documents as multipart/form-data. See below for more information.

Single file

To create a document with a single file you have to send a POST request to /documents with the content as body.

HeaderTypeDescription
Content-Disposition?stringThe file name of the document.
Content-Type?stringThe content type of the document.
Language?stringThe language of the document.
Expires?TimestampWhen the document file should expire in RFC 3339 format
Query ParameterTypeDescription
language?languageThe language of the document.
formatter?formatterWith which formatter to render the document.
style?style nameWhich style to use for the formatter
expires?TimestampWhen the document file should expire in RFC 3339 format
Example
package main

func main() {
	println("Hello World!")
}

Multiple files

To create a document with multiple files you have to send a POST request to /documents with the content as multipart/form-data body. Each file has to be in its own part with the name file-{index}. The first file has to be named file-0, the second file-1 and so on.

Query ParameterTypeDescription
formatter?formatterWith which formatter to render the document.
style?style nameWhich style to use for the formatter
expires?TimestampWhen the document file should expire in RFC 3339 format
HeaderTypeDescription
Expires?TimestampWhen the document file should expire in RFC 3339 format
Part HeaderTypeDescription
Content-DispositionstringThe form & file name of the document.
Content-Type?stringThe content type/language of the document.
Language?stringThe language of the document.
Expires?TimestampWhen the document file should expire in RFC 3339 format, overwrites the query param & header
Example
-----------------------------302370379826172687681786440755
Content-Disposition: form-data; name="file-0"; filename="main.go"
Content-Type: text/x-gosrc
Language: Go
Expires: 2023-10-10T10:10:10Z

package main

func main() {
	println("Hello World!")
}
-----------------------------302370379826172687681786440755
Content-Disposition: form-data; name="file-1"; filename="untitled1"
Content-Type: text/plain; charset=utf-8

Hello World!
-----------------------------302370379826172687681786440755--

A successful request will return a 201 Created response with a JSON body containing the document key and token to update the document.

{
  "key": "hocwr6i6",
  "version": 1,
  "files": [
    {
      "name": "main.go",
      "content": "package main\n\nfunc main() {\n    println(\"Hello World!\")\n}",
      // only if formatter is set
      "formatted": "...",
      "language": "Go",
      "expires_at": null
    },
    {
      "name": "untitled1",
      "content": "Hello World!",
      // only if formatter is set
      "formatted": "...",
      "language": "plaintext",
      "expires_at": null
    }
  ],
  "token": "kiczgez33j7qkvqdg9f7ksrd8jk88wba"
}

Get a document (version)

To get a document you have to send a GET request to /documents/{key} or /documents/{key}/versions/{version}.

Query ParameterTypeDescription
formatter?formatterWith which formatter to render the document
style?style nameWhich style to use for the formatter
file?file nameWhich file to return
language?languageIn which language the document should be rendered. Only works in combination with the file param

The response will be a 200 OK with the document content as application/json body.

{
  "key": "hocwr6i6",
  "version": 1,
  "files": [
    {
      "name": "main.go",
      "content": "package main\n\nfunc main() {\n    println(\"Hello World!\")\n}",
      // only if formatter is set
      "formatted": "...",
      "language": "Go",
      "expires_at": null
    },
    {
      "name": "untitled1",
      "content": "Hello World!",
      // only if formatter is set
      "formatted": "...",
      "language": "plaintext",
      "expires_at": null
    }
  ]
}

In case you provide a file query param the response will be like from Get a document file


Get a document (version) file

To get a document (version) file you have to send a GET request to /documents/{key}/files/{fileName}or /documents/{key}/versions/{version}/files/{fileName}

Query ParameterTypeDescription
formatter?formatterWith which formatter to render the document.
style?style nameWhich style to use for the formatter
language?language nameWhich language to use for the formatter

The response will be a 200 OK with the document content as application/json body.

{
  "name": "main.go",
  // only if withContent is set
  "content": "package main\n\nfunc main() {\n    println(\"Hello World!\")\n}",
  // only if formatter is set
  "formatted": "...",
  "language": "Go",
  "expires_at": null
}

Get a documents versions

To get a documents versions you have to send a GET request to /documents/{key}/versions.

Query ParameterTypeDescription
formatter?formatterWith which formatter to render the document
style?style nameWhich style to use for the formatter
withContent?boolIf the content should be included in the response.

The response will be a 200 OK with the document content as application/json body.

[
  {
    "key": "hocwr6i6",
    "version": 2,
    "files": [
      {
        "name": "main.go",
        // only if withContent is set
        "content": "package main\n\nfunc main() {\n    println(\"Hello World!\")\n}",
        // only if formatter is set
        "formatted": "...",
        "language": "Go",
        "expires_at": null
      },
      {
        "name": "untitled1",
        // only if withContent is set
        "content": "Hello World!",
        // only if formatter is set
        "formatted": "...",
        "language": "plaintext",
        "expires_at": null
      }
    ]
  },
  {
    "key": "hocwr6i6",
    "version": 1,
    "files": [
      {
        "name": "main.go",
        "content": "package main\n\nfunc main() {\n    println(\"Hello!\")\n}",
        // only if formatter is set
        "formatted": "...",
        "language": "Go",
        "expires_at": null
      },
      {
        "name": "untitled1",
        "content": "Hello!",
        // only if formatter is set
        "formatted": "...",
        "language": "plaintext",
        "expires_at": null
      }
    ]
  }
]

Update a document

You can update a document with a single file or multiple files. When updating a document with a single file you can simply PATCH the content to /documents/{key}. When updating a document with multiple files you have to PATCH the content to /documents/{key} as multipart/form-data. See below for more information.

Single file

To create a document with a single file you have to send a PATCH request to /documents/{key} with the content as body.

HeaderTypeDescription
Content-DispositionstringThe form & file name of the document.
Content-Type?stringThe content type of the document.
Language?stringThe language of the document.
Authorization?stringThe update token of the document. (prefix with Bearer )
Expires?TimestampWhen the document file should expire in RFC 3339 format
Query ParameterTypeDescription
language?languageThe language of the document.
formatter?formatterWith which formatter to render the document.
style?style nameWhich style to use for the formatter
expires?TimestampWhen the document file should expire in RFC 3339 format
Example
package main

func main() {
	println("Hello World Updated!")
}

Multiple files

To update a document with multiple files you have to send a PATCH request to /documents/{key} with the content as multipart/form-data body. Each file has to be in its own part with the name file-{index}. The first file has to be named file-0, the second file-1 and so on.

HeaderTypeDescription
Authorization?stringThe update token of the document. (prefix with Bearer )
Expires?TimestampWhen the document file should expire in RFC 3339 format
Query ParameterTypeDescription
formatter?formatterWith which formatter to render the document.
style?style nameWhich style to use for the formatter
expires?TimestampWhen the document file should expire in RFC 3339 format
Part HeaderTypeDescription
Content-DispositionstringThe form & file name of the document.
Content-Type?stringThe content type of the document.
Language?stringThe language of the document.
Expires?TimestampWhen the document file should expire in RFC 3339 format, overwrites the query param & header
Example
Authorization: kiczgez33j7qkvqdg9f7ksrd8jk88wba
-----------------------------302370379826172687681786440755
Content-Disposition: form-data; name="file-0"; filename="main.go"
Content-Type: text/x-gosrc
Language: Go
Expires: 2023-10-10T10:10:10Z

package main

func main() {
	println("Hello World!")
}
-----------------------------302370379826172687681786440755
Content-Disposition: form-data; name="file-1"; filename="untitled1"
Content-Type: text/plain; charset=utf-8

Hello World!
-----------------------------302370379826172687681786440755--

A successful request will return a 201 Created response with a JSON body containing the document key and token to update the document.

[!Note] The update token will not change after updating the document. You can use the same token to update the document again.

{
  "key": "hocwr6i6",
  "version": 2,
  "files": [
    {
      "name": "main.go",
      "content": "package main\n\nfunc main() {\n    println(\"Hello World Updated!\")\n}",
      // only if formatter is set
      "formatted": "...",
      "language": "Go",
      "expires_at": null
    },
    {
      "name": "untitled1",
      "content": "Hello World Updated!",
      // only if formatter is set
      "formatted": "...",
      "language": "plaintext",
      "expires_at": null
    }
  ],
  "token": "kiczgez33j7qkvqdg9f7ksrd8jk88wba"
}

Delete a document (version)

To delete a document you have to send a DELETE request to /documents/{key} or /documents/{key}/versions/{version} with the token as Authorization header.

HeaderTypeDescription
Authorization?stringThe update token of the document. (prefix with Bearer )

A successful request will return a 204 No Content response with an empty body or a 200 OK with a JSON body containing the count of remaining document versions:

{
  "versions": 1
}

Share a document

To share a document you have to send a POST request to /documents/{key}/share.

HeaderTypeDescription
Authorization?stringThe update token of the document. (prefix with Bearer )
{
  "permissions": [
    "write",
    "delete",
    "share"
  ]
}

A successful request will return a 200 OK response with a JSON body containing the share token. You can append the token to URLs like this: https://xgob.in/{key}?token={token} to make the frontend auto import the token for editing/deleting/sharing the document.

{
  "token": "kiczgez33j7qkvqdg9f7ksrd8jk88wba"
}

Document webhooks

You can listen for document changes using webhooks. The webhook will send a POST request to the specified url with the following JSON body:

{
  // the id of the webhook
  "webhook_id": "hocwr6i6",
  // the event which triggered the webhook (update or delete)
  "event": "update",
  // when the event was created
  "created_at": "2021-08-01T12:00:00Z",
  // the updated or deleted document
  "document": {
    // the key of the document
    "key": "hocwr6i6",
    // the version of the document
    "version": 2,
    // the files of the document
    "files": [
      {
        "name": "main.go",
        "content": "package main\n\nfunc main() {\n    println(\"Hello World Updated!\")\n}",
        "language": "Go",
        "expires_at": null
      }
    ]
  }
}

Gobin will include the webhook secret in the Authorization header in the following format: Secret {secret}.

When sending an event to a webhook fails gobin will retry it up to x times with an exponential backoff. The retry settings can be configured in the config file. When an event fails to be sent after x retries, the webhook will be dropped.

[!Important] Authorizing for the following webhook endpoints is done using the Authorization header in the following format: Secret {secret}.

Create a document webhook

To create a webhook you have to send a POST request to /documents/{key}/webhooks with the following JSON body:

{
  // the url to send a request to
  "url": "https://example.com/webhook",
  // the secret to include in the request
  "secret": "secret",
  // the events you want to receive
  "events": [
    // update event is sent when a document is updated. This includes content and language changes
    "update",
    // delete event is sent when a document is deleted
    "delete"
  ]
}

A successful request will return a 200 OK response with a JSON body containing the webhook.

{
  // the id of the webhook
  "id": 1,
  // the url to send a request to
  "url": "https://example.com/webhook",
  // the secret to include in the request
  "secret": "secret",
  // the events you want to receive
  "events": [
    // update event is sent when a document is updated. This includes content and language changes
    "update",
    // delete event is sent when a document is deleted
    "delete"
  ]
}

Get a document webhook

To get a webhook you have to send a GET request to /documents/{key}/webhooks/{id} with the Authorization header.

A successful request will return a 200 OK response with a JSON body containing the webhook.

{
  // the id of the webhook
  "id": 1,
  // the url to send a request to
  "url": "https://example.com/webhook",
  // the secret to include in the request
  "secret": "secret",
  // the events you want to receive
  "events": [
    // update event is sent when a document is updated. This includes content and language changes
    "update",
    // delete event is sent when a document is deleted
    "delete"
  ]
}

Update a document webhook

To update a webhook you have to send a PATCH request to /documents/{key}/webhooks/{id} with the Authorization header and the following JSON body:

[!Note] All fields are optional, but at least one field is required.

{
  // the url to send a request to
  "url": "https://example.com/webhook",
  // the secret to include in the request
  "secret": "secret",
  // the events you want to receive
  "events": [
    // update event is sent when a document is updated. This includes content and language changes
    "update",
    // delete event is sent when a document is deleted
    "delete"
  ]
}

A successful request will return a 200 OK response with a JSON body containing the webhook.

{
  // the id of the webhook
  "id": 1,
  // the url to send a request to
  "url": "https://example.com/webhook",
  // the secret to include in the request
  "secret": "secret",
  // the events you want to receive
  "events": [
    // update event is sent when a document is updated. This includes content and language changes
    "update",
    // delete event is sent when a document is deleted
    "delete"
  ]
}

Delete a document webhook

To delete a webhook you have to send a DELETE request to /documents/{key}/webhooks/{id} with the Authorization header.

A successful request will return a 204 No Content response with an empty body.


Other endpoints

  • GET/HEAD /{key}/files/{filename} - Get the content of a file in a document, query parameters are the same as for GET /documents/{key}.
  • GET/HEAD /{key}/versions/{version}/files/{filename} - Get the content of a file in a document with a specific version, query parameters are the same as for GET /documents/{key}.
  • GET/HEAD /assets/theme.css?style={style} - Get the css of a style, this is used for the syntax highlighting in the frontend.
  • GET/HEAD /{key}/preview - Get the preview of a document, query parameters are the same as for GET /documents/{key}.
  • GET/HEAD /{key}/{version}/preview - Get the preview of a document version, query parameters are the same as for GET /documents/{key}/versions/{version}.
  • GET/HEAD /raw/{key} - Get the raw content of a document, query parameters are the same as for GET /documents/{key}.
  • GET/HEAD /raw/{key}/files/{filename} - Get the raw content of a document file, query parameters are the same as for GET /documents/{key}.
  • GET/HEAD /raw/{key}/versions/{version} - Get the raw content of a document version, query parameters are the same as for GET /documents/{key}/versions/{version}.
  • GET/HEAD /raw/{key}/versions/{version}/files/{filename} - Get the raw content of a document version file, query parameters are the same as for GET /documents/{key}/versions/{version}.
  • GET /ping - Get the status of the server.
  • GET /debug - Proof debug endpoint (only available in debug mode).
  • GET /version - Get the version of the server.

License

gobin is licensed under the Apache License 2.0.


Contributing

Contributions are always welcome! Just open a pull request or discussion and I will take a look at it.


Credits


Contact

# Packages

No description provided by the author