ShipPulse
  • Pricing
  • Docs
  • Blog
  • Compare

Product

TestimonialsChangelogStatus PagesFeedbackRoadmapPricing

Resources

DocsBlogAPI ReferenceSDKHelp Center

Company

AboutContact

Legal

TermsPrivacyCookie PolicyDPASub-processors

Product updates

Changelog updates only. Unsubscribe any time.

ShipPulse operated by Igor Bogdanov, Limassol, Cyprus. [email protected]. Cyprus registration number pending — will be published once issued.

ShipPulse

© 2026 ShipPulse. All rights reserved.

OverviewQuick StartCore ConceptsWidget ReferencePlatform GuidesAPI ReferenceAPI PlaygroundError HandlingPaginationRate LimitingJavaScript SDKWebhooksZapier, n8n & MakeCustom DomainsTeam ManagementBilling & PlansNotification ChannelsAI FeaturesOverviewFrom SenjaFrom Testimonial.toFrom HeadwayFrom Canny

Introduction

  • Overview
  • Quick Start
  • Core Concepts

Embed Widgets

  • Widget Reference
  • Platform Guides

REST API

  • API Reference
  • API Playground
  • Error Handling
  • Pagination
  • Rate Limiting

SDK & Webhooks

  • JavaScript SDK
  • Webhooks
  • Zapier, n8n & Make

Guides

  • Custom Domains
  • Team Management
  • Billing & Plans
  • Notification Channels
  • AI Features

Migrations

  • Overview
  • From Senja
  • From Testimonial.to
  • From Headway
  • From Canny

Need help?

[email protected]
API

Rate Limiting

ShipPulse API rate limits are applied per API key using a sliding window algorithm. Limits vary by plan and endpoint group.

Limits by plan

Plan/api/v1/*/api/collect/api/subscribe
FreeNo API access10 req / 10 min5 req / 15 min
StarterNo API access20 req / 10 min5 req / 15 min
Pro100 req / min50 req / 10 min10 req / 15 min
Agency500 req / min200 req / 10 min20 req / 15 min

Need higher limits? Contact us for enterprise quotas.

Rate limit headers

Every API response includes headers showing your current rate limit status:

http
HTTP/1.1 200 OK
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 87
X-RateLimit-Reset: 1714000860
Retry-After: 13   ← only present on 429
HeaderDescription
X-RateLimit-LimitMaximum requests allowed in the current window
X-RateLimit-RemainingRequests remaining in the current window
X-RateLimit-ResetUnix timestamp (seconds) when the window resets
Retry-AfterSeconds to wait before retrying (only on 429 responses)

Handling 429 Too Many Requests

When you receive a 429, always check the Retry-After header and wait that many seconds before retrying. Never retry immediately — you will stay rate-limited.

typescript
async function callWithRateLimitHandling(
  url: string,
  apiKey: string,
  maxRetries = 5,
): Promise<Response> {
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    const res = await fetch(url, {
      headers: { Authorization: `Bearer ${apiKey}` },
    });

    if (res.status !== 429) return res;

    const retryAfter = Number(res.headers.get("Retry-After") ?? 60);
    console.warn(`Rate limited. Retrying in ${retryAfter}s...`);
    await new Promise((r) => setTimeout(r, retryAfter * 1000));
  }

  throw new Error("Max retries exceeded after rate limiting");
}

Best practices

Cache responses

For read-heavy operations (listing testimonials for a public widget), cache the API response on your server or CDN for 60–300 seconds. This dramatically reduces your API usage.

Batch writes

When importing testimonials or creating changelog entries in bulk, batch them in groups of 10–50 with a small delay between batches rather than sending all requests simultaneously.

Use webhooks instead of polling

Instead of polling for new testimonials or incidents, subscribe to webhooks. This eliminates polling traffic entirely. See the Webhooks guide.

Monitor X-RateLimit-Remaining

Log the X-RateLimit-Remaining header in your application. If it consistently drops to single digits, consider upgrading your plan or reducing request frequency.

See also: Error Handling · Webhooks