@muhammedaksam/upwork-node
v1.0.0
Published
Modern Node.js client for Upwork API v2 with OAuth2 and GraphQL support
Maintainers
Readme
Upwork Node.js Client
Modern TypeScript/Node.js client for the Upwork API v2 with OAuth2 and GraphQL support.
⚠️ Disclaimer: This is an unofficial client library. This project is not affiliated with, endorsed by, or supported by Upwork. "Upwork" is a trademark of Upwork Global Inc. Use of the Upwork API through this library is subject to Upwork's API Terms of Use.
Features
- ✅ OAuth2 Authentication - Full support for all OAuth2 grant types
- ✅ GraphQL API - Native GraphQL client with type-safe operations
- ✅ TypeScript - Written in TypeScript with full type definitions
- ✅ Modern & Async - Built with async/await and Promises
- ✅ Easy to Use - High-level API wrappers for common operations
- ✅ Automatic Token Refresh - Handles token expiration automatically
Installation
# Using pnpm (recommended)
pnpm add @muhammedaksam/upwork-node
# Using npm
npm install @muhammedaksam/upwork-node
# Using yarn
yarn add @muhammedaksam/upwork-nodePrerequisites
Before using this library, you need to:
- Create an Upwork account
- Register your application at Upwork API Settings
- Get your
Client IDandClient Secret - Set up a redirect URI for OAuth2 callback
Quick Start
1. Initialize the Client
import { UpworkClient } from "@muhammedaksam/upwork-node"
const client = new UpworkClient({
clientId: "YOUR_CLIENT_ID",
clientSecret: "YOUR_CLIENT_SECRET",
redirectUri: "http://localhost:3000/callback",
})2. Authenticate Using Authorization Code Flow
// Step 1: Generate authorization URL
const authUrl = client.auth.getAuthorizationUrl({
state: "random-state-string",
scope: "openid profile",
})
console.log("Visit this URL to authorize:", authUrl)
// Step 2: User authorizes and is redirected to your callback URL
// Extract the 'code' parameter from the callback URL
// Step 3: Exchange code for access token
const tokenResponse = await client.auth.getAccessToken(code)
console.log("Access Token:", tokenResponse.access_token)3. Make API Calls
// Get current user information
const user = await client.users.getMe()
console.log("User:", user.data)
// Search for jobs
const jobs = await client.jobs.searchJobs({
query: "Node.js developer",
limit: 10,
})
console.log("Jobs:", jobs.data)
// Get contracts
const contracts = await client.contracts.getContracts({ limit: 20 })
console.log("Contracts:", contracts.data)Authentication Methods
Authorization Code Grant (Recommended for Web Apps)
// Generate authorization URL
const authUrl = client.auth.getAuthorizationUrl({
state: "csrf-protection-string",
})
// After user authorizes, exchange code for token
const tokens = await client.auth.getAccessToken(authorizationCode)Client Credentials Grant (For Server-to-Server)
const tokens = await client.auth.getClientCredentialsToken({
scope: "your-scopes",
})Refresh Token Grant
// Automatically handled by the library
const newTokens = await client.auth.refreshAccessToken()
// Or manually with a specific refresh token
const newTokens = await client.auth.refreshAccessToken(refreshToken)Using Existing Tokens
// If you already have tokens stored
client.auth.setAccessToken(
"your_access_token",
"your_refresh_token",
3600 // expires_in seconds
)API Reference
Jobs API
// Get a specific job posting
const job = await client.jobs.getJobPosting("job-id")
// Search for jobs
const jobs = await client.jobs.searchJobs({
query: "Python developer",
limit: 20,
offset: 0,
})
// Create a job posting
const newJob = await client.jobs.createJobPosting({
title: "Looking for Node.js Developer",
description: "We need an experienced developer...",
// ... other fields
})
// Update a job posting
const updated = await client.jobs.updateJobPosting("job-id", {
title: "Updated Title",
})Users & Profiles API
// Get current user
const user = await client.users.getMe()
// Get organization
const org = await client.users.getOrganization("org-id")
// Get freelancer profile
const profile = await client.users.getFreelancerProfile("profile-key")Contracts & Offers API
// Get contract details
const contract = await client.contracts.getContract("contract-id")
// List contracts
const contracts = await client.contracts.getContracts({
limit: 10,
offset: 0,
})
// End a contract (freelancer)
const result = await client.contracts.endContract("contract-id", "Project completed")
// Create an offer
const offer = await client.contracts.createOffer({
// offer details
})Proposals API
// Get freelancer proposals
const proposals = await client.proposals.getProposals({ limit: 20 })
// Get client proposals
const clientProposals = await client.proposals.getClientProposals()Metadata API
// Get countries
const countries = await client.metadata.getCountries()
// Get time zones
const timeZones = await client.metadata.getTimeZones()
// Search skills
const skills = await client.metadata.getSkills({
query: "javascript",
limit: 10,
})Search API
// Search freelancers
const freelancers = await client.search.searchFreelancers({
query: "React developer",
limit: 20,
})Custom GraphQL Queries
You can execute custom GraphQL queries directly:
const query = `
query GetCustomData($id: ID!) {
jobPosting(id: $id) {
id
title
description
createdDateTime
}
}
`
const result = await client.graphql.query(query, { id: "job-id" })
console.log(result.data)Custom Mutations
const mutation = `
mutation UpdateJobPosting($id: ID!, $input: JobPostingUpdateRequest!) {
updateJobPosting(id: $id, input: $input) {
jobPosting {
id
title
}
}
}
`
const result = await client.graphql.mutate(mutation, {
id: "job-id",
input: { title: "New Title" },
})Organization ID (Enterprise Features)
For enterprise features, you can set the organization ID:
// Set during client initialization
const client = new UpworkClient(
{
clientId: "YOUR_CLIENT_ID",
clientSecret: "YOUR_CLIENT_SECRET",
},
{
organizationId: "your-org-id",
}
)
// Or set it later
client.graphql.setOrganizationId("your-org-id")
// Or override per request
await client.graphql.query(query, variables, {
organizationId: "specific-org-id",
})Error Handling
try {
const result = await client.jobs.searchJobs({ query: "developer" })
console.log(result.data)
} catch (error) {
if (error.graphqlErrors) {
// GraphQL errors
console.error("GraphQL Errors:", error.graphqlErrors)
} else if (error.status) {
// HTTP errors
console.error(`HTTP Error ${error.status}:`, error.message)
} else {
// Other errors
console.error("Error:", error.message)
}
}TypeScript Support
This library is written in TypeScript and includes full type definitions:
import {
AuthConfig,
GraphQLResponse,
TokenResponse,
UpworkAuth,
UpworkClient,
UpworkGraphQLClient,
} from "@muhammedaksam/upwork-node"Examples
Check out the examples directory for complete working examples:
examples/basic-usage.ts- Complete Express.js OAuth2 flowexamples/generated-client-usage.ts- Using auto-generated types
# Copy the example environment file
cp .env.example .env
# Edit .env with your credentials
# Then run the example
npm run exampleCode Generation
This library includes tools to automatically generate TypeScript types and methods from the Upwork GraphQL schema.
Auto-Generate Full Type Support
You have two options to generate complete type definitions and API methods:
Option 1: From Live API (Requires Access Token)
# Set your access token
export UPWORK_ACCESS_TOKEN=your_token
# Generate complete types and methods
npm run generateThis will create:
src/generated/schema.json- Full GraphQL schemasrc/generated/generated-types.ts- All TypeScript types (642+ types)src/generated/generated-queries.ts- All query methods (75+ queries)src/generated/generated-mutations.ts- All mutation methods (52+ mutations)
Option 2: Extract from Documentation HTML
# Extract operation names and type names from docs
npm run extract:htmlThis generates a scaffold with:
src/generated/OPERATIONS.md- Complete list of all 127 operationssrc/generated/extracted-methods.ts- Method scaffolds for all operationssrc/generated/extracted-types.ts- Type name scaffolds for all 642 types
Currently Supported Operations
The library manually implements the most commonly used operations. After running code generation, you'll have access to ALL 127 operations including:
Queries (75): jobPosting, marketplaceJobPostings, contract, user, freelancerProfile, proposals, timeReport, and 68 more...
Mutations (52): createJobPosting, updateJobPosting, createOffer, endContract, createMilestone, and 47 more...
See src/generated/OPERATIONS.md for the complete list after extraction.
API Documentation
For detailed information about the Upwork API and available scopes, visit:
- Upwork API Documentation
- GraphQL API Reference
- OAuth2 Scopes Reference - Complete list of all available scopes
Development
Prerequisites
- Node.js >= 14.0.0
- pnpm >= 8.0.0 (recommended) or npm/yarn
Setup
# Install dependencies
pnpm install
# Run type checking
pnpm run typecheck
# Run linting
pnpm run lint
# Fix linting issues
pnpm run lint:fix
# Format code
pnpm run format
# Check formatting
pnpm run format:check
# Run all checks
pnpm run checkBuild
pnpm run buildWatch Mode
pnpm run build:watchRun Tests
pnpm testContributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
This library is released under the MIT License - see the LICENSE file for details.
Important: This is a client library wrapper. Your use of the Upwork API itself is governed by Upwork's API Terms of Use. By using this library to access the Upwork API, you agree to comply with:
The MIT license applies to this client library code only, not to the Upwork API or its data.
Author
Muhammed Mustafa AKŞAM
- GitHub: @muhammedaksam
- Email: [email protected]
Changelog
For detailed changes and migration guide from OAuth1 libraries, see CHANGELOG.md
Support
If you have any questions or need help:
- Open an issue on GitHub
- Check the Upwork API Documentation
- Review the Quick Start Guide
- See OAuth2 Scopes Reference for permission details
Acknowledgments
This library is a modern TypeScript implementation for the Upwork API v2, built to support OAuth2 and GraphQL. It's designed as a complete solution for developers who need to integrate with Upwork's platform.
