SharpAPI Node Core is the foundational package that powers all SharpAPI Node.js SDK packages. It provides the base service class, HTTP client, job polling, rate limiting, error handling, and shared utilities used across all 30 specialized SharpAPI packages.
- Overview
- Installation
- Architecture
- Core Components
- Rate Limiting & Throttling
- Building Custom Services
- API Documentation
- Testing
- License
The SharpAPI Core package provides:
- Base Service Class:
SharpApiCoreService— foundation for all API services - HTTP Client: Axios-based HTTP client with Bearer token authentication
- Job Polling: Automatic polling for asynchronous API endpoints with adaptive intervals
- Rate Limiting: Two-layer rate limiting — proactive sliding window throttling + reactive 429 retry logic
- Rate Limit Header Tracking: Automatic extraction of
X-RateLimit-LimitandX-RateLimit-Remainingheaders - Error Handling:
SharpApiErrorwith HTTP status codes for timeout and rate limit errors - Type Definitions: Enums for job statuses, languages, and voice tones
- DTO Classes: Data Transfer Objects for API responses (
SharpApiJob,SharpApiSubscriptionInfo)
npm install @sharpapi/sharpapi-node-coreNote: This package is typically installed automatically as a dependency of specialized SharpAPI packages. You only need to install it directly if you're building custom services.
sharpapi-node-core/
├── src/
│ ├── SharpApiCoreService.js # Base service class
│ ├── SlidingWindowRateLimiter.js # Proactive rate limiter
│ ├── Dto/
│ │ ├── SharpApiJob.js # Job DTO
│ │ └── SharpApiSubscriptionInfo.js # Subscription DTO
│ ├── Enums/
│ │ ├── SharpApiJobStatusEnum.js # Job statuses
│ │ ├── SharpApiLanguages.js # Supported languages
│ │ └── SharpApiVoiceTone.js # Voice tone options
│ ├── Exceptions/
│ │ └── SharpApiError.js # Custom error class
│ └── index.js # Package exports
├── __tests__/
│ ├── SharpApiCoreService.test.js # Core service tests
│ └── SlidingWindowRateLimiter.test.js
├── package.json
└── README.md
sharpapi-node-core (base package)
↓
All 30 specialized SharpAPI packages extend core:
├── sharpapi-node-translate
├── sharpapi-node-summarize-text
├── sharpapi-node-detect-emails
├── sharpapi-node-parse-resume
├── sharpapi-node-product-categories
└── ... (25 more)
The base class that all SharpAPI services extend.
Constructor:
const { SharpApiCoreService } = require('@sharpapi/sharpapi-node-core');
const service = new SharpApiCoreService(
apiKey, // Required: your SharpAPI API key
apiBaseUrl = 'https://sharpapi.com/api/v1', // Optional: API base URL
userAgent = 'SharpAPINodeClient/1.3.0' // Optional: custom User-Agent
);Properties (with defaults):
| Property | Default | Description |
|---|---|---|
apiJobStatusPollingInterval |
10 |
Polling interval in seconds |
apiJobStatusPollingWait |
180 |
Maximum polling wait time in seconds |
rateLimitLimit |
null |
Server-reported rate limit (from headers) |
rateLimitRemaining |
null |
Server-reported remaining requests |
maxRetryOnRateLimit |
3 |
Max retries on 429 responses |
rateLimitLowThreshold |
3 |
Remaining count that triggers adaptive polling |
throttleRequests |
true |
Enable proactive sliding window throttling |
requestsPerMinute |
60 |
Requests per minute for sliding window limiter |
Standalone rate limiter that tracks request timestamps in a rolling window.
const { SlidingWindowRateLimiter } = require('@sharpapi/sharpapi-node-core');
const limiter = new SlidingWindowRateLimiter(
maxRequests = 60, // Max requests in window
windowSeconds = 60 // Window duration
);
limiter.canProceed(); // true/false — check without waiting
limiter.remaining(); // Number of slots left
await limiter.waitIfNeeded(); // Block until capacity, returns seconds waited
limiter.adaptFromServerLimit(120); // One-way ratchet up from server headerCustom error class for API and timeout errors.
const { SharpApiError } = require('@sharpapi/sharpapi-node-core');
try {
const job = await service.fetchResults(statusUrl);
} catch (error) {
if (error instanceof SharpApiError) {
console.error(error.message); // "Job polling timed out after 180s"
console.error(error.statusCode); // 408 (timeout) or 429 (rate limited)
}
}const { SharpApiJobStatusEnum } = require('@sharpapi/sharpapi-node-core');
SharpApiJobStatusEnum.NEW // 'new'
SharpApiJobStatusEnum.PENDING // 'pending'
SharpApiJobStatusEnum.SUCCESS // 'success'
SharpApiJobStatusEnum.FAILED // 'failed'80+ supported languages:
const { SharpApiLanguages } = require('@sharpapi/sharpapi-node-core');
SharpApiLanguages.ENGLISH
SharpApiLanguages.SPANISH
SharpApiLanguages.FRENCH
// ... and moreVoice tone options for content generation:
const { SharpApiVoiceTone } = require('@sharpapi/sharpapi-node-core');
SharpApiVoiceTone.PROFESSIONAL
SharpApiVoiceTone.CASUAL
SharpApiVoiceTone.FORMAL
// ... and moreRepresents a completed API job:
const job = await service.fetchResults(statusUrl);
job.getId(); // Job UUID
job.getType(); // e.g. 'content_translate'
job.getStatus(); // 'success' or 'failed'
job.getResultJson(); // Prettified JSON string
job.getResultObject(); // Raw JavaScript objectSubscription details returned by the quota() endpoint:
const info = await service.quota();
info.timestamp // Date
info.on_trial // boolean
info.trial_ends // Date
info.subscribed // boolean
info.current_subscription_start // Date
info.current_subscription_end // Date
info.current_subscription_reset // Date or null
info.subscription_words_quota // number
info.subscription_words_used // number
info.subscription_words_used_percentage // number
info.requests_per_minute // number or nullThe core service implements a two-layer rate limiting architecture mirroring the PHP SDK v1.3.0:
Before every request, the service checks a local sliding window rate limiter. If the window is full, it waits until capacity is available. This prevents hitting 429 errors in the first place.
const service = new SharpApiCoreService(apiKey);
// Configure throttling
service.setRequestsPerMinute(120); // Match your plan's RPM
service.setThrottleRequests(true); // Enabled by default
// The limiter auto-adapts from server headers:
// If X-RateLimit-Limit: 200, the limiter ratchets up to 200If a 429 response is received despite throttling, the service retries with the Retry-After header value:
service.setMaxRetryOnRateLimit(3); // Up to 3 retries (default)When rateLimitRemaining drops below the threshold, polling intervals scale up automatically:
adjustedInterval = baseInterval * (2 + (threshold - remaining))
For example, with threshold=3 and remaining=1:
- Base interval 10s becomes
10 * (2 + 2) = 40s
You can inspect and persist rate limit state across requests:
// Check current state
console.log(service.getRateLimitLimit()); // 100
console.log(service.getRateLimitRemaining()); // 97
console.log(service.canMakeRequest()); // true
// Persist state for external caching
const state = service.getRateLimitState();
// ... later ...
service.setRateLimitState(state);ping() and quota() bypass throttling automatically since they are lightweight health/info endpoints. quota() also adapts requestsPerMinute from the server response when available.
Extend SharpApiCoreService to create custom API integrations:
const { SharpApiCoreService } = require('@sharpapi/sharpapi-node-core');
class MyCustomService extends SharpApiCoreService {
constructor(apiKey, apiBaseUrl = 'https://sharpapi.com/api/v1') {
super(apiKey, apiBaseUrl, 'MyCustomService/1.0.0');
}
async analyzeContent(text) {
const data = { content: text };
const response = await this.makeRequest('POST', '/content/summarize', data);
return this.parseStatusUrl(response);
}
}
// Usage
const service = new MyCustomService(process.env.SHARP_API_KEY);
const statusUrl = await service.analyzeContent('Your text here...');
const job = await service.fetchResults(statusUrl);
console.log(job.getResultJson());All rate limiting, throttling, 429 retry, and header tracking are inherited automatically.
Make HTTP requests to the API. Routes through the rate limit retry wrapper.
method(string):'GET'or'POST'url(string): API endpoint path (relative toapiBaseUrl)data(object, optional): Request body (POST) or query parameters (GET)filePath(string, optional): File path for multipart uploads
Returns: Promise<AxiosResponse>
Convenience method for GET requests.
Poll an async job until completion with adaptive intervals and 429 handling.
statusUrl(string): Job status URL fromparseStatusUrl()
Returns: Promise<SharpApiJob>
Throws: SharpApiError on timeout (408) or rate limit exhaustion (429)
Extract status URL from API response.
response(AxiosResponse): Response frommakeRequest()
Returns: string
Check API availability. Bypasses throttling.
Returns: Promise<object> — { ping: 'pong', timestamp: '...' }
Get subscription details. Bypasses throttling. Adapts requestsPerMinute from server.
Returns: Promise<SharpApiSubscriptionInfo|null>
The core service uses Axios with the following defaults:
- Base URL:
https://sharpapi.com/api/v1 - User-Agent:
SharpAPINodeClient/1.3.0 - Headers:
Authorization:Bearer {apiKey}Accept:application/json
const { SharpApiError } = require('@sharpapi/sharpapi-node-core');
try {
const job = await service.fetchResults(statusUrl);
} catch (error) {
if (error instanceof SharpApiError) {
// Timeout or rate limit error from core
console.error(error.message); // Descriptive message
console.error(error.statusCode); // 408 or 429
} else if (error.response) {
// Other HTTP error from axios
console.error('Status:', error.response.status);
} else {
// Network or other error
console.error('Error:', error.message);
}
}# Run all tests
npm test
# Tests cover:
# - SlidingWindowRateLimiter (8 tests)
# - SharpApiCoreService (34 tests)
# - Constructor & backward compatibility
# - Rate limit header extraction
# - Adaptive polling intervals
# - 429 retry logic
# - fetchResults polling, timeout, and radix fix
# - ping/quota throttle bypass
# - Getter/setter round-trips
# - State serializationAll 30 specialized SharpAPI Node.js packages depend on this core package:
- @sharpapi/sharpapi-node-translate
- @sharpapi/sharpapi-node-summarize-text
- @sharpapi/sharpapi-node-detect-emails
- @sharpapi/sharpapi-node-parse-resume
- @sharpapi/sharpapi-node-product-categories
- ... and 25 more specialized packages
This project is licensed under the MIT License. See the LICENSE.md file for details.
- Documentation: SharpAPI.com Documentation
- Issues: GitHub Issues
- Email: contact@sharpapi.com
Powered by SharpAPI - AI-Powered API Workflow Automation
