API reference

One endpoint turns a name into a signature image drawn by our own model. Send JSON with your API key, get the image back in the response body, with its metadata in X-Signature-* headers.

Quickstart

  1. Create a key

    Open your Account and create a key. It is shown once; keep it on your server, never in a browser or a mobile app.

  2. Authenticate

    Send the key with every request as Authorization: Bearer hs_live_… or X-API-Key.

  3. Generate a signature

    POST /v1/signatures returns the image directly in the response body.

    curl https://handsign.app/v1/signatures \
      -H "Authorization: Bearer $HANDSIGN_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "name": "Jordan Hayes",
        "style": "flourish",
        "size": "L",
        "color": "navy",
        "background": "transparent",
        "format": "png"
      }' \
      -o signature.png

Parameters

JSON body of POST /v1/signatures. Only name is required.

Text

name required

1 to 80 characters. Accents are normalized.

Signature

style default random

Overall gesture: natural is plain cursive, elegant is thin with long loops, flourish adds a sweeping underline, scrawl is fast with a strike-through and a paraph. Not needed with hand: the hand sets the style, and a different style returns 422.

randomnaturalelegantflourishscrawl
hand default derived from the name

Which real signature lends its hand. Every hand comes from a real signature; the name is written in that hand. Left empty, the hand is derived from the name, so the same name always gets the same hand in a given style. Pass an id from GET /v1/hands to choose one, without style; the seed then only changes the take. Ink weight comes from the hand. Choosing a hand is available from the Starter plan.

Ink

color name or hex

Ink color: a name or #RRGGBB.

blackbluenavyroyalredgreengray

Output

format default png

Image format of the response body. SVG is available from the Starter plan; PNG on the Free plan carries a light watermark.

pngsvg
size default M

Image width: S 128 px, M 256 px, L 512 px or XL 768 px. Height follows the signature. For high-density screens, request the next size up and display it at half width, or use SVG.

SMLXL
background default transparent

Image background.

transparentwhite
seed 0 to 2147483647

The same seed and parameters always give the same signature. With a fixed hand, changing the seed gives another take in the same hand.

Response

A successful call returns 200 with the image as the body and its Content-Type set to the requested format. Metadata comes in headers.

Response headers 10
X-Signature-Seed
Seed used, to reproduce the signature
X-Signature-Style
Style used
X-Signature-Text
Text written
X-Signature-Size
Size used
X-Signature-Width
Image width in pixels
X-Signature-Height
Image height in pixels
X-Signature-Realism
Resemblance of the returned take to real signatures, 0 to 1
X-Signature-Hand
Id of the hand used, to reuse it with the hand parameter
X-Signature-Elapsed-Ms
Generation time in milliseconds
X-Signature-Cache
Present with the value hit when the same request was served again within 24 hours

Quality

Signatures are drawn by our own image model, trained on real handwritten signatures. The hand comes from a real signature, the name is written in that hand. The model sees that signature cut into shuffled strips, so it takes the stroke without the letters. Each request writes the name in that hand several times and returns the take closest to the hand, with its resemblance to real signatures in X-Signature-Realism. Paid plans write three takes, the Free plan two. The same name always gets the same hand, so your users keep one signature across documents; a hand is never lent for the name of the person it belongs to. Identical requests are served from a 24 hour cache.

Like any generative model it can misspell a letter or leave a small artefact. When it matters, retry with another seed, or call the batch endpoint and keep the best take. We are improving these details with every version.

Endpoints

POST /v1/signatures/batch

Same body plus count (1 to 16). Returns JSON with base64 images. Starter plan and above.

GET /v1/styles

Every accepted value, as JSON. No key needed.

GET /v1/hands

Catalogue of hands as JSON, with id and style. Filter with ?style=. No key needed.

GET /v1/plans

Plans and quotas, as JSON. No key needed.

GET /health

Service status.

Errors

Error bodies are JSON shaped as {"detail": "…"}.

401 Unauthorized

Missing, invalid or revoked API key.

403 Forbidden

Not available on your plan (batch, hand choice, SVG), or key limit reached.

422 Invalid parameters

A parameter is missing or outside its accepted values.

429 Too many requests

Monthly quota reached (resets on the 1st at 00:00 UTC), or rate limit exceeded: 10 signatures a minute on Free, 60 on paid plans. Rate limited responses carry a Retry-After header in seconds.

503 Unavailable

Generator temporarily unavailable, retry shortly.

Privacy

Names travel only in request bodies, never in URLs, so they do not end up in access logs. Nothing you send is stored; see the Terms