TL;DRIntegrate the AI Humanizer API into Node.js with a single fetch call: POST your text and tone to /v1/humanize and parse the JSON response. Production-ready patterns include AbortController for timeouts, exponential backoff for rate limits, and the batch endpoint for high-volume workloads.

AI Humanizer API: Node.js Integration Guide

Integrating the AI Humanizer API into your Node.js application is straightforward and opens up powerful possibilities for transforming AI-generated text into naturally human writing. This guide walks you through everything you need to know, from npm setup to production deployment.

Getting Started with npm

First, install the necessary dependencies. You’ll need a package to make HTTP requests. We recommend axios for its simplicity and reliability, though node-fetch works just as well if you prefer the Fetch API.

npm install axios dotenv
npm install --save-dev typescript @types/node ts-node

Create a .env file in your project root to store your API key securely.

HUMANIZER_API_KEY=your_api_key_here
HUMANIZER_API_URL=https://api.aihumanizerapi.com/v1

Fetch vs Axios: Which Should You Use?

Both work well, but here’s how they compare. Axios provides automatic JSON serialization and built-in timeout support, making it slightly easier for beginners. Fetch is now native to Node.js 18+ and requires no external dependencies if you prefer minimal overhead.

For this guide, we’ll use axios, but the patterns work with either approach. The choice depends on your project’s existing dependencies and your comfort level with promises.

Basic API Call with Axios

Here’s a simple function to humanize text using axios.

import axios from 'axios';

async function humanizeText(text: string): Promise {
  try {
    const response = await axios.post(
      `${process.env.HUMANIZER_API_URL}/humanize`,
      { text },
      {
        headers: {
          'Authorization': `Bearer ${process.env.HUMANIZER_API_KEY}`,
          'Content-Type': 'application/json',
        },
        timeout: 30000,
      }
    );
    return response.data.humanized_text;
  } catch (error) {
    console.error('API call failed:', error);
    throw error;
  }
}

Express Middleware Pattern

When building web applications, you’ll often want to create middleware that handles humanization requests consistently. Here’s a production-ready Express middleware pattern.

import express, { Request, Response, NextFunction } from 'express';
import axios from 'axios';

interface HumanizeRequest extends Request {
  text?: string;
}

const humanizeMiddleware = async (
  req: HumanizeRequest,
  res: Response,
  next: NextFunction
) => {
  try {
    if (!req.body.text) {
      return res.status(400).json({ error: 'Text is required' });
    }

    const response = await axios.post(
      `${process.env.HUMANIZER_API_URL}/humanize`,
      { text: req.body.text },
      {
        headers: {
          'Authorization': `Bearer ${process.env.HUMANIZER_API_KEY}`,
          'Content-Type': 'application/json',
        },
        timeout: 30000,
      }
    );

    req.text = response.data.humanized_text;
    next();
  } catch (error) {
    next(error);
  }
};

const app = express();
app.use(express.json());

app.post('/humanize', humanizeMiddleware, (req, res) => {
  res.json({ humanized_text: req.text });
});

TypeScript Types for Type Safety

Using TypeScript types ensures your code is robust and catches errors early. Define clear interfaces for API requests and responses.

interface HumanizeRequest {
  text: string;
  preserve_formatting?: boolean;
  tone?: 'professional' | 'casual' | 'academic';
}

interface HumanizeResponse {
  humanized_text: string;
  original_length: number;
  humanized_length: number;
  processing_time_ms: number;
}

interface ApiError {
  error: string;
  code: string;
  status: number;
}

async function humanizeWithTypes(
  request: HumanizeRequest
): Promise {
  const response = await axios.post(
    `${process.env.HUMANIZER_API_URL}/humanize`,
    request,
    {
      headers: {
        'Authorization': `Bearer ${process.env.HUMANIZER_API_KEY}`,
      },
    }
  );
  return response.data;
}

Streaming Responses for Large Documents

For longer texts, streaming responses helps you display results progressively instead of waiting for the entire response. This improves user experience significantly.

import { createReadStream } from 'fs';

async function humanizeStream(
  text: string,
  onChunk: (chunk: string) => void
): Promise {
  const response = await axios.post(
    `${process.env.HUMANIZER_API_URL}/humanize/stream`,
    { text },
    {
      headers: {
        'Authorization': `Bearer ${process.env.HUMANIZER_API_KEY}`,
      },
      responseType: 'stream',
    }
  );

  response.data.on('data', (chunk: Buffer) => {
    const text = chunk.toString('utf-8');
    onChunk(text);
  });

  return new Promise((resolve, reject) => {
    response.data.on('end', resolve);
    response.data.on('error', reject);
  });
}

// Usage
humanizeStream(myText, (chunk) => {
  console.log('Received chunk:', chunk);
}).catch(console.error);

Error Handling with Exponential Backoff

API calls can fail for various reasons, rate limits, temporary outages, or network issues. Implement exponential backoff to retry failed requests gracefully without overwhelming the service.

interface RetryOptions {
  maxRetries: number;
  initialDelayMs: number;
  maxDelayMs: number;
}

async function humanizeWithRetry(
  text: string,
  options: RetryOptions = {
    maxRetries: 3,
    initialDelayMs: 1000,
    maxDelayMs: 10000,
  }
): Promise {
  let lastError: Error | null = null;

  for (let attempt = 0; attempt <= options.maxRetries; attempt++) {
    try {
      const response = await axios.post(
        `${process.env.HUMANIZER_API_URL}/humanize`,
        { text },
        {
          headers: {
            'Authorization': `Bearer ${process.env.HUMANIZER_API_KEY}`,
          },
          timeout: 30000,
        }
      );
      return response.data.humanized_text;
    } catch (error) {
      lastError = error as Error;

      // Don't retry on client errors (4xx)
      if (axios.isAxiosError(error) && error.response?.status! >= 400 && error.response?.status! < 500) {
        throw error;
      }

      if (attempt < options.maxRetries) {
        const delayMs = Math.min(
          options.initialDelayMs * Math.pow(2, attempt),
          options.maxDelayMs
        );
        await new Promise((resolve) => setTimeout(resolve, delayMs));
      }
    }
  }

  throw lastError || new Error('Failed after max retries');
}

Unit Testing Your Integration

Good tests ensure your integration works reliably. Use jest and axios-mock-adapter to mock API responses without hitting the real service.

import MockAdapter from 'axios-mock-adapter';
import axios from 'axios';
import { humanizeText } from './humanizer';

describe('Humanizer Integration', () => {
  let mock: MockAdapter;

  beforeEach(() => {
    mock = new MockAdapter(axios);
  });

  afterEach(() => {
    mock.reset();
  });

  it('should humanize text successfully', async () => {
    const mockResponse = {
      humanized_text: 'Here is the humanized version.',
    };

    mock.onPost().reply(200, mockResponse);

    const result = await humanizeText('Here is the ai generated text.');
    expect(result).toBe('Here is the humanized version.');
  });

  it('should handle API errors', async () => {
    mock.onPost().reply(429, { error: 'Rate limited' });

    await expect(humanizeText('test')).rejects.toThrow();
  });

  it('should retry on timeout', async () => {
    let attempts = 0;

    mock.onPost().reply(() => {
      attempts++;
      if (attempts < 2) {
        throw new Error('Timeout');
      }
      return [200, { humanized_text: 'Success' }];
    });

    const result = await humanizeWithRetry('test');
    expect(result).toBe('Success');
    expect(attempts).toBe(2);
  });
});

Environment Configuration

Different environments require different configurations. Create a config module to manage this cleanly.

interface Config {
  apiKey: string;
  apiUrl: string;
  timeout: number;
  maxRetries: number;
}

const config: Config = {
  apiKey: process.env.HUMANIZER_API_KEY || '',
  apiUrl: process.env.HUMANIZER_API_URL || 'https://api.aihumanizerapi.com/v1',
  timeout: parseInt(process.env.API_TIMEOUT || '30000', 10),
  maxRetries: parseInt(process.env.MAX_RETRIES || '3', 10),
};

if (!config.apiKey) {
  throw new Error('HUMANIZER_API_KEY environment variable is required');
}

export default config;

Production Deployment Checklist

Before shipping to production, ensure these items are handled.

API Key Management

Use a secrets manager (AWS Secrets Manager, Vault, or your platform's built-in solution). Never commit API keys to version control. Rotate keys regularly.

Rate Limiting

Implement client-side rate limiting to avoid hitting your account limits. Use a library like express-rate-limit for Express applications.

Monitoring

Set up logging for all API calls. Track error rates, response times, and usage metrics. Alert your team when error rates spike.

Caching

Cache humanized results when appropriate. If the same text is humanized multiple times, returning a cached result improves performance and reduces API costs.

Graceful Degradation

Plan for API failures. Should your application return original text, display an error, or queue the request for retry? Design this behavior upfront.

Documentation

Document your integration patterns for your team. Include environment variable setup, error handling expectations, and testing procedures.

// Example deployment checklist
const deploymentChecklist = {
  environment: {
    apiKeySet: !!process.env.HUMANIZER_API_KEY,
    nodeEnv: process.env.NODE_ENV,
    loggingConfigured: !!process.env.LOG_LEVEL,
  },
  integration: {
    retryLogicImplemented: true,
    errorHandlingImplemented: true,
    metricsLogged: true,
  },
  testing: {
    unitTestsPassing: true,
    integrationTestsPassing: true,
    loadTestCompleted: true,
  },
};

Moving Forward

You now have a solid foundation for integrating the AI Humanizer API into your Node.js applications. The patterns shown here scale from simple scripts to complex distributed systems. For more advanced features and integration examples, check our API documentation.

Ready to transform your AI-generated content? Get a free API key and start with 10,000 words per month, no credit card required.

Production patterns for Node.js

The minimal example shows you the shape, but production integrations need a few more pieces: timeout handling, retry logic, environment-aware config, and observability.

With AbortController for clean timeouts

async function humanize(text, tone = 'professional') {
  const controller = new AbortController();
  const timeoutId = setTimeout(() => controller.abort(), 15000);

  try {
    const r = await fetch('https://api.aihumanizerapi.com/v1/humanize', {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${process.env.AIH_API_KEY}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ text, tone }),
      signal: controller.signal,
    });
    if (!r.ok) throw new Error(`HTTP ${r.status}`);
    return await r.json();
  } finally {
    clearTimeout(timeoutId);
  }
}

With retry + exponential backoff

async function humanizeWithRetry(text, tone, maxAttempts = 3) {
  for (let attempt = 1; attempt <= maxAttempts; attempt++) {
    try {
      return await humanize(text, tone);
    } catch (err) {
      if (attempt === maxAttempts) throw err;
      const wait = Math.min(1000 * Math.pow(2, attempt - 1), 8000);
      await new Promise(r => setTimeout(r, wait));
    }
  }
}

Frequently asked questions

Should I use the official SDK or just fetch?

For most teams, plain fetch is fine - fewer dependencies, less surface area. The SDK adds nice ergonomics (typed responses, built-in retry) when you're making many calls across a codebase. Choose based on your team's preference.

How do I handle streaming responses?

The streaming endpoint (/v1/humanize/stream) returns Server-Sent Events. Use a library like eventsource-parser to consume the stream chunk-by-chunk for chat-style UIs. See the API docs for the SSE format.

What's the right concurrency for batch operations?

For sustained throughput, run 5-10 concurrent calls and respect the rate-limit headers. Beyond that, switch to the batch endpoint - it's more efficient than parallelizing single calls.

How do I test integrations locally without burning credits?

The free tier (10K words/month) is enough for development. For unit tests, mock the fetch call - there's no need to hit the live API in tests. The response shape is documented in our docs.

Does this work with Edge runtimes (Vercel Edge, Cloudflare Workers)?

Yes. The API is plain HTTP, so it runs anywhere fetch is available. See our Next.js + Vercel guide for an Edge function example.

Sign up for a free API key to get started.