One webhook schema. Six SDKs that never drift.
Hand-maintained clients drift the week you ship. Generate all six from one schema file, and let CI fail the pull request that forgets one.

You declare an order.created event once, and ship. A quarter later the TypeScript client carries a currency field,
the Python one still doesn't, and the docs your customers integrate against describe a third shape. Nobody wrote
bad code. Everybody edited their own copy of the same contract.
A contract lives in four places at once: the publisher's types, every consumer SDK, the bytes on the wire, and the docs page a customer reads before writing their handler. Change a field and you owe all four an edit, by hand. Miss one and nothing breaks loudly, which is why you hear about it from a customer. More discipline won't fix that. Removing the copies will.
One file, six clients#
The schema is small enough to learn in a sitting. A
model describes a payload, a type names your events, an event ties the
two together, and a generator picks a language to emit.
generator api {
language = "typescript"
}
generator payments {
language = "go"
output = "../services/payments/internal/repostclient"
}
type Order {
/// An order was created
created
}
model Order {
id String
amount Float
}
event OrderCreated {
type @type(Order.created)
data Order
timestamp DateTime
}repost schema generate runs every generator, and the write is all-or-nothing:
if one output fails, the ones already written roll back. Two services can't
come out of the same run on different versions of the schema.
Each language gets a native client: typed models, one method
per event type, and a compile error the moment you misspell a field or pass a
string where the schema says Float.
Every client reads the same declarations, so fields come out in the same order everywhere. Six languages, one set of bytes. Which matters more than it sounds: a signature covers bytes, not intentions.
No SDK for your language? The HTTP endpoint underneath all six is one POST. And tell us which one is missing: [email protected]. Adding a language is our favorite kind of feature request.
Your customers read generated pages too#
The /// comment above an event member is not decoration. It becomes the
generated method's documentation, the event's description in your environment,
and the text on your public event docs, which Repost
rebuilds on every deploy.
So the page your customers integrate against cannot fall behind the payload. Nobody writes it, so nobody forgets it.
Let CI do the remembering#
--check recomputes every generator's output and exits non-zero on drift,
listing the changed and stale files per output
(all the flags). Put it in your pull request job
next to repost schema migrate status.
Committed clients then land in git diff beside the migration that caused
them, so a reviewer sees the contract change and its blast radius on one
screen.
Anything you can hand-edit will drift. So don't hand-edit the client. Edit the schema, and let CI diff the rest.