Writing APIs & Events
In Godspeed, every API is defined as an event, and handled by a corresponding function. This unified event-driven structure works for both REST and non-REST event sources (HTTP, WebSocket, Kafka, etc.).
This guide explains how to write new APIs in three clear steps:
Step 1: Setup an Event Sourceโ
An event source is a mechanism that listens for incoming requests or events. Godspeed supports HTTP (via Express), GraphQL, Fastify, Cron and Kafka.
๐น By Default: HTTP via Expressโ
When you create a new project with:
godspeed create my-project
It comes pre-configured with Express as the default event source.
Check: src/eventsources/http.yaml
type: express
port: 3000
docs:
endpoint: api-docs
This allows you to start writing HTTP APIs immediately without additional setup.
๐น Optional: Add Another Event Sourceโ
If you want to consume events from other protocols (e.g., Kafka, WebSocket, Cron) use:
godspeed plugin add
Select the required event source like:
kafka-as-datasource-as-eventsource
cron-as-eventsource
graphql-as-eventsource
Then configure it in the src/eventsources/
folder.
Step 2: Define the Schema for your APIโ
Event Schemaโ
To define an api endpoint, first you need to write an Event Schema. This schema is a structured YAML configuration that follows the OpenAPI specification, allowing you to define every detail of how the event should behave. All events adhere to a standard structure, which is one of the core design principles of Godspeed, regardless of their source or protocol.
It involves specifying:
- The name/topic/URL of the event
- The event handler Workflow (fn)
- Input and Output schema
- Validation error handling
- Authorization checks
By writing an event schema, you provide a blueprint that defines how an incoming request or message should be handled, making your API endpoints easy to manage and highly configurable.
The generic Event Schemaโ
Godspeed follows Schema Driven Development & Single Source of Truth, Configure Over Code and Modular Architecture approach in
- Listening to events from various sources and acting upon them.
- Generating API documentation (Swagger) and other schemas like Graphql
The meta-framework follows a generic schema for defining events - their inputs, outputs, swagger specs, with validations, authentication, authorization etc.
http.get./greet: #The initial line depicts a fusion of the event, the employed method, and the path associated with the event.
fn: function_greet #Required. The 'fn' key receives the function name located in 'src/functions' and forwards the accompanying parameters.
#optional configurations
#Swagger components
body: #same as requestBody in Swagger world
params: #same as swagger `parameters` schema
responses: #same as swagger `responses` schema
id: # swagger. if not provided, when generating swagger, this is generated from the URI of the event by default
operationId: # swagger if not provided, check if `id` is set. If that is also not set, use the summary to generate the operationId
summary:
tags: # swagger if you give `tags` array in schema of event, framework uses that to add tags to your generated spec. Else it uses the path and name of the file containing the event as tags. For ex. <folder_name>_<file_name>
#Other non-swagger components (optional)
authn: #custom authentication. Currently plugins support JWT. Can be customized
authz: #your custom authz workflow
on_request_validation_error: #when validation fails
on_response_validation_error: #when validation fails
log: #Open Telemetry compliant log attributes which help debug and search through logs better
attributes:
Lets understand the first line from the above snippet http.get./greet
.
http
: Protocol http eventsource (can be any)
get
: method (depends on the eventsource used. Can be topic for Kafka)
/helloworld
: endpoint (In case of http and graphql sources. Can be groupId in case of Kafka for ex.)
We are exposing an endpoint with a get
method on http
protocol. This endpoint is calling an eventhandler called helloworld
in the second line. Event handlers can be functions written in typescript, javascript or yaml workflows in Godspeed's DSL format. In the above example the helloworld function exists in src/functions
directory.
Key Differences between a Sync and Async Event Schemaโ
When switching between eventsources, the event schema undergoes significant changes.
- The first line is changed for each protocol:
In the case of sync events or HTTP events, the start line includes the eventsource name, method, and path.
However, for async events, the start line combines the source name, topic and group ID (for Kafka), or schedule (for Cron).
-
Async events like Kafka do not have responses, authentication and authorization fields in schema.
-
Cron events do not have any input.
You can apply multiple compatible eventsource instances in a URI for ex. graphql & http.get./greeting
Example HTTP Event Schemaโ
Example: src/events/helloworld.yaml
http.get./helloworld:
fn: helloworld
authn: false
params:
- name: name
in: query
required: true
schema:
type: string
responses:
200:
content:
application/json:
schema:
type: string
Anatomy of an Eventโ
Field | Purpose |
---|---|
http.get./helloworld | Event key โ REST method and route |
fn | The function (event handler) to invoke |
params | Query/path/header parameters, as per Swagger format |
responses | API response schema definition for documentation and validation |
authn | Set to true or false to require authentication |
This schema controls how Swagger UI documents the API and how the framework validates inputs.
Step 3: Write the Event Handler Functionโ
The event handler function processes the request. It can be written in TypeScript or Javascript.
๐น Example: TypeScript Handler Functionโ
src/functions/helloworld.ts
import { GSCloudEvent, GSContext, PlainObject, GSStatus } from "@godspeedsystems/core";
export default function (ctx: GSContext, args: PlainObject) {
const {
inputs: {
data: {
query // query parameters from rest api
// params,//path parameters from endpoint url
// body, // request body in case of http and graphql apis, event data in case of message bus or socket
// user, // user payload parsed from jwt token
// headers //request headers in case of http and graphql apis
}
},
}= ctx;
return new GSStatus(true, 200, 'OK', 'Hello ' + query.name);
}
In Godspeed, your function gets input in a standard JSON format and returns output in a standard JSON format, independent of the eventsource through which this function is triggered. Eventsource could be Express, Fastify, Apollo Graphql or event message bus like Kafka, RabbitMQ or socket message. This means Godspeed has a unified way to deal with all eventsources, giving you modular architecture and re-uasability of your functions.
Click the link below to explore the complete anatomy of an event handler function written in TypeScript. It illustrates how to access inputs, use the GSContext, interact with datasources, and return responses correctly.
๐ Full Example: Understanding Godspeed Function Structure
Test Your APIโ
Run the service:
godspeed serve
Visit the Swagger UI at:
http://localhost:3000/api-docs
Try the /helloworld
endpoint. Provide a name
in the query, and observe the JSON response.
Summaryโ
Step | Action | File Path |
---|---|---|
1 | Confirm eventsource (Express or other) | src/eventsources/<eventsource-name>.yaml |
2 | Define your event schema | src/events/<your-api>.yaml |
3 | Write the event handler function | src/functions/<your-function>.ts |
Extending Furtherโ
- Use
datasources
(Axios, AWS, Prisma) in the handler viactx.datasources
- Chain multiple tasks using YAML workflows instead of writing code
- Auto-generate CRUD APIs via
godspeed gen-crud-api
To get a quick understanding of Event schema, please watch the video provided belowโฆ