API reference

Webhooks

We tell your server when something changes that you did not cause: a hold running out, a staging area closing, a rule changing. Nothing is sent for what you did yourself, such as checking in or cancelling. Register an endpoint, and we send each event to it as a signed POST.

Each POST carries a Lanoo-Signature header, t=<unix seconds>,v1=<hex>, where v1 is an HMAC-SHA256 of <t>.<raw body> with the endpoint's secret. Compare it in constant time and reject a t, the time we sent it, more than 5 minutes from your clock either way. Answer with a 2xx; anything else, or no answer, counts as failed, and failed deliveries are retried with backoff. Events can arrive more than once and out of order.

The event object

idstringrequired

Unique, starting evt_. The same event may arrive more than once; use this to notice.

object"event"required
typeenumrequired

reservation.expired: the vehicle did not check in before held_until. reservation.cancelled: the staging area closed and gave up your hold; alternatives lists others with room. Not sent when you cancel yourself. reservation.overstayed: a checked-in vehicle is past leave_by; sent once. What follows is for the staging area's owner to decide. reservation.must_leave: the staging area closed suddenly with your vehicle checked in; it has to leave now, and alternatives lists others with room. staging_area.updated: its rules, details or planned closures changed. staging_area.closed and staging_area.reopened: it stopped or started taking vehicles. ping: a test event, sent only when you ask for one; you need not list it.

One of reservation.expired, reservation.cancelled, reservation.overstayed, reservation.must_leave, staging_area.updated, staging_area.closed, staging_area.reopened, ping.

created_attimestamprequired
api_versionstringrequired

The API version the event is written in.

dataobjectrequired

object is the reservation or staging area as it is after the change. On ping, it is the endpoint.

The event object
{
"id": "evt_1c7e55",
"object": "event",
"type": "reservation.expired",
"created_at": "2026-11-02T14:02:00Z",
"api_version": "2026-10-30",
"data": {
"object": {
"id": "res_8f2c41",
"object": "reservation",
"vehicle_id": "rt-0417",
"staging_area": "sa_norreport",
"spot": "2",
"location": {
"lat": 55.6838,
"lng": 12.5721
},
"status": "held",
"arrive_by": "2026-11-02T14:02:00Z",
"held_until": "2026-11-02T14:02:00Z",
"checked_in_at": "2026-11-02T14:02:00Z",
"leave_by": "2026-11-02T14:02:00Z",
"checked_out_at": "2026-11-02T14:02:00Z",
"cancellation_reason": "requested",
"metadata": {},
"created_at": "2026-11-02T14:02:00Z"
},
"alternatives": [
{
"object": "availability",
"staging_area": "sa_norreport",
"name": "Nørreport",
"distance_m": 420,
"free_spots": 3,
"chance_free": 0.92
}
]
}
}

Add a webhook endpoint

POST/v1/webhook_endpoints

Where to send events, and which. The response carries the endpoint's signing secret, once: store it, you need it to check every event.

Body

urlstringrequired

Where to send events. HTTPS only.

eventsarray of enumrequired

Which events to send.

Headers

Idempotency-Keystring, header

A unique key, such as a UUID, for this request. Send the same key when you retry: the request takes effect once, and the retry gets the first answer back. Kept for 24 hours. The same key with a different body is refused with idempotency_key_reused (422).

Responses

201

The endpoint, with its secret.

422
url_invalid

The URL is not HTTPS, or does not resolve.

Endpoint

POST https://api.golanoo.com/v1/webhook_endpoints

Request
curl -X POST https://api.golanoo.com/v1/webhook_endpoints \
-H "Authorization: Bearer lk_test_..." \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"url": "https://dispatch.example.com/lanoo/events",
"events": [
"reservation.expired",
"reservation.cancelled",
"staging_area.closed"
]
}'
Response
{
"id": "we_3b91d0",
"object": "webhook_endpoint",
"url": "https://dispatch.example.com/lanoo/events",
"events": [
"reservation.expired",
"reservation.cancelled",
"staging_area.closed"
],
"secret": "whsec_6f1c0a…",
"created_at": "2026-11-01T10:00:00Z"
}

List webhook endpoints

GET/v1/webhook_endpoints

Parameters

limitinteger

How many to return, 1 to 100. Defaults to 20.

starting_afterstring

For the next page, the id of the last item on this one.

Responses

200

A page of endpoints. Secrets are not shown again.

Endpoint

GET https://api.golanoo.com/v1/webhook_endpoints

Request
curl https://api.golanoo.com/v1/webhook_endpoints \
-H "Authorization: Bearer lk_test_..."
Response
{
"object": "list",
"data": [
{
"id": "we_3b91d0",
"object": "webhook_endpoint",
"url": "string",
"events": [
"reservation.expired"
],
"secret": "whsec_6f1c0a…",
"created_at": "2026-11-02T14:02:00Z"
}
],
"has_more": true
}

Remove a webhook endpoint

DEL/v1/webhook_endpoints/{id}

No more events are sent to it, including retries still waiting.

Parameters

idstring, pathrequired

The endpoint's id.

Responses

200

The endpoint, removed.

404
not_found

No endpoint with this id.

Endpoint

DELETE https://api.golanoo.com/v1/webhook_endpoints/{id}

Request
curl -X DELETE https://api.golanoo.com/v1/webhook_endpoints/we_3b91d0 \
-H "Authorization: Bearer lk_test_..."
Response
{
"id": "we_3b91d0",
"object": "webhook_endpoint",
"deleted": true
}

Change a webhook endpoint

PATCH/v1/webhook_endpoints/{id}

A new URL, other events, or both. Send only what changes. Events on their way go to the new URL from the moment it changes, and the secret stays the same.

Parameters

idstring, pathrequired

The endpoint's id.

Body

urlstring

Where to send events. HTTPS only.

eventsarray of enum

Which events to send, in place of the ones before.

Headers

Idempotency-Keystring, header

A unique key, such as a UUID, for this request. Send the same key when you retry: the request takes effect once, and the retry gets the first answer back. Kept for 24 hours. The same key with a different body is refused with idempotency_key_reused (422).

Responses

200

The endpoint as it is now.

404
not_found

No endpoint with this id.

422
url_invalid

The URL is not HTTPS, or does not resolve.

Endpoint

PATCH https://api.golanoo.com/v1/webhook_endpoints/{id}

Request
curl -X PATCH https://api.golanoo.com/v1/webhook_endpoints/we_3b91d0 \
-H "Authorization: Bearer lk_test_..." \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"events": [
"reservation.expired",
"reservation.cancelled",
"reservation.overstayed",
"staging_area.closed"
]
}'
Response
{
"id": "we_3b91d0",
"object": "webhook_endpoint",
"url": "https://dispatch.example.com/lanoo/events",
"events": [
"reservation.expired",
"reservation.cancelled",
"reservation.overstayed",
"staging_area.closed"
],
"created_at": "2026-11-01T10:00:00Z"
}

Get a new secret

POST/v1/webhook_endpoints/{id}/roll_secret

For a secret that has leaked, or one you want to change. The response carries the new secret, once. Choose when the old one stops: now for a leaked secret, or in_24_hours to swap it without missing an event. Until the old one stops, every event is signed with both.

Parameters

idstring, pathrequired

The endpoint's id.

Body

expire_old_secretenumrequired

When the old secret stops working.

One of now, in_24_hours.

Headers

Idempotency-Keystring, header

A unique key, such as a UUID, for this request. Send the same key when you retry: the request takes effect once, and the retry gets the first answer back. Kept for 24 hours. The same key with a different body is refused with idempotency_key_reused (422).

Responses

200

The endpoint, with its new secret.

404
not_found

No endpoint with this id.

Endpoint

POST https://api.golanoo.com/v1/webhook_endpoints/{id}/roll_secret

Request
curl -X POST https://api.golanoo.com/v1/webhook_endpoints/we_3b91d0/roll_secret \
-H "Authorization: Bearer lk_test_..." \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"expire_old_secret": "in_24_hours"
}'
Response
{
"id": "we_3b91d0",
"object": "webhook_endpoint",
"url": "https://dispatch.example.com/lanoo/events",
"events": [
"reservation.expired",
"reservation.cancelled",
"reservation.overstayed",
"staging_area.closed"
],
"created_at": "2026-11-01T10:00:00Z",
"secret": "whsec_9d2e4b…"
}

Send a test event

POST/v1/webhook_endpoints/{id}/ping

Sends a ping event to the endpoint straight away, signed like every other event, so you can see your server receive and check it. It is sent whichever events the endpoint asks for.

Parameters

idstring, pathrequired

The endpoint's id.

Responses

202

The event is on its way.

404
not_found

No endpoint with this id.

Endpoint

POST https://api.golanoo.com/v1/webhook_endpoints/{id}/ping

Request
curl -X POST https://api.golanoo.com/v1/webhook_endpoints/we_3b91d0/ping \
-H "Authorization: Bearer lk_test_..."
Response
{
"id": "evt_0a4f93",
"object": "event",
"type": "ping"
}