Developer preview

Build with Shindig

One group-planning API, two transports. Approved integrations can help a user create a draft event, configure polls and tasks, add links and FAQs, and hand control back to the organiser. REST and MCP share the app’s permissions and business rules.

Agent access is limited to approved OAuth clients. These preview docs describe the implemented REST/MCP contract and the intended production connection setup. Client registration and account linking require approval; this page is not a public onboarding invitation. Disabled API and MCP endpoints return 404.

Endpoints

Availability

These are the intended production URLs. Approved development integrations receive their own issuer and resource URLs; never mix development tokens with production resources. Discovery is available only when the corresponding feature is enabled.

  • REST base URLhttps://api.getshindig.app/v1
  • MCP endpointhttps://api.getshindig.app/mcp
  • Issuerhttps://getshindig.app/api/auth
  • Authorization endpointhttps://getshindig.app/api/auth/oauth2/authorize
  • Token endpointhttps://getshindig.app/api/auth/oauth2/token
  • REST protected-resource metadatahttps://api.getshindig.app/.well-known/oauth-protected-resource/v1
  • MCP protected-resource metadatahttps://api.getshindig.app/.well-known/oauth-protected-resource/mcp
  • Authorization-server metadatahttps://getshindig.app/.well-known/oauth-authorization-server/api/auth
  • OpenAPI documenthttps://api.getshindig.app/v1/openapi.json
OAuth 2.0

Connect with OAuth

  1. Client registration is admin-approved. Dynamic client registration, API keys and client-credentials grants are not supported in v1.
  2. Use authorization code flow with PKCE S256. Send client_id, an approved redirect_uri, response_type=code, code_challenge, code_challenge_method=S256, requested scopes, state and the exact resource URL. Validate state on return and exchange the code with the original code_verifier and redirect_uri. Registered confidential clients must also authenticate at the token endpoint.
  3. REST tokens must target the REST resource URL ending in /v1; MCP tokens must target the MCP resource URL ending in /mcp. A token for one audience is not accepted by the other. Discover the authorization server from the matching protected-resource metadata rather than inferring it from the endpoint host.
  4. Request only the permissions needed. profile is required for GET /v1/me and get_current_profile, not as a blanket scope for every tool. Request offline_access if refresh-token access is needed; retain it when refreshing a chain that should continue rotating.
  5. Users sign in to Shindig and approve the client’s requested permissions. Never ask for a Shindig password, session cookie or another client’s credentials.
Permissions

Permissions

OAuth scopes for REST and MCP
ScopeDescription
profileRead the connected user’s profile ID.
events:readList and read events the user belongs to.
events:writeCreate drafts and update events the user hosts.
events:publishExplicitly publish hosted drafts and read active share links.
polls:readRead aggregate date and choice poll results.
polls:writeConfigure date polls and create choice polls or options on hosted events.
tasks:writeCreate and update tasks with the existing host permissions.
content:writeAppend links and FAQs to hosted events.
offline_accessAllow refresh-token access; this is not an event permission.

A scope does not replace event access checks. Membership is required for event reads; writes and share links require the relevant host permissions. Plan limits and event lifecycle rules still apply.

REST API

REST API

Send Authorization: Bearer <access_token>. Nonempty write bodies use application/json; every write requires an Idempotency-Key. The full request/response schemas are published in the OpenAPI 3.1 discovery document when enabled. This is a server-to-server API; browser CORS access to business routes is not supported.

REST operations and equivalent MCP tools
ActionMethodPathScopeMCP tool
profile.meGET/v1/meprofileget_current_profile
events.createPOST/v1/eventsevents:writecreate_event
events.listGET/v1/eventsevents:readlist_events
events.getGET/v1/events/{eventId}events:readget_event
events.updatePATCH/v1/events/{eventId}events:writeupdate_event
events.publishPOST/v1/events/{eventId}/publishevents:publishpublish_event
events.shareLinkGET/v1/events/{eventId}/share-linkevents:publishget_event_share_link
datePoll.upsertPUT/v1/events/{eventId}/date-pollpolls:writeset_date_poll
datePoll.resultsGET/v1/events/{eventId}/date-poll/resultspolls:readget_date_poll_results
choicePolls.createPOST/v1/events/{eventId}/choice-pollspolls:writecreate_choice_poll
choicePolls.addOptionPOST/v1/events/{eventId}/choice-polls/{pollId}/optionspolls:writeadd_choice_poll_option
choicePolls.resultsGET/v1/events/{eventId}/choice-polls/{pollId}/resultspolls:readget_choice_poll_results
tasks.createPOST/v1/events/{eventId}/taskstasks:writecreate_task
tasks.updatePATCH/v1/tasks/{taskId}tasks:writeupdate_task
links.addPOST/v1/events/{eventId}/linkscontent:writeadd_useful_link
faqs.addPOST/v1/events/{eventId}/faqscontent:writeadd_faq

Event lists default to 20 entries, with a maximum of 50. A status-filtered page can be empty while nextCursor is non-null: keep following the cursor until it is null. Opaque cursors are bound to the client, user and filter and expire after 24 hours. Poll results are aggregate-only. Reads beyond supported budgets return 422 resource_too_large rather than silently truncated results. The same error is also used when link, FAQ or task limits are exceeded.

REST and MCP share token-bucket limits: 60 requests per minute per client and profile (burst 20), and 600 requests per minute per client (burst 100). Admitted scope, validation and domain failures consume quota; quota-refused requests do not. MCP initialization and tool discovery do not consume the domain-operation quota.

MCP

Use the same capabilities through MCP

MCP uses authenticated streamable HTTP at the MCP resource URL. Connect an OAuth-capable MCP client, complete account linking, then initialize and discover tools through tools/list. Tool names and required scopes are shown alongside the REST operations above; each tool enforces its own scope. Read operations return structured data, and failures carry stable problem details.

Write tools require idempotencyKey in their arguments. Most write tools put the request fields inside body and resource IDs alongside it; publish_event takes eventId and idempotencyKey without a body. Follow the discovered input schema, not a guessed argument shape. REST and MCP share quotas and access checks; an idempotency key must not be reused across transports for the same action.

Examples

Examples

Examples require an approved client, an enabled endpoint and a token with the matching scopes. ACCESS_TOKEN is the OAuth access token; CREATE_EVENT_KEY is a unique key chosen once for this logical create operation and retained for retries. Do not paste real tokens into issue reports, screenshots or logs.

curl 'https://api.getshindig.app/v1/events?limit=20' \
  -H "Authorization: Bearer $ACCESS_TOKEN"
curl -X POST 'https://api.getshindig.app/v1/events' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H 'Content-Type: application/json' \
  -H "Idempotency-Key: $CREATE_EVENT_KEY" \
  --data '{"title":"Group weekend","dateMode":"poll"}'
{
  "idempotencyKey": "weekend-create-001",
  "body": {
    "title": "Group weekend",
    "dateMode": "poll"
  }
}
  1. Create a draft event with events:write. The returned appUrl is for the organiser to review; it is not an invite link.
  2. Set the full date-poll candidate list in one operation using real YYYY-MM-DD calendar dates (at least two), then add choice polls, tasks, links or FAQs as needed.
  3. Ask the organiser to review the plan. Changes to published event dates can notify members; draft creation does not silently publish or invite anyone.
  4. Publish only after an explicit request from the organiser and with events:publish. The event must satisfy the app’s publish validation and plan limits.
  5. Read the share link only after the event is published and active. Hand it to the organiser to share; the integration does not send third-party invitations.
Reliability

Errors and retries

401 means the token is missing, invalid, expired, revoked or intended for another audience. Reauthenticate or refresh only as appropriate; do not retry indefinitely. 403 means a required scope or event permission is missing. 409 can signal idempotency-key reuse with a different request. 422 resource_too_large can indicate a read budget or a link, FAQ or task limit; reduce the request or resource rather than retrying unchanged. 413 payload_too_large means the request body exceeds the payload-size limit. 429 includes Retry-After; wait before retrying.

Writes are retained for idempotent replay for 24 hours. For REST retries, reuse the exact original key, method, path, query and raw JSON body bytes. For MCP retries, reuse the same key and arguments; validated arguments are canonicalized independently of JSON-RPC request IDs. Replays re-check current permissions and do not repeat committed writes or notifications.

After an ambiguous internal_error, the write may already have committed. Retry the original key and identical request or read the current state; do not repeat the action under a new key. Invalid arguments can be corrected and retried with the same key because validation runs before the mutation.

Rotated refresh-token reuse is treated as possible theft and revokes that exact connection, including lost-response retries. On invalid_grant, reconnect and reauthorize instead of blindly retrying a consumed refresh token.

Errors use stable codes and request IDs; REST uses application/problem+json. Provide the request ID and a redacted reproduction when asking for help, never bearer tokens or secrets.

Control

Safety and revocation

Users manage authorized clients in Settings → Connected apps and can disconnect them. Revocation invalidates bound access tokens, refresh tokens and unused authorization codes; reconnecting does not revive old credentials.

Keep publishing an explicit user decision. V1 does not expose event deletion, member removal, ownership transfer, third-party invitations, expense modification or payment actions. The integration is not a subscription checkout or upsell flow.

Changing the configured resource origin invalidates old-audience access tokens and old-resource requests. Update discovery/resource/origin URLs; a still-valid consent-bound refresh token may obtain a token for the new resource, otherwise reconnect. There is no dual-audience overlap period.