go-upwork

module
v0.0.0-...-44ff49d Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 1, 2025 License: MIT

README

Upwork Go SDK

GoDoc Go Report Card

go get github.com/rizome-dev/go-upwork

built by: rizome labs

contact us: hi (at) rizome.dev

Quick Start

package main

import (
    "context"
    "fmt"
    "log"
    
    "github.com/rizome-dev/go-upwork/pkg"
)

func main() {
    // Create client configuration
    config := &pkg.Config{
        ClientID:     "your-client-id",
        ClientSecret: "your-client-secret",
        RedirectURL:  "your-redirect-url",
    }
    
    // Create client
    ctx := context.Background()
    client, err := pkg.NewClient(ctx, config)
    if err != nil {
        log.Fatal(err)
    }
    
    // Get authorization URL
    authURL := client.GetAuthURL("state")
    fmt.Println("Visit:", authURL)
    
    // Exchange authorization code for token
    token, err := client.ExchangeCode(ctx, "auth-code")
    if err != nil {
        log.Fatal(err)
    }
    
    // Use the authenticated client
    user, err := client.Users.GetCurrentUser(ctx)
    if err != nil {
        log.Fatal(err)
    }
    
    fmt.Printf("Hello, %s!\n", user.Name)
}

Core Services

Authentication
// OAuth2 Authorization Code Flow
authURL := client.GetAuthURL("state")
token, err := client.ExchangeCode(ctx, "code")

// Refresh token
newToken, err := client.RefreshToken(ctx)

// Service Account (Enterprise)
config.ServiceAccount = true
Users & Organizations
// Get current user
user, err := client.Users.GetCurrentUser(ctx)

// Get user by ID
user, err := client.Users.GetUserByID(ctx, "user-id")

// Get organization
org, err := client.Users.GetOrganization(ctx)

// List companies
companies, err := client.Users.GetCompanySelector(ctx)
Contracts & Milestones
// List contracts
contracts, err := client.Contracts.ListContracts(ctx, api.ListContractsInput{
    Filter: &api.ContractFilter{
        Status: []api.ContractStatus{api.ContractStatusActive},
    },
})

// Create milestone
milestone, err := client.Contracts.CreateMilestone(ctx, api.CreateMilestoneInput{
    ContractID:    "contract-id",
    Description:   "Milestone 1",
    DepositAmount: "1000.00",
    DueDate:       "2024-12-31",
})

// End contract
err = client.Contracts.EndContractAsClient(ctx, api.EndContractInput{
    ContractID: "contract-id",
    Reason:     "Work completed",
})
Job Postings
// Search jobs
jobs, err := client.Jobs.SearchJobs(ctx, api.MarketplaceJobFilter{
    SearchExpression: "golang developer",
    JobType:         api.ContractTypeHourly,
    DaysPosted:      7,
})

// Create job posting
job, err := client.Jobs.CreateJobPosting(ctx, api.CreateJobPostingInput{
    Title:        "Go Developer Needed",
    Description:  "Looking for experienced Go developer",
    CategoryID:   "category-id",
    Skills:       []string{"golang", "api"},
    ContractType: api.ContractTypeHourly,
})
Messaging
// List rooms
rooms, err := client.Messages.ListRooms(ctx, &api.RoomFilter{
    UnreadRoomsOnly: true,
}, nil, api.SortOrderDesc)

// Send message
story, err := client.Messages.SendMessage(ctx, api.CreateStoryInput{
    RoomID:  "room-id",
    Message: "Hello!",
})

// Create room
room, err := client.Messages.CreateRoom(ctx, api.CreateRoomInput{
    RoomName: "Project Discussion",
    RoomType: api.RoomTypeGroup,
    Users: []api.RoomUserInput{
        {UserID: "user1", OrganizationID: "org1"},
        {UserID: "user2", OrganizationID: "org1"},
    },
})
Reports & Analytics
// Get time reports
reports, err := client.Reports.GetTimeReport(ctx, api.TimeReportInput{
    OrganizationID: "org-id",
    DateRange: api.DateRange{
        Start: time.Now().AddDate(0, -1, 0),
        End:   time.Now(),
    },
})

// Get work diary
diary, err := client.Reports.GetWorkDiaryByCompany(ctx, "company-id", "2024-01-15")
Freelancer Profiles
// Search freelancers
results, err := client.Freelancers.SearchFreelancers(ctx, api.SearchFreelancersInput{
    Skills:     []string{"golang", "python"},
    Countries:  []string{"US", "CA"},
    TopRated:   true,
    HourlyRate: &api.RangeFilter{Min: 50, Max: 150},
})

// Get profile
profile, err := client.Freelancers.GetFreelancerProfile(ctx, "profile-key")

Advanced Features

Concurrent Operations
// Batch operations using goroutines
var wg sync.WaitGroup
errors := make(chan error, 3)

wg.Add(3)
go func() {
    defer wg.Done()
    if _, err := client.Users.GetCurrentUser(ctx); err != nil {
        errors <- err
    }
}()

go func() {
    defer wg.Done()
    if _, err := client.Contracts.ListContracts(ctx, input); err != nil {
        errors <- err
    }
}()

go func() {
    defer wg.Done()
    if _, err := client.Messages.ListRooms(ctx, nil, nil, ""); err != nil {
        errors <- err
    }
}()

wg.Wait()
close(errors)
Error Handling
// Check for specific error types
if err != nil {
    var apiErr *errors.APIError
    if errors.As(err, &apiErr) {
        if apiErr.IsRateLimited() {
            // Handle rate limiting
        } else if apiErr.IsUnauthorized() {
            // Refresh token
        }
    }
}
Custom HTTP Client
// Use custom HTTP client with proxy
httpClient := &http.Client{
    Timeout: 60 * time.Second,
    Transport: &http.Transport{
        Proxy: http.ProxyURL(proxyURL),
    },
}

config := &pkg.Config{
    HTTPClient: httpClient,
    // ... other config
}

Configuration

Environment Variables
export UPWORK_CLIENT_ID=your-client-id
export UPWORK_CLIENT_SECRET=your-client-secret
export UPWORK_REDIRECT_URL=http://localhost:8080/callback
Organization Context
// Set default organization
client.SetOrganizationID("org-id")

// Or use per-request context
ctx = context.WithValue(ctx, "org-id", "different-org-id")

Project Structure

go-upwork/
├── pkg/                  # Public API package
│   ├── client.go         # Main client implementation
│   ├── auth/             # OAuth2 authentication
│   ├── errors/           # Error types and handling
│   ├── models/           # Shared data models
│   └── services/         # API service implementations
├── internal/             # Internal packages
│   ├── graphql/          # GraphQL client internals
│   └── ratelimit/        # Rate limiting implementation
├── cmd/upwork-cli/       # CLI tool
├── examples/             # Usage examples
└── docs/                 # Additional documentation

Testing

The SDK includes a comprehensive test suite with unit tests, integration tests, and benchmarks.

Quick Testing
# Run all tests
make test

# Run tests with coverage
make test-coverage

# Run unit tests only
make test-unit

# Run integration tests
make test-integration

# Run with race detector
make test-race

# Run benchmarks
make test-bench
Test Categories
  1. Unit Tests - Test individual components in isolation using mocks
  2. Integration Tests - Test against the real Upwork API (requires credentials)
  3. Race Tests - Detect concurrent access issues
  4. Benchmarks - Performance testing
Coverage Goals
  • Overall Coverage: >80%
  • Critical Paths: 100% (authentication, error handling)
  • Service Layer: >90%
Running Specific Tests
# Run specific test
make test-specific TEST=TestOAuth2

# Test specific package
make test-package PKG=./pkg/services

# With verbose output
go test -v ./pkg/auth/...

# Integration tests (requires API credentials)
go test -tags=integration ./tests/integration/...
Test Environment Setup

For integration tests, set these environment variables:

export UPWORK_CLIENT_ID=your-client-id
export UPWORK_CLIENT_SECRET=your-client-secret
export UPWORK_ACCESS_TOKEN=your-access-token
export UPWORK_REFRESH_TOKEN=your-refresh-token
export UPWORK_ORGANIZATION_ID=your-org-id
Continuous Integration

Tests run automatically on:

  • Pull requests
  • Pushes to main branch
  • Daily schedule

See TESTING.md for detailed testing documentation.

Examples

See the examples directory for more detailed usage examples:

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

License

This project is licensed under the MIT License - see the LICENSE file for details.

Support

Acknowledgments

  • Built with concurrent design patterns for optimal performance
  • Follows Go best practices and idioms
  • Comprehensive GraphQL support for modern API interactions

Directories

Path Synopsis
cmd
upwork-cli command
Package main provides a CLI tool for the Upwork SDK.
Package main provides a CLI tool for the Upwork SDK.
Package main demonstrates basic usage of the Upwork Go SDK
Package main demonstrates basic usage of the Upwork Go SDK
internal
graphql
Package graphql provides internal GraphQL client functionality.
Package graphql provides internal GraphQL client functionality.
ratelimit
Package ratelimit provides rate limiting functionality for the Upwork SDK.
Package ratelimit provides rate limiting functionality for the Upwork SDK.
pkg
Package pkg provides a Go client for the Upwork API.
Package pkg provides a Go client for the Upwork API.
auth
Package auth provides OAuth2 authentication for the Upwork API.
Package auth provides OAuth2 authentication for the Upwork API.
errors
Package errors provides custom error types for the Upwork SDK.
Package errors provides custom error types for the Upwork SDK.
models
Package models contains shared data models for the Upwork SDK.
Package models contains shared data models for the Upwork SDK.
services
Package services provides service clients for the Upwork API.
Package services provides service clients for the Upwork API.
tests

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL