Authentication, Limits, and Errors
API keys#
Create REST API keys in the dashboard under MCP & APIs. Send the key in the Authorization header as a Bearer token on protected /api/projects/:projectId/* requests. MCP uses OAuth instead, and visitor endpoints are anonymous and must not receive this header.
curl -H "Authorization: Bearer gi_live_a1b2c3d4e5f6..." \
"https://goodinbound.com/api/projects/proj_123/contacts"
API keys are project-scoped management credentials. Keep them in server-side secret storage or a local agent configuration. Never expose them in visitor-side code.
API and MCP access are available on every plan with no monthly request quota. Read GET /api/projects/:projectId/entitlements when your integration needs the current resource limits.
Send either a dashboard session or an API key, never both:
| Situation | Error code |
|---|---|
A valid session plus any Authorization header |
ambiguous_credentials |
| An invalid Bearer value (never falls back to a session) | invalid_api_key |
| A key used with another project | api_key_project_mismatch |
| A project without API access on its plan | api_access_unavailable |
Rate limits#
Over a limit, requests return 429 Too Many Requests with code rate_limited and a Retry-After header.
| Endpoint | Limit |
|---|---|
| Availability checks | 60 requests/minute per IP |
| Booking creation | 10 requests/minute and 5 bookings per project every 10 minutes per IP |
| Form responses | 30 requests/minute per IP |
| Form response uploads | 30 requests/minute per IP |
| Form step submissions | 60 requests/minute per IP |
| REST API (API key) | 120 requests/minute per key |
| MCP tools | 120 calls/minute per project and tool |
Per-IP limits apply to visitor endpoints. Protected project requests are also constrained by project ownership, current plan, and resource limits.
Errors#
All errors return a JSON object with a descriptive error field, and sometimes a stable code. Use the HTTP status to tell the kind of error apart.
{
"error": "Descriptive error message"
}
| Status | Meaning |
|---|---|
| 400 | Validation error: check your request body or parameters |
| 401 | Unauthorized: missing or invalid API key |
| 403 | Forbidden: plan limit reached or feature not available |
| 404 | Not found: the resource does not exist |
| 409 | Conflict: a unique value already exists or a referenced resource cannot be deleted |
| 429 | Rate limited: too many requests, try again later |
| 500 | Server error: something went wrong on our end |
Pagination#
Pagination is endpoint-specific. Do not assume every list uses the same model.
| List | Model |
|---|---|
| Contacts | Offset pagination with limit and offset. Default 50, maximum 100; the response includes the full filtered total. |
| Contact activity | Cursor pagination, default 20, maximum 100. Pass the returned opaque nextCursor unchanged. |
| Tags | Optional cursor pagination from 1 to 100 items. When using a cursor, repeat the same limit on the next request. |
| Other lists | Return their complete result unless their section lists a limit. |