Building Integrations
GGNomad is designed to plug into the systems a travel business already runs — property management systems, channel managers, and ticketing platforms — and to let partners build their own apps on top of GGNomad inventory and bookings. This guide walks through the building blocks of an integration: querying inventory, writing bookings, keeping availability in sync, and reacting to domain events.
The SDKs and the CLI referenced below are roadmap and not yet published; the GraphQL API is the available surface.
Integration building blocks
The pieces of an integration A typical GGNomad integration is built from:
- A workspace-scoped credential (OAuth client or API key)
- Read queries against inventory (listings, providers, availability)
- Write mutations for bookings and listings
- An event subscription to react to changes (for example
booking.created) - Idempotent sync logic so re-runs are safe
What you can integrate GGNomad commonly connects with:
- Property and channel management systems (availability and rates)
- Ticketing and event platforms (events and ticket inventory)
- Payment and finance systems (settlement and reconciliation)
- Notification and CRM tools (traveler and host communications)
Getting set up
Create credentials Issue a workspace-scoped credential from the developer portal, then confirm connectivity with a read query:
query Ping {
ggnomadProperties(pagination: { skip: 0, take: 1 }) { id name }
}
If this returns results, your token carries the ggnomad:read permission and is
scoped to the right workspace.
Reading inventory
Pull listings to mirror or display them in your own system. Request only the fields you need:
query Inventory {
ggnomadProperties(pagination: { skip: 0, take: 50 }) {
id
name
location
pricePerNight
provider { id name type }
}
}
The same pattern applies to tours, activities, events, and transport trips.
Writing bookings
Confirm a reservation from your own checkout or back office. GGNomad generates a
reference code, validates workspace ownership of the target, and emits a
booking.created event:
mutation Book($input: CreateGgnomadBookingInput!) {
createGgnomadBooking(input: $input) {
id
referenceCode
status
paymentStatus
}
}
Cancellation Cancellations move a booking to the cancelled state, with the transition recorded on both the trip timeline and the host's booking queue:
mutation Cancel($id: ID!) {
cancelGgnomadBooking(id: $id) { id status }
}
Reacting to events
Rather than polling, subscribe to GGNomad's domain events. A common pattern is to keep an external system in sync as bookings are confirmed — register a webhook endpoint for the events you care about and handle the delivery:
// Your webhook endpoint, subscribed to ggnomad.booking.created
app.post('/webhooks/ggnomad', async (req, res) => {
const event = req.body;
if (event.type === 'ggnomad.booking.created') {
// Mirror the confirmed booking into your PMS / channel manager
await syncBookingToExternalSystem(event.payload);
}
res.sendStatus(200);
});
Build your handler to be idempotent — events may be redelivered, so applying
the same booking.created twice must be a no-op.
Keeping availability in sync
When inventory changes in an external system, push the change into GGNomad so discovery and checkout price against current availability. A robust sync:
- Reads the current GGNomad state for the affected listing
- Computes the delta against the source of truth
- Applies updates through the appropriate mutation
- Records the sync so re-runs are safe
Error handling
Handle the typed GraphQL error codes rather than parsing messages:
UNAUTHENTICATED/FORBIDDEN— token or permission issueWORKSPACE_REQUIRED— missing workspace contextNOT_FOUND— the target does not exist in this workspaceVALIDATION_ERROR— input failed validation
const { data, errors } = await client.request(CREATE_BOOKING, variables);
if (errors?.length) {
const code = errors[0].extensions?.code;
if (code === 'VALIDATION_ERROR') {
// surface field-level details to the caller
}
throw new IntegrationError(code, errors[0].message);
}
Best practices
- Send every call to the public API endpoint with a valid credential
- Let roles scope every action — request the minimum permissions
- Make writes and event handlers idempotent
- Paginate every list query and request only needed fields
- Treat the published GraphQL schema as the contract — watch for deprecations
Getting started
Begin building an integration:
- Issue a credential and confirm a read query works
- Wire booking create/cancel into your flow
- Subscribe to
booking.createdand keep an external system in sync - Verify cross-workspace isolation and RBAC behavior
For integration support, see the API Reference or contact the GGNomad developer team.