Help us shape the future of Go! Take the 2026 Go Developer Survey

kavel

package module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 13, 2026 License: MIT Imports: 11 Imported by: 0

README

kavel-go

Generate and edit images from Go with no API key, no account and no card.

go get github.com/hanshs474/kavel-go
img, err := kavel.Generate(context.Background(),
    "matte black ceramic mug on pale oak, soft window light from the left, shallow depth of field",
    kavel.Options{AspectRatio: "16:9"})
// img.URL         https://cdn.kavel.ai/uploads/kie/image/....webp
// img.Watermarked true on the free tier
img, err := kavel.Edit(context.Background(), sourceURL,
    "place the mug on a white marble surface with a sprig of rosemary beside it",
    kavel.Options{})

Or without writing any code:

go run github.com/hanshs474/kavel-go/example@latest "an isometric coffee shop, pastel palette"
go run github.com/hanshs474/kavel-go/example@latest -edit https://example.com/portrait.jpg "give him a buzz cut"

Every other image client wants a key from OpenAI, fal or Replicate before it runs once. This one talks to the anonymous tier of Kavel — a client id the package invents rather than an account you register — so it works on a machine with nothing configured.

What you get

  • An edit lane, not just generation. Most no-key clients can only make a new picture. Edit takes a photo you already have and a sentence describing the change.
  • Zero dependencies. Standard library only, so there is nothing to pin and nothing that can drift out from under you.
  • A url, not bytes. The returned CDN link is permanent and cacheable, and Watermarked says whether a mark was actually drawn rather than leaving you to assume.
  • Errors you can branch on. ErrQuota, ErrRejected and ErrSignIn are sentinel errors; errors.Is tells you whether to wait, to reword, or to sign in.
  • It keeps polling through a dropped connection. A free run sits in a queue and is only sent to the model at the end of it, so abandoning the wait on one failed poll would throw away a job that was about to run.

Limits, read out of the running service

Measured 2026-09-07 by calling it, not estimated:

  • The anonymous grant is 15 credits. One generated image costs 5, so a fresh client id buys three; the package mints one per call, so a loop is not capped at three.
  • One edit costs 15 — the whole grant, so a client id buys exactly one edit.
  • A ceiling of 30 credits per IP per day sits on top: about six images, or two edits, from one machine. That surfaces as ErrQuota.
  • Free output is 1K and watermarked.
  • Free runs wait 25–80 seconds in a queue before the model is called at all. That is why the default deadline is six minutes and why polling is not optional.
  • 🔴 Video cannot run anonymously. The cheapest clip costs more than the grant can pay at any setting, so this package does not pretend to offer one — it returns ErrSignIn. The video generator has a free browser lane instead.

Signing in removes the watermark, lifts the ceiling and opens the rest of the shelf: Nano Banana 2 for generating or editing from up to 14 reference photos, GPT Image 2 for 1K–4K output, Qwen Image 3 when the picture has to contain writing that is spelled correctly, and Seedream 5.0 Pro for photoreal people and motion. Pricing lists what each tier costs.

Past the free tier: an API key

When the free allowance runs out, the error tells you where to go next. Create a key at kavel.ai/settings/apikeys — the same account you use on the site — and pass it (or set KAVEL_API_KEY):

img, err := kavel.Generate(ctx, prompt, kavel.Options{APIKey: os.Getenv("KAVEL_API_KEY"), Model: "gpt-image-2"})

With a key every call runs on your account, exactly as it would on the site: your credits and plan, no per-IP ceiling, no watermark on a paid plan, and any image model your plan includes. errors.Is(err, kavel.ErrAuth) means the key is wrong; ErrQuota with a key means the account is out of credits.

Writing prompts that work

Name the light, the material and the composition. "A product photo of a mug" gives the model nothing; "matte black ceramic mug on pale oak, soft window light from the left, shallow depth of field" gives it a picture. Finished output is in the showcase, and the blog works through longer examples.

For edits, say what changes and leave the rest alone — the model keeps the source framing. The same lane backs the hairstyle changer and the product photo editor on the site, and it is Nano Banana 2 Lite underneath.

The same engines back the free AI image generator and the ChatGPT image generator in a browser.

Testing

go test ./...

The tests do not hit the network. They cover argument validation, per-call client id uniqueness, the quota wall (which answers HTTP 200 and can only be recognised by a field), the sign-in refusal, deadline propagation, and that a dropped poll does not abandon a running job.

MIT.

Documentation

Overview

Package kavel generates and edits images from Go with no API key and no account.

It calls the anonymous tier of kavel.ai, which meters its free allowance against a client id this package invents rather than an account you register, so a program using it works on a machine with nothing configured.

img, err := kavel.Generate(context.Background(), "a paper boat at sunrise", kavel.Options{AspectRatio: "16:9"})

Measured against the running service on 2026-09-07: a signed-out caller is granted 15 credits, one generated image costs 5 and one edit costs 15, so the package mints a fresh client id per call and neither lane is limited to a single run. A ceiling of 30 credits per IP per day sits above that. Free output is 1K and watermarked.

Index

Constants

View Source
const (
	// AnonGrant is the credit balance a signed-out caller starts with.
	AnonGrant = 15
	// CostTextToImage is what one generated image costs, so the grant pays for three.
	CostTextToImage = 5
	// CostEdit is what one edit costs: exactly the grant, so one edit per client id.
	CostEdit = 15
	// IPDailyCeiling caps one machine per day regardless of how many client ids it mints.
	IPDailyCeiling = 30
)

Free-tier facts, read out of the running service rather than estimated.

View Source
const (
	// ModelGenerate is the free text-to-image engine. It takes no image input.
	ModelGenerate = "kavel-image-v1"
	// ModelEdit is the free image-to-image engine. It requires a source image.
	ModelEdit = "nano-banana-2-lite"
)

Models reachable without an account. Anything else needs a signed-in session and returns ErrSignIn.

Variables

View Source
var BaseURL = "https://www.kavel.ai"

BaseURL is the service this package talks to. It is a variable so a test or a corporate proxy can point the package somewhere else.

View Source
var ErrAuth = errors.New("kavel: invalid API key")

ErrAuth is returned when the API key is invalid or has been deleted.

View Source
var ErrQuota = errors.New("kavel: allowance spent (create an API key at https://www.kavel.ai/settings/apikeys to keep going)")

ErrQuota is returned when the free allowance is spent, either for this client id or for this machine's daily ceiling. Signing in at https://www.kavel.ai lifts the ceiling and removes the watermark.

View Source
var ErrRejected = errors.New("kavel: prompt refused")

ErrRejected is returned when the content filter refuses a prompt, or when the model fails on it. Rewording clears it; retrying the same text does not.

View Source
var ErrSignIn = errors.New("kavel: this needs a signed-in account")

ErrSignIn is returned when the request asks for something the anonymous tier does not serve — a model off the free shelf, or video, which costs more than the grant can pay at any setting.

Functions

func Credits

func Credits(ctx context.Context, clientID string, httpClient *http.Client) (remaining, grant int, err error)

Credits reports what the current machine and a given client id have left. It is the same read the site's own header does, and it costs nothing to call.

Pass an empty clientID to ask about a fresh identity, which is what Generate and Edit each mint per call.

Types

type Image

type Image struct {
	// URL is a permanent, cacheable CDN link.
	URL string
	// Watermarked reports whether a mark was actually drawn on it. Signing in
	// removes it; the field is here so a caller can tell rather than assume.
	Watermarked bool
}

Image is one finished picture.

func Edit

func Edit(ctx context.Context, sourceURL, instruction string, opts Options) (Image, error)

Edit rewrites an existing image. sourceURL must be a publicly reachable http(s) url and instruction says what to change ("give him a buzz cut", "put the product on a marble surface").

One edit costs the whole anonymous grant, so a fresh client id buys exactly one. This is the lane behind the hairstyle, outfit and product-photo tools on the site.

func Generate

func Generate(ctx context.Context, prompt string, opts Options) (Image, error)

Generate turns prompt into a new image and returns it.

Naming the light, the material and the composition moves the result far more than adding adjectives: "a product photo of a mug" gives the model nothing, "matte black ceramic mug on pale oak, soft window light from the left, shallow depth of field" gives it a picture.

type Options

type Options struct {
	// AspectRatio is one of "1:1", "16:9", "9:16", "4:3", "3:4". Empty means
	// "1:1". Ignored by Edit, which keeps the source framing.
	AspectRatio string
	// PollEvery is how often the job is polled. Zero means five seconds.
	PollEvery time.Duration
	// Timeout bounds the whole call. Zero means six minutes.
	Timeout time.Duration
	// HTTPClient is used for every request. Nil means http.DefaultClient.
	HTTPClient *http.Client
	// APIKey is a key from https://www.kavel.ai/settings/apikeys. With a key the
	// call runs on your account: your credits, your plan's models, and no
	// watermark on a paid plan. Empty means the KAVEL_API_KEY environment
	// variable, and if that is unset too, the free anonymous tier.
	APIKey string
	// Model overrides the engine. Only honoured with an API key; the free tier
	// has one model per lane.
	Model string
}

Options tunes a single call. The zero value is valid and means a square image with a six minute deadline.

Directories

Path Synopsis
Command example prints the url of an image generated by kavel.ai, with no key and no account.
Command example prints the url of an image generated by kavel.ai, with no key and no account.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL