Add a backend
Scaffold the outbox table, describe your routes in OpenAPI, and call them with a typed db.run().
- Describe your routes in OpenAPI
Sp00ky derives the callable routes and their payload types from an OpenAPI spec. Each
pathbecomes a route you can pass todb.run(), and the request body schema becomes its argument type.api/openapi.yml - Register the backend
spky api addwrites thesp00ky.ymlentry and generates the outbox table schema for you.Run it without flags for an interactive prompt. The resulting config looks like this:
sp00ky.ymlField Meaning typebackendfor an outbox-invoked HTTP service.specPath to the OpenAPI file. Required. It’s where routes and types come from. baseUrlWhere the job runner sends requests. Use host.docker.internalto reach a service on your host from the containerised stack.method.typeoutbox. The only supported trigger today.method.tableName of the outbox table in SurrealDB. method.schemaPath where the generated table definition is written. Note Validate the file at any point withspky lint. - Review the generated outbox table
spky api addwrites aDEFINE TABLEwith every field the job runner needs. You don’t have to import it anywhere: the CLI appendsmethod.schemato your schema automatically whenever it builds, so migrations and codegen pick it up.schema/src/outbox/api.surqlField Written by Purpose path,payloadclient Which route to call, and with what. statusrunner pending → processing → success | failed.resultrunner Your backend’s response body. errorsrunner One { code, reason }entry per failed attempt.retries,max_retries,retry_strategymixed Attempt budget; linearorexponential.delayclient One-shot delay in ms before the job becomes due. assigneeplatform Which SSP instance claimed the row. Don't loosen the write permissionsClient code may create rows and read them back, but
status,result,errorsandassigneeareFOR update WHERE false. The job runner is the single writer of job status. Making these client-writable lets a browser lie about whether work succeeded. - Regenerate types
Backend names and route paths are now part of your generated schema, so
db.run()autocompletes them and typechecks the payload. - Call it
db.run()resolves once the job row is written, not when your backend replies. Watch the row to follow the actual work. See Jobs.
Implementing the route
Your service is an ordinary HTTP server. The job runner POSTs the payload to baseUrl + path and
stores whatever JSON you return in the row’s result field.
A non-2xx response marks the attempt failed and schedules a retry according to the row’s
max_retries and retry_strategy. Return quickly, or raise the
timeout.
Running it locally
Add a dev block and spky dev starts your backend alongside SurrealDB and the SSP. See
Dev servers & sidecars.