API Documentation

    Generate introductions programmatically using the IntroMakerAI API, or connect IntroMakerAI to Claude and other AI assistants over MCP. to get an API key.

    Use IntroMakerAI inside Claude (MCP)

    IntroMakerAI runs a remote MCP server, so any AI assistant that speaks MCP can write your introductions for you and save them straight to your library. Claude already knows the context of your conversation, so you can just ask for a bio and it fills in the details.

    Server URL

    https://api.intromakerai.com/mcp

    Transport is streamable HTTP. Authenticate with the same API key as the REST API, sent as an Authorization header.

    Claude Code

    claude mcp add --transport http intromakerai https://api.intromakerai.com/mcp \
      --header "Authorization: Bearer sk_your_api_key_here"

    Claude Desktop, Cursor, and other MCP clients

    Add this to your client's MCP configuration file.

    {
      "mcpServers": {
        "intromakerai": {
          "type": "http",
          "url": "https://api.intromakerai.com/mcp",
          "headers": {
            "Authorization": "Bearer sk_your_api_key_here"
          }
        }
      }
    }

    Available tools

    ToolCostWhat it does
    generate_introduction1 creditWrites an introduction and saves it to your library
    refine_introduction1 creditRewrites one you already have (shorter, more casual, custom instruction)
    get_usageFreeCredits left this period and the date they renew
    save_introductionFreeSaves text you already have to your library
    list_introductionsFreeLists your saved introductions, newest first
    update_introductionFreeEdits the text or title of a saved introduction
    delete_introductionFreePermanently deletes a saved introduction

    Only generate_introduction and refine_introduction spend a credit, and they draw from the same plan allowance as the web app. Everything else is free, so asking Claude to fix a typo or reorder a line costs nothing.

    Authentication

    All API requests require a Bearer token in the Authorization header. You can create API keys from the Settings page.

    Authorization: Bearer sk_your_api_key_here

    POST /api/v1/generate

    Generate a personalized introduction based on the provided input data. The endpoint accepts the same fields used in the app, so any template you can pick in the UI (LinkedIn headline, Twitter/X bio, Instagram bio, TikTok bio, Conference speaker, Podcast guest, Online community, Portfolio about) can be reproduced by sending the matching tone, types.Name, types.Audience, types["Purpose of the introduction"], types["Maximum length?"], and types.CTA values.

    Request body

    FieldTypeRequiredDescription
    inputData.typestringYes"bio" or "community"
    inputData.languagestringYesLanguage for the introduction (e.g. "English", "Spanish")
    inputData.namestringYesPerson's name
    inputData.locationstringNoLocation (city, country)
    inputData.background.fieldsstringNoBrief professional background
    inputData.current_fieldstringNoCurrent professional field
    inputData.projectsstringNoNotable projects
    inputData.passionstringNoPassions and goals
    inputData.achievementsstringNoNotable achievements
    inputData.fun_factstringNoA fun fact about the person
    inputData.types.TypestringNoIntroduction type (e.g. "Bio", "Event - In person")
    inputData.types.NamestringNoWhere it'll be used — e.g. "LinkedIn", "Instagram", "Twitter", "Substack", "TikTok", "Conference"
    inputData.types["Purpose of the introduction"]stringNoGoal of the intro (e.g. "Make recruiters stop and connect")
    inputData.types.AudiencestringNoWho will read it (e.g. "Recruiters and peers on LinkedIn")
    inputData.types["Maximum length?"]stringNoMax length — e.g. "Custom (300 characters)", "Twitter bio (150 characters)", "Instagram bio (150 characters)", "TikTok bio (80 characters)", "Not relevant"
    inputData.types["Describe where are you going to use it"]stringNoExtra context about where this intro will live
    inputData.types.CTAstringNoCall to action to include verbatim at the end
    inputData.tonestringNoVoice — e.g. "Professional", "Casual", "Friendly", "natural"
    inputData.must_includestringNoSpecific points the intro MUST answer or mention (e.g. "Who you are, business name, who you help, how long in business"). Treated as mandatory.

    Response

    {
      "introduction": "Hi, I'm Jane — a software engineer turned AI researcher based in San Francisco. I build open source NLP tools and speak at conferences like PyCon about making AI accessible to everyone. When I'm not coding, I'm probably doing something questionable at high altitude. Let's connect!",
      "intro": "Same as introduction (kept for backward compatibility)"
    }

    POST /api/v1/regenerate

    Rewrite an introduction you already have instead of starting from scratch. This is the same refine flow the app uses, so it keeps the person's voice, preserves their facts and respects the target platform's format and character limit. Costs one credit, refunded if the rewrite fails.

    Pass an id to refine a saved introduction. The original context is rebuilt for you and the person's other introductions are fed in as a style reference, so you don't have to resend anything. To refine loose text instead, send introduction plus inputData.

    Request body

    FieldTypeRequiredDescription
    idstringNo*ID of a saved introduction to refine
    introductionstringNo*Raw text to refine, when you have no saved ID
    adjustmentstringNo**One of shorter, longer, formal, casual, professional, creative
    instructionstringNo**Free-text instruction. Wins over the preset when they conflict
    savebooleanNoOverwrite the saved copy with the result. Needs id. Defaults to false
    inputDataobjectNoGeneration context. Required only when refining raw text with no id

    * Send either id or introduction.
    ** Send at least one of adjustment or instruction.

    Example request

    curl -X POST https://api.intromakerai.com/api/v1/regenerate \
      -H "Content-Type: application/json" \
      -H "Authorization: Bearer YOUR_API_KEY" \
      -d '{
        "id": "abc123",
        "adjustment": "shorter",
        "instruction": "drop the emoji and keep the city",
        "save": true
      }'

    Response

    {
      "introduction": "The rewritten text",
      "revised": "Same as introduction (kept for backward compatibility)",
      "id": "abc123",
      "saved": true
    }

    POST /api/v1/chat

    Conversational generation. Instead of filling in every field up front, you send the conversation so far and the assistant asks for whatever it still needs. When it has enough it writes the introduction and saves it.

    Conversation turns are free. A credit is only spent on the turn that actually produces an introduction, the one that comes back with done: true. A conversation is capped at 25 user turns.

    Request body

    {
      "messages": [
        { "role": "user", "content": "I need a bio for my LinkedIn profile" },
        { "role": "assistant", "content": "Happy to help. What's your name?" },
        { "role": "user", "content": "Jane Smith, I'm an AI engineer in Barcelona" }
      ]
    }

    Send back the messages array from the previous response to continue the conversation.

    Response while still gathering details

    {
      "done": false,
      "reply": "What would you like the bio to highlight?",
      "messages": [ ... ]
    }

    Response when the introduction is ready

    {
      "done": true,
      "reply": "Here's your introduction 👇",
      "introduction": "The generated text",
      "inputData": { ... },
      "messages": [ ... ]
    }

    GET /api/v1/introductions

    Retrieve all your generated introductions (both web and API).

    Query parameters

    ParameterTypeRequiredDescription
    pagenumberNoPage number (default: 1)
    limitnumberNoItems per page (default: 20, max: 100)
    sourcestringNoFilter by source: "api" or "web"

    Example request

    curl https://api.intromakerai.com/api/v1/introductions?page=1&limit=10 \
      -H "Authorization: Bearer YOUR_API_KEY"

    Response

    {
      "introductions": [
        {
          "id": "uuid",
          "title": "Jane Smith Introduction",
          "content": "Hi, I'm Jane — a software engineer...",
          "language": "English",
          "created_at": "2026-03-16T10:30:00Z",
          "source": "api"
        }
      ],
      "pagination": {
        "page": 1,
        "limit": 10,
        "total": 42,
        "total_pages": 5
      }
    }

    GET /api/v1/introductions/:id

    Fetch a single introduction by its ID. Free. You can only read introductions that belong to your account, anything else returns 404.

    Example request

    curl https://api.intromakerai.com/api/v1/introductions/abc123 \
      -H "Authorization: Bearer YOUR_API_KEY"

    Response

    {
      "id": "abc123",
      "title": "Jane Smith Introduction",
      "content": "The introduction text",
      "language": "English",
      "created_at": "2026-07-30T09:21:00.000Z",
      "source": "api"
    }

    POST /api/v1/introductions

    Save an introduction you wrote yourself into your library. Free, no AI runs and no credit is spent. Use this when you already have the text and just want it stored alongside the generated ones.

    Request body

    FieldTypeRequiredDescription
    contentstringYesThe introduction text
    titlestringNoLibrary title. Defaults to "Saved introduction"
    languagestringNoDefaults to "English"
    tonestringNoDefaults to "natural"

    Example request

    curl -X POST https://api.intromakerai.com/api/v1/introductions \
      -H "Content-Type: application/json" \
      -H "Authorization: Bearer YOUR_API_KEY" \
      -d '{
        "title": "Conference bio",
        "content": "I'"'"'m Jane, an AI engineer based in Barcelona."
      }'

    Returns 201 with the saved introduction.

    PATCH /api/v1/introductions/:id

    Update the text (or title) of one of your introductions — handy when you've refined the wording and want to save the final version. You can only update introductions that belong to your account. This does not use AI and does not count against your usage.

    Request body

    FieldTypeRequiredDescription
    contentstringNo*New introduction text
    titlestringNo*New title

    *At least one of content or title is required.

    Example request

    curl -X PATCH https://api.intromakerai.com/api/v1/introductions/abc123 \
      -H "Content-Type: application/json" \
      -H "Authorization: Bearer YOUR_API_KEY" \
      -d '{ "content": "Hey there! I'\''m Celia, based in Taipei..." }'

    Response

    {
      "id": "abc123",
      "title": "Celia Introduction",
      "content": "Hey there! I'm Celia, based in Taipei...",
      "language": "English",
      "source": "web"
    }

    DELETE /api/v1/introductions/:id

    Permanently delete one of your introductions by its ID. You can only delete introductions that belong to your account. Get the id from GET /api/v1/introductions.

    Path parameters

    ParameterTypeRequiredDescription
    idstringYesThe ID of the introduction to delete

    Example request

    curl -X DELETE https://api.intromakerai.com/api/v1/introductions/abc123 \
      -H "Authorization: Bearer YOUR_API_KEY"

    Response

    {
      "success": true,
      "id": "abc123"
    }

    GET /api/v1/usage

    Check how many introduction credits are left in the current period and when the allowance renews. This endpoint is free, it never spends a credit. Use it before generating in a script so you can stop cleanly instead of hitting a 403.

    Example request

    curl https://api.intromakerai.com/api/v1/usage \
      -H "Authorization: Bearer YOUR_API_KEY"

    Response

    {
      "used": 3,
      "limit": 50,
      "remaining": 47,
      "renews_at": "2026-08-14T09:21:00.000Z",
      "plan": "paid"
    }

    Response fields

    FieldTypeDescription
    usednumberIntroductions generated in the current period
    limitnumberTotal allowance for the period
    remainingnumberCredits still available, never negative
    renews_atstringISO date when the allowance resets to zero
    planstring"free" or "paid"

    The renewal cycle is monthly, anchored to your purchase date on a paid plan and to your signup date on the free plan.

    What costs a credit

    Only calls that actually run the AI spend a credit. Reading, editing and organising your library is always free, and a credit is refunded automatically if the AI call fails, so a transient error never costs you anything.

    EndpointCost
    POST /api/v1/generate1 credit
    POST /api/v1/regenerate1 credit
    POST /api/v1/chat1 credit, only on the turn that returns an introduction
    GET /api/v1/usageFree
    GET /api/v1/introductionsFree
    GET /api/v1/introductions/:idFree
    POST /api/v1/introductionsFree
    PATCH /api/v1/introductions/:idFree
    DELETE /api/v1/introductions/:idFree

    Rate Limits

    API keys are limited to 100 requests per day. If you need a higher limit, contact us.

    Examples

    cURL

    curl -X POST https://api.intromakerai.com/api/v1/generate \
      -H "Content-Type: application/json" \
      -H "Authorization: Bearer YOUR_API_KEY" \
      -d '{
        "inputData": {
          "type": "Bio",
          "language": "English",
          "name": "Jane Smith",
          "location": "San Francisco",
          "background": { "fields": "Software engineer with 5 years of experience" },
          "current_field": "AI & Machine Learning",
          "projects": "Open source NLP tools",
          "passion": "Making AI accessible to everyone",
          "achievements": "Speaker at PyCon, 10k GitHub stars",
          "fun_fact": "I once debugged code while skydiving",
          "tone": "Professional",
          "must_include": "Who I am, the name of my business, who I help, how long I have been in business",
          "types": {
            "Name": "LinkedIn",
            "Purpose of the introduction": "Make recruiters and peers stop, read, and connect with me",
            "Audience": "LinkedIn visitors — recruiters, peers, potential collaborators",
            "Maximum length?": "Custom (220 characters)",
            "Describe where are you going to use it": "LinkedIn profile headline",
            "CTA": "Let\'s connect!"
          }
        }
      }'

    JavaScript

    const response = await fetch(
      "https://api.intromakerai.com/api/v1/generate",
      {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          "Authorization": "Bearer YOUR_API_KEY",
        },
        body: JSON.stringify({
          inputData: {
            type: "Bio",
            language: "English",
            name: "Jane Smith",
            location: "San Francisco",
            background: { fields: "Software engineer with 5 years of experience" },
            current_field: "AI & Machine Learning",
            projects: "Open source NLP tools",
            passion: "Making AI accessible to everyone",
            achievements: "Speaker at PyCon, 10k GitHub stars",
            fun_fact: "I once debugged code while skydiving",
            tone: "Professional",
            must_include: "Who I am, the name of my business, who I help, how long I have been in business",
            types: {
              "Name": "LinkedIn",
              "Purpose of the introduction": "Make recruiters and peers stop, read, and connect with me",
              "Audience": "LinkedIn visitors — recruiters, peers, potential collaborators",
              "Maximum length?": "Custom (220 characters)",
              "Describe where are you going to use it": "LinkedIn profile headline",
              "CTA": "Let's connect!",
            },
          },
        }),
      }
    );
    
    const data = await response.json();
    console.log(data.introduction); // Your generated introduction

    Python

    import requests
    
    response = requests.post(
        "https://api.intromakerai.com/api/v1/generate",
        headers={
            "Content-Type": "application/json",
            "Authorization": "Bearer YOUR_API_KEY",
        },
        json={
            "inputData": {
                "type": "Bio",
                "language": "English",
                "name": "Jane Smith",
                "location": "San Francisco",
                "background": {"fields": "Software engineer with 5 years of experience"},
                "current_field": "AI & Machine Learning",
                "projects": "Open source NLP tools",
                "passion": "Making AI accessible to everyone",
                "achievements": "Speaker at PyCon, 10k GitHub stars",
                "fun_fact": "I once debugged code while skydiving",
                "tone": "Professional",
                "must_include": "Who I am, the name of my business, who I help, how long I have been in business",
                "types": {
                    "Name": "LinkedIn",
                    "Purpose of the introduction": "Make recruiters and peers stop, read, and connect with me",
                    "Audience": "LinkedIn visitors — recruiters, peers, potential collaborators",
                    "Maximum length?": "Custom (220 characters)",
                    "Describe where are you going to use it": "LinkedIn profile headline",
                    "CTA": "Let's connect!",
                },
            }
        },
    )
    
    data = response.json()
    print(data["introduction"])  # Your generated introduction

    Error Codes

    StatusDescription
    401Missing or invalid API key
    429Rate limit exceeded (100 requests/day)
    400Missing required fields (inputData)
    404Introduction not found (or not owned by your account)
    500Server error during generation