---
title: Request IDs & Debugging
description: How to use request IDs for debugging and tracing API requests
---

## Overview

Every API request to Plunk receives a unique request ID that follows the request through the entire system. Request IDs are essential for debugging, support, and monitoring.

## What are Request IDs?

A request ID is a UUID (e.g., `f47ac10b-58cc-4372-a567-0e02b2c3d479`) that:
- Is generated for every API request
- Appears in all related log entries
- Is included in both success and error responses
- Can be used to trace requests across services

## Where to Find Request IDs

### In API Responses

**Error responses** (in the `error.requestId` field):
```json
{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Request validation failed",
    "requestId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
    ...
  }
}
```

**Response headers** (always present, even on success):
```bash
X-Request-ID: f47ac10b-58cc-4372-a567-0e02b2c3d479
```

### In Your Application

You can capture and log request IDs for correlation:

```javascript
const response = await fetch('https://api.useplunk.com/v1/send', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${apiKey}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({ to, subject, body })
});

// Get request ID from response header
const requestId = response.headers.get('X-Request-ID');

// Log it for correlation
console.log(`[${requestId}] Email send request initiated`);

const data = await response.json();
if (!data.success) {
  // Request ID is also in error response
  console.error(`[${data.error.requestId}] Error:`, data.error.message);
}
```

## Database Request Logging

In addition to console/file logs, Plunk stores all API requests in the database with their request IDs. This provides:

- **Historical audit trail** - See all API calls made to your project
- **Analytics** - Analyze API usage patterns, error rates, popular endpoints
- **User-facing logs** - Display API request history in your dashboard
- **Long-term debugging** - Investigate issues that occurred days or weeks ago
- **Compliance** - Meet audit requirements for API access logs

### Database Schema

Each request is stored with:
- Request ID (primary key)
- HTTP method and path
- Status code and response time
- Project ID and user ID (if authenticated)
- IP address and user agent
- Error code and message (if failed)
- Request/response sizes
- Timestamp

### Retention Policy

API request logs are retained for **30 days** by default. A background job runs daily at 3 AM to delete older logs. This prevents unbounded table growth while maintaining recent history for debugging.

You can query your request logs via SQL if self-hosting:

```sql
-- Find all failed requests in the last 24 hours
SELECT * FROM api_requests
WHERE "statusCode" >= 400
AND "createdAt" > NOW() - INTERVAL '24 hours'
ORDER BY "createdAt" DESC;

-- Find all requests for a specific project
SELECT * FROM api_requests
WHERE "projectId" = 'prj_abc123'
ORDER BY "createdAt" DESC
LIMIT 100;

-- Analyze error rates by endpoint
SELECT
  path,
  COUNT(*) as total_requests,
  COUNT(*) FILTER (WHERE "statusCode" >= 400) as errors,
  ROUND(100.0 * COUNT(*) FILTER (WHERE "statusCode" >= 400) / COUNT(*), 2) as error_rate_pct
FROM api_requests
WHERE "createdAt" > NOW() - INTERVAL '7 days'
GROUP BY path
ORDER BY error_rate_pct DESC;
```

## How Request IDs Help with Debugging

### Example Scenario

You send an email via the API and receive an error. Here's how request IDs help:

**1. Your application receives an error:**
```json
{
  "success": false,
  "error": {
    "code": "TEMPLATE_NOT_FOUND",
    "message": "Template with ID \"tpl_abc123\" was not found",
    "requestId": "a1b2c3d4-e5f6-7890-gh12-i34567890jkl",
    ...
  }
}
```

**2. You contact support with the request ID**

**3. We search our logs for that request ID and see:**

```
[a1b2c3d4-e5f6-7890-gh12-i34567890jkl] POST /v1/send → Request received
  └─ authType: apiKey
  └─ projectId: prj_xyz789
  └─ ip: 192.168.1.1

[a1b2c3d4-e5f6-7890-gh12-i34567890jkl] Looking up template: tpl_abc123
  └─ projectId: prj_xyz789

[a1b2c3d4-e5f6-7890-gh12-i34567890jkl] Template not found
  └─ errorCode: TEMPLATE_NOT_FOUND
  └─ statusCode: 404

[a1b2c3d4-e5f6-7890-gh12-i34567890jkl] POST /v1/send → 404 (45ms)
```

From this, we can immediately see:
- You're authenticated correctly (authType: apiKey)
- The template ID doesn't exist in your project
- The request took 45ms to process
- No database errors or system issues

**Result:** We can quickly tell you "That template doesn't exist in your project" without back-and-forth debugging.

## Using Request IDs in Self-Hosted Deployments

If you're self-hosting Plunk, you can use request IDs to debug issues in your own logs.

### Searching Logs

**With Docker logs:**
```bash
# Find all logs for a specific request
docker logs plunk-api 2>&1 | grep "a1b2c3d4-e5f6-7890-gh12-i34567890jkl"
```

**With standard logs:**
```bash
# Search application logs
grep "a1b2c3d4-e5f6-7890-gh12-i34567890jkl" /var/log/plunk/api.log

# Search with context (10 lines before and after)
grep -C 10 "a1b2c3d4-e5f6-7890-gh12-i34567890jkl" /var/log/plunk/api.log
```

### Log Structure

Every log entry includes the request ID in brackets:

```
[f47ac10b-58cc-4372-a567-0e02b2c3d479] POST /v1/track → Request received
[f47ac10b-58cc-4372-a567-0e02b2c3d479] Contact created: cnt_abc123
[f47ac10b-58cc-4372-a567-0e02b2c3d479] Event tracked: evt_xyz789
[f47ac10b-58cc-4372-a567-0e02b2c3d479] POST /v1/track → 200 (127ms)
```

This makes it easy to trace a single request from start to finish.

## Providing Request IDs with Load Balancers

If you use a load balancer or API gateway, you can pass your own request IDs:

```bash
curl -X POST https://api.useplunk.com/v1/send \
  -H "X-Request-ID: your-custom-request-id" \
  -H "Authorization: Bearer sk_..." \
  -H "Content-Type: application/json" \
  -d '...'
```

Plunk will use your provided request ID instead of generating a new one. This allows you to:
- Correlate requests across your entire system
- Trace requests from your frontend → your backend → Plunk → email delivery
- Maintain consistent request IDs in your monitoring tools

## Best Practices

### 1. Always Log Request IDs

```javascript
// ✅ Good: Log request ID for correlation
const response = await plunk.send(email);
const requestId = response.headers.get('X-Request-ID');
logger.info(`Email sent to ${email.to}`, { requestId });
```

```javascript
// ❌ Bad: Discard request ID
await plunk.send(email);
// No way to correlate this with Plunk's logs
```

### 2. Include in Error Reporting

```javascript
// ✅ Good: Include request ID in error reports
try {
  await plunk.send(email);
} catch (error) {
  Sentry.captureException(error, {
    extra: {
      requestId: error.requestId,
      emailTo: email.to
    }
  });
}
```

### 3. Store for Audit Trails

```javascript
// ✅ Good: Store request ID in your database
await db.emailLog.create({
  to: email.to,
  subject: email.subject,
  plunkRequestId: requestId,
  sentAt: new Date()
});
```

### 4. Return to End Users (Optional)

For customer-facing applications, you can show request IDs to users:

```
❌ Error sending email. Please try again.
```

```
❌ Error sending email. Please contact support and provide this reference: a1b2c3d4-e5f6
```

## Monitoring and Observability

Request IDs are essential for:

- **Distributed tracing** - Follow requests across services
- **Error correlation** - Link errors to specific API calls
- **Performance monitoring** - Identify slow requests
- **Debugging production** - Reproduce issues without PII
- **Rate limit tracking** - Monitor usage patterns per project

## FAQ

### Do request IDs expire?

No, request IDs are logged indefinitely (subject to your log retention policy).

### Can I reuse request IDs?

No, each request should have a unique ID. If you send the same request ID twice, logs will be mixed.

### Are request IDs sequential?

No, they are random UUIDs. This prevents information leakage about request volume.

### Can I search by request ID in the dashboard?

This feature is planned but not yet available. For now, contact support with the request ID.

## Related Documentation

- [Error Codes](/api-reference/errors) - Understanding API errors
- [API Reference](/api-reference/overview) - Complete API documentation
- [Troubleshooting](/guides/troubleshooting) - Common issues and solutions
