Third-party integrations
Use the OAuth-style authorization flow to connect organizer accounts and read event feed data from the API with a scoped bearer token.
1) Redirect users to authorize
Send organizers to Kagibag with your app name, callback URL, and a random state value.
GET /oauth/authorize?client_name=MyApp&redirect_uri=https%3A%2F%2Fexample.com%2Fkagibag%2Fcallback&state=csrf_token_123client_name: Display name shown on the consent screen.redirect_uri: Your callback URL that receives success/error params.state: Your anti-CSRF token. Validate it on callback.
2) Handle callback results
Kagibag redirects back to your redirect_uri with either a token payload or an error payload.
Success query params
token: Sanctum bearer token scoped toevents:readevent_feed_url: Organizer feed endpoint URLstate: Echoed value from your original request
Error query params
error:access_deniederror_description: Reason (for example, user denied or not organizer)state: Echoed value from your original request
3) Read organizer event feeds
Use the returned token as a bearer token on the organizer event endpoints.
curl -H "Authorization: Bearer {token}" "{event_feed_url}"curl -H "Authorization: Bearer {token}" "https://app.kagibag.test/api/v1/organizer/{team_slug}/events/{event_slug}"List events:
GET /api/v1/organizer/{team:slug}/eventsEvent detail: GET /api/v1/organizer/{team:slug}/events/{slug}Auth scope: tokens can only access the issuing organizer's team feed.Security checklist
- Generate a unique, random state per authorization request and verify it on callback.
- Use HTTPS callback URLs in production only.
- Treat the token like a secret and store it encrypted at rest.
- Never expose tokens in client-side logs, analytics, or browser storage when avoidable.
- Handle denied/error callbacks gracefully and prompt users to retry if needed.
Example callback handler
if (query.error) {
assert(query.state === session.oauth_state);
return showError(query.error_description ?? 'Authorization failed');
}
assert(query.state === session.oauth_state);
saveKagibagToken(query.token);
saveKagibagFeedUrl(query.event_feed_url);
return syncEventsNow();