Skip to main content

API reference

Quickstart: Go

Drive the Jobby.dev API from Go using net/http directly — there's no first-party Go SDK yet, but the surface is small enough that you don't need one.

Last updated

There's no first-party Go SDK yet — but the v1 surface is small enough that you don't need one. net/http + the standard library is enough. If you want a generated client, point oapi-codegen at /api/v1/openapi.json.

Minimal client

package jobbydev

import (
    "bytes"
    "encoding/json"
    "fmt"
    "io"
    "net/http"
    "time"
)

type Client struct {
    BaseURL  string
    APIToken string
    HTTP     *http.Client
}

func NewClient(token string) *Client {
    return &Client{
        BaseURL:  "https://jobby.dev/api/v1",
        APIToken: token,
        HTTP:     &http.Client{Timeout: 30 * time.Second},
    }
}

type APIError struct {
    Status  int
    Code    string
    Message string
    Details json.RawMessage
}

func (e *APIError) Error() string {
    return fmt.Sprintf("jobbydev: %d %s: %s", e.Status, e.Code, e.Message)
}

func (c *Client) Do(method, path string, body any, out any) error {
    var buf io.Reader
    if body != nil {
        b, err := json.Marshal(body)
        if err != nil {
            return err
        }
        buf = bytes.NewReader(b)
    }

    req, err := http.NewRequest(method, c.BaseURL+path, buf)
    if err != nil {
        return err
    }
    req.Header.Set("Authorization", "Bearer "+c.APIToken)
    req.Header.Set("Accept", "application/json")
    if body != nil {
        req.Header.Set("Content-Type", "application/json")
    }

    resp, err := c.HTTP.Do(req)
    if err != nil {
        return err
    }
    defer resp.Body.Close()

    raw, _ := io.ReadAll(resp.Body)
    if resp.StatusCode >= 400 {
        var envelope struct {
            Error   string          `json:"error"`
            Code    string          `json:"code"`
            Details json.RawMessage `json:"details"`
        }
        _ = json.Unmarshal(raw, &envelope)
        return &APIError{
            Status:  resp.StatusCode,
            Code:    envelope.Code,
            Message: envelope.Error,
            Details: envelope.Details,
        }
    }
    if out != nil && len(raw) > 0 {
        return json.Unmarshal(raw, out)
    }
    return nil
}

Usage

package main

import (
    "fmt"
    "log"
    "os"
    "errors"

    "yourapp/internal/jobbydev"
)

func main() {
    client := jobbydev.NewClient(os.Getenv("JOBBYDEV_API_TOKEN"))

    var events struct {
        Data []map[string]any `json:"data"`
    }
    if err := client.Do("GET", "/live-events?limit=5", nil, &events); err != nil {
        var apiErr *jobbydev.APIError
        if errors.As(err, &apiErr) && apiErr.Status == 429 {
            log.Fatalf("rate limited; retry after Retry-After")
        }
        log.Fatal(err)
    }
    fmt.Printf("%d live events\n", len(events.Data))
}

Rate-limit awareness

Read X-RateLimit-Remaining and X-RateLimit-Reset from resp.Header before discarding the response. On 429, parse Retry-Afterand sleep before retrying. The minimal client above doesn't do this automatically — production code should add it.

Code generation

For a fully-typed client across all 35 endpoints, run oapi-codegen:

go install github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen@latest

curl -o openapi.json https://jobby.dev/api/v1/openapi.json
oapi-codegen -package jobbydev openapi.json > jobbydev_gen.go

That gives you typed request / response structs for every endpoint in the spec. Combine with the minimal auth wrapper above for a complete client.

Related reading