UpHunt - AI-Powered Freelance Job Platform
UpHunt
Back to Blog
3 months ago·8 min read

U

UpHunt Team

Upwork Apply API: How to Submit Proposals Programmatically in 2026

If you've ever searched for an Upwork API to submit proposals, you already know the answer: it doesn't exist. Upwork's public API lets you search jobs and read profile data, but it deliberately excludes the one action freelancers care about most — applying to jobs.

That's the gap UpHunt fills. With a single REST endpoint, you can submit Upwork proposals programmatically, complete with a custom cover letter, hourly rate, fixed bid, and timeline — no browser, no manual clicking.

Why Upwork Doesn't Offer a Proposal API

Upwork has never exposed a public endpoint for submitting proposals. Their API documentation covers authentication, user profiles, job search, and reporting — but the application flow is intentionally locked behind their web UI.

The reasons are straightforward:

  • Spam prevention — An open apply endpoint would invite mass-application bots.
  • Platform control — Upwork wants freelancers inside their interface, seeing upsells like Connects boosting and featured proposals.
  • Quality gatekeeping — Forcing manual applications is supposed to keep proposal quality high (though anyone who has hired on Upwork knows that's debatable).

For individual freelancers clicking through the UI, this is fine. But for agencies, developers, and power users who want to build automated workflows — generate a cover letter with AI, filter jobs by custom criteria, apply in seconds — the lack of an API is a hard blocker.

UpHunt's Auto-Apply API: The Missing Piece

UpHunt provides the REST API that Upwork won't. Here's what it looks like in practice:

curl -X POST https://uphunt.io/api/auto-apply/external \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  -d '{
    "jobId": "~1234567890abcde",
    "coverLetter": "Hi, I noticed you need a React developer...",
    "profileId": "PROFILE_ID",
    "applicationOptions": {
      "hourlyRate": 55,
      "fixedBid": 1500,
      "timeline": "1 to 3 months",
      "boostBids": 0
    },
    "autoFillOtherQuestions": true
  }'

That's it. One POST request and your proposal is queued and submitted to Upwork.

What You Can Control

| Parameter | Description | |-----------|-------------| | jobId | The Upwork job ciphertext (starts with ~, same as in Upwork URLs) | | coverLetter | Your proposal text — generate it with GPT, Claude, or write it yourself | | profileId | Which Upwork profile to apply with (default or specialized) | | hourlyRate | Your proposed hourly rate | | fixedBid | Your fixed-price bid amount | | timeline | Project duration estimate | | boostBids | Extra Connects to boost visibility | | autoFillOtherQuestions | Let AI handle additional screening questions |

Response

{
  "success": true,
  "queueId": "queue_abc",
  "creditsRemaining": 42,
  "message": "Job queued for auto-apply via API key."
}

You also get a status endpoint to track whether the application went through:

GET /api/auto-apply/external/status?jobId=~1234567890abcde
{
  "jobId": "~1234567890abcde",
  "applicationStatus": "applied",
  "applicationStatusMessage": "Successfully applied via auto-apply (via api)",
  "appliedAt": 1732204800000,
  "errorMessage": null
}

How It Actually Works

UpHunt isn't just proxying an undocumented Upwork endpoint. The system works like this:

  1. You connect your Upwork account to UpHunt (one-time setup via the dashboard).
  2. UpHunt monitors Upwork for new jobs matching your configured feeds — keywords, categories, budget ranges, client history, and more.
  3. When a matching job appears, UpHunt can notify you via webhook, Slack, or Telegram — including the jobId you need for the API.
  4. You call the Auto-Apply API with the jobId, your cover letter, and application options.
  5. UpHunt submits the proposal on your behalf through your connected Upwork account.

The key insight: UpHunt handles the browser-level interaction with Upwork so your code never has to. You get a clean REST interface; UpHunt handles the complexity behind the scenes.

Real-World Use Cases

1. Fully Automated Apply Pipeline

The most common pattern: combine UpHunt's webhook notifications with the Auto-Apply API to build a fully automated pipeline.

// Your webhook endpoint receives job notifications from UpHunt
app.post('/uphunt-webhook', async (req, res) => {
  const job = req.body;

  // Your custom filtering logic
  if (job.matchingScore < 80) return res.json({ skip: true });
  if (job.budget < 500) return res.json({ skip: true });

  // Generate a cover letter with your preferred AI
  const coverLetter = await generateCoverLetter({
    jobTitle: job.title,
    jobDescription: job.description,
    mySkills: ['React', 'Node.js', 'TypeScript']
  });

  // Apply via UpHunt API
  const response = await fetch('https://uphunt.io/api/auto-apply/external', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-api-key': process.env.UPHUNT_API_KEY
    },
    body: JSON.stringify({
      jobId: job.jobId,
      profileId: 'YOUR_PROFILE_ID',
      coverLetter,
      applicationOptions: {
        hourlyRate: 55,
        timeline: '1 to 3 months'
      },
      autoFillOtherQuestions: true
    })
  });

  const result = await response.json();
  console.log(`Applied to "${job.title}": ${result.success}`);
  res.json({ applied: result.success });
});

2. Agency Bulk Apply

If you run an Upwork agency, you can use the List Freelancers endpoint to get all your team members and their profiles, then route jobs to the right person:

GET /api/auto-apply/external/freelancers
{
  "freelancers": [
    {
      "id": "FREELANCER_1",
      "name": "Alice Chen",
      "profiles": [
        { "type": "default", "name": "Default Profile", "profileId": "P1" },
        { "type": "specialization", "name": "React Developer", "profileId": "P2" }
      ]
    },
    {
      "id": "FREELANCER_2",
      "name": "Bob Smith",
      "profiles": [
        { "type": "default", "name": "Default Profile", "profileId": "P3" }
      ]
    }
  ]
}

Then apply with the right profile for each job:

// Route React jobs to Alice's specialized profile
if (job.skills.includes('React')) {
  await applyWithProfile(job.jobId, 'P2', coverLetter);
}
// Route backend jobs to Bob
else if (job.skills.includes('Node.js')) {
  await applyWithProfile(job.jobId, 'P3', coverLetter);
}

3. n8n / Make.com Integration

Don't want to write code? Use UpHunt webhooks as a trigger in n8n or Make.com, add an AI node to generate proposals, then use an HTTP request node to call the Auto-Apply API. No code required.

4. AI-Powered Proposal Generation

Pair the API with any LLM. Feed the job description into GPT-4, Claude, or your own fine-tuned model, get a tailored cover letter back, and submit it — all in under a second:

import openai
import requests

def apply_to_job(job):
    # Generate proposal with AI
    response = openai.chat.completions.create(
        model="gpt-4",
        messages=[{
            "role": "user",
            "content": f"""Write a concise Upwork proposal for this job:
            Title: {job['title']}
            Description: {job['description']}
            Budget: {job['budget']}
            
            Keep it under 200 words. Be specific and professional."""
        }]
    )
    cover_letter = response.choices[0].message.content

    # Submit via UpHunt API
    result = requests.post(
        "https://uphunt.io/api/auto-apply/external",
        headers={
            "Content-Type": "application/json",
            "x-api-key": UPHUNT_API_KEY
        },
        json={
            "jobId": job["jobId"],
            "coverLetter": cover_letter,
            "profileId": MY_PROFILE_ID,
            "applicationOptions": {
                "hourlyRate": 60
            },
            "autoFillOtherQuestions": True
        }
    )
    return result.json()

Getting Started

Setting up takes about 5 minutes:

  1. Sign up at uphunt.io and pick a plan that includes Auto-Apply.
  2. Connect your Upwork account from the dashboard.
  3. Create job feeds — define keywords, categories, and filters for the jobs you want to target.
  4. Get your API key from Dashboard → Auto-Apply API & Webhooks.
  5. Set up a webhook URL (optional) to receive real-time job notifications.
  6. Start calling the API — use the jobId from webhooks or from the UpHunt dashboard.

Full API documentation is available at uphunt.io/docs.

API Endpoints at a Glance

| Method | Endpoint | Purpose | |--------|----------|---------| | POST | /api/auto-apply/external | Submit a proposal to an Upwork job | | GET | /api/auto-apply/external/freelancers | List your team members and profiles | | GET | /api/auto-apply/external/status?jobId=... | Check application status |

All endpoints are authenticated via the x-api-key header.

Why Use an API Instead of Manual Apply?

  • Speed — Apply within seconds of a job being posted. Early proposals get 3-5x more views from clients.
  • Scale — Apply to 50+ relevant jobs per day without burning hours on manual submissions.
  • Consistency — Every proposal follows your template and rules. No more rushed, sloppy applications at midnight.
  • Custom logic — Filter by budget, client rating, job category, or any criteria you define in code.
  • AI integration — Generate personalized cover letters for every job automatically.
  • Tracking — Monitor application status programmatically and feed it into your CRM or analytics.

Frequently Asked Questions

Is this against Upwork's terms of service?

UpHunt applies through your own connected Upwork account. You're still using your Connects, your profile, and your cover letters. UpHunt automates the submission process — the same way email clients automate sending emails through Gmail's servers.

How fast are applications submitted?

Applications are queued and typically submitted within 30-60 seconds of your API call.

Can I use this with multiple Upwork accounts?

Yes, agencies can connect multiple team members and use the profileId parameter to apply with the right person for each job.

What happens if I run out of Connects?

The API returns a clear error with status 402 and a message indicating insufficient credits. You can handle this in your code and pause applications until you top up.

Do I need to run UpHunt's job feeds, or can I use my own job source?

You need at least one UpHunt job feed configured, because UpHunt needs to process and index the job before you can apply via the API. The jobId you send must correspond to a job that UpHunt has already seen through your feeds.

Stop Searching for an API That Upwork Won't Build

Upwork has no incentive to give you a proposal API. They want you in their UI, spending Connects through their interface. If you're a developer, agency owner, or automation enthusiast who wants programmatic control over your Upwork applications, UpHunt is the solution.

Get started with UpHunt's Auto-Apply API →

Related Posts