> ## Documentation Index
> Fetch the complete documentation index at: https://developer.meetergo.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Troubleshooting

> Common issues and how to resolve them

Solutions to frequently encountered problems when integrating with the meetergo API.

## Authentication Issues

### 401 Unauthorized

**Symptoms:** API returns `401 Unauthorized`

**Causes & Solutions:**

<AccordionGroup>
  <Accordion title="Invalid API key format">
    API keys must follow the format: `ak_live:<uuid>:<secret>`

    ```bash theme={null}
    # Correct
    Authorization: Bearer ak_live:01234567-89ab-cdef-0123-456789abcdef:secretpart

    # Wrong - missing Bearer
    Authorization: ak_live:01234567-89ab-cdef-0123-456789abcdef:secretpart

    # Wrong - using "API-Key" instead of "Bearer"
    Authorization: API-Key ak_live:...
    ```
  </Accordion>

  <Accordion title="Expired API key">
    API keys have mandatory expiration dates (1-90 days). Check when your key was created and generate a new one if expired.

    ```bash theme={null}
    # Test your key
    curl -X GET "https://api.meetergo.com/v4/user/me" \
      -H "Authorization: Bearer YOUR_API_KEY"
    ```
  </Accordion>

  <Accordion title="Deactivated key">
    Keys can be deactivated in the dashboard. Check [my.meetergo.com/admin/api-keys](https://my.meetergo.com/admin/api-keys) to verify your key is active.
  </Accordion>
</AccordionGroup>

### 400 Missing x-meetergo-api-user-id Header

**Symptoms:** API returns `400 Bad Request` with message about missing header

**Solution:** Most endpoints require the `x-meetergo-api-user-id` header:

```javascript theme={null}
const response = await fetch('https://api.meetergo.com/v4/meeting-type', {
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'x-meetergo-api-user-id': 'user-uuid-here'  // Required!
  }
});
```

**How to get the user ID:**

```bash theme={null}
# Get your own user ID
curl -X GET "https://api.meetergo.com/v4/user/me" \
  -H "Authorization: Bearer YOUR_API_KEY"

# Response includes your user ID
# { "id": "user-uuid-here", ... }
```

## Availability Issues

### No Available Slots Returned

**Symptoms:** `GET /v4/booking-availability` returns empty `dates` array

<AccordionGroup>
  <Accordion title="Date range is in the past">
    Ensure `start` and `end` dates are in the future:

    ```javascript theme={null}
    const today = new Date();
    const nextWeek = new Date(today.getTime() + 7 * 24 * 60 * 60 * 1000);

    const params = new URLSearchParams({
      meetingTypeId: meetingTypeId,
      start: today.toISOString().split('T')[0],  // Today
      end: nextWeek.toISOString().split('T')[0]  // 7 days from now
    });
    ```
  </Accordion>

  <Accordion title="No availability configured">
    The user may not have availability set up. Check their availability:

    ```bash theme={null}
    curl -X GET "https://api.meetergo.com/availability?userId=USER_ID" \
      -H "Authorization: Bearer YOUR_API_KEY" \
      -H "x-meetergo-api-user-id: USER_ID"
    ```
  </Accordion>

  <Accordion title="Calendar is fully booked">
    The host's calendar may be full. Try a longer date range or use `troubleshoot: true`:

    ```bash theme={null}
    curl -X GET "https://api.meetergo.com/v4/booking-availability?\
    meetingTypeId=MT_ID&start=2024-01-15&end=2024-01-22&troubleshoot=true" \
      -H "Authorization: Bearer YOUR_API_KEY"
    ```

    This returns blocked timeslots with reasons.
  </Accordion>

  <Accordion title="Minimum notice period">
    The meeting type may have a minimum notice period. If it's set to 24 hours, slots within the next 24 hours won't appear.
  </Accordion>

  <Accordion title="Buffer times">
    Buffer times before/after meetings reduce available slots. A 30-minute meeting with 15-minute buffers needs 60 minutes of free time.
  </Accordion>
</AccordionGroup>

### Slots Show Wrong Times

**Symptoms:** Available slots don't match expected availability

<AccordionGroup>
  <Accordion title="Timezone mismatch">
    All API times are in UTC by default. Specify timezone if needed:

    ```javascript theme={null}
    const params = new URLSearchParams({
      meetingTypeId: meetingTypeId,
      start: '2024-01-15',
      end: '2024-01-22',
      timezone: 'Europe/Berlin'  // Get slots in local timezone
    });
    ```
  </Accordion>

  <Accordion title="Calendar sync delay">
    External calendar events may take a few minutes to sync. If a slot was just blocked, it might still appear available briefly.
  </Accordion>
</AccordionGroup>

## Booking Issues

### 400 Bad Request on Booking

**Symptoms:** `POST /v4/booking` returns `400`

<AccordionGroup>
  <Accordion title="Slot no longer available">
    The slot may have been booked by someone else. Always fetch fresh availability before booking:

    ```javascript theme={null}
    // 1. Get availability
    const slots = await getAvailability(meetingTypeId);

    // 2. Book immediately (don't cache slots for long)
    const booking = await createBooking(slots[0].start);
    ```
  </Accordion>

  <Accordion title="Invalid attendee data">
    Check attendee fields:

    ```javascript theme={null}
    // Correct
    attendee: {
      email: 'valid@email.com',       // Required (unless allowPhoneOnlyBooking)
      fullname: 'John Doe',           // Required
      phone: '+1234567890'            // E.164 format recommended
    }

    // Wrong - missing required fields
    attendee: {
      email: 'valid@email.com'
      // Missing fullname
    }
    ```
  </Accordion>

  <Accordion title="Phone-only booking not enabled">
    If booking without email, enable `allowPhoneOnlyBooking` on the meeting type:

    ```bash theme={null}
    curl -X PATCH "https://api.meetergo.com/v4/meeting-type/MT_ID" \
      -H "Authorization: Bearer YOUR_API_KEY" \
      -H "x-meetergo-api-user-id: USER_ID" \
      -H "Content-Type: application/json" \
      -d '{"meetingOptions": {"allowPhoneOnlyBooking": true}}'
    ```
  </Accordion>

  <Accordion title="Invalid start time format">
    Use ISO 8601 format:

    ```javascript theme={null}
    // Correct
    start: '2024-01-15T14:00:00Z'
    start: '2024-01-15T14:00:00+01:00'

    // Wrong
    start: '2024-01-15 14:00:00'
    start: '01/15/2024 2:00 PM'
    ```
  </Accordion>
</AccordionGroup>

## Webhook Issues

### Webhooks Not Received

<AccordionGroup>
  <Accordion title="Endpoint not reachable">
    Your webhook endpoint must be publicly accessible. Test with:

    ```bash theme={null}
    curl -X POST "https://your-server.com/webhooks/meetergo" \
      -H "Content-Type: application/json" \
      -d '{"test": true}'
    ```
  </Accordion>

  <Accordion title="HTTPS required">
    Webhook endpoints must use HTTPS in production.
  </Accordion>

  <Accordion title="Responding too slowly">
    Respond with `200 OK` immediately, then process async:

    ```javascript theme={null}
    app.post('/webhooks/meetergo', async (req, res) => {
      // Respond immediately
      res.status(200).send('OK');

      // Process in background
      processWebhook(req.body).catch(console.error);
    });
    ```
  </Accordion>

  <Accordion title="Wrong event types">
    Verify your webhook is subscribed to the right events:

    ```bash theme={null}
    curl -X GET "https://api.meetergo.com/webhooks" \
      -H "Authorization: Bearer YOUR_API_KEY" \
      -H "x-meetergo-api-user-id: USER_ID"
    ```
  </Accordion>
</AccordionGroup>

### Duplicate Webhooks

**Symptoms:** Same event received multiple times

**Solution:** Implement idempotency:

```javascript theme={null}
const processedEvents = new Set();

app.post('/webhooks/meetergo', async (req, res) => {
  res.status(200).send('OK');

  const eventId = `${req.body.webhookType}-${req.body.id || req.body.formId}-${req.body.updatedAt || req.body.submittedAt}`;

  if (processedEvents.has(eventId)) {
    console.log('Duplicate event, skipping');
    return;
  }

  processedEvents.add(eventId);

  // Process event...

  // Clean up old events periodically
  setTimeout(() => processedEvents.delete(eventId), 3600000);
});
```

## Rate Limiting

### 429 Too Many Requests

**Symptoms:** API returns `429` status code

**Solution:** Implement exponential backoff:

```javascript theme={null}
async function fetchWithRetry(url, options, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    const response = await fetch(url, options);

    if (response.status === 429) {
      const retryAfter = response.headers.get('Retry-After') || Math.pow(2, i);
      console.log(`Rate limited, waiting ${retryAfter}s`);
      await new Promise(r => setTimeout(r, retryAfter * 1000));
      continue;
    }

    return response;
  }

  throw new Error('Max retries exceeded');
}
```

**Rate limits:**

* 100 requests/minute per API key
* Burst allowance up to 200 requests

## Common Error Codes

| Code  | Meaning       | Solution                                   |
| ----- | ------------- | ------------------------------------------ |
| `400` | Bad Request   | Check request body and parameters          |
| `401` | Unauthorized  | Verify API key                             |
| `403` | Forbidden     | Check permissions for the resource         |
| `404` | Not Found     | Verify ID exists                           |
| `409` | Conflict      | Resource already exists or slot taken      |
| `422` | Unprocessable | Validation failed, check field values      |
| `429` | Rate Limited  | Implement backoff, reduce request rate     |
| `500` | Server Error  | Retry later, contact support if persistent |

## Getting Help

If you're still stuck:

1. **Check the request/response** - Log full request and response bodies
2. **Use troubleshoot mode** - Add `?troubleshoot=true` to availability calls
3. **Test in Swagger UI** - [api.meetergo.com/spec/v2](https://api.meetergo.com/spec/v2)
4. **Contact support** - [api-support@meetergo.com](mailto:api-support@meetergo.com)

When contacting support, include:

* Request URL and method
* Request headers (redact API key)
* Request body
* Response status and body
* Timestamp of the request
