https://github.com/rizome-dev/go-upwork
pure go upwork.com sdk
https://github.com/rizome-dev/go-upwork
golang sdk upwork
Last synced: 21 days ago
JSON representation
pure go upwork.com sdk
- Host: GitHub
- URL: https://github.com/rizome-dev/go-upwork
- Owner: rizome-dev
- License: mit
- Created: 2025-06-26T01:17:34.000Z (about 1 year ago)
- Default Branch: main
- Last Pushed: 2025-07-01T21:03:47.000Z (about 1 year ago)
- Last Synced: 2025-11-09T02:17:31.869Z (8 months ago)
- Topics: golang, sdk, upwork
- Language: Go
- Homepage: https://pkg.go.dev/github.com/rizome-dev/go-upwork
- Size: 199 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Upwork Go SDK
[](https://pkg.go.dev/github.com/rizome-dev/go-upwork)
[](https://goreportcard.com/report/github.com/rizome-dev/go-upwork)
```shell
go get github.com/rizome-dev/go-upwork
```
built by: [rizome labs](https://rizome.dev)
contact us: [hi (at) rizome.dev](mailto:hi@rizome.dev)
## Quick Start
```go
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
```go
// 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
```go
// 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
```go
// 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
```go
// 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
```go
// 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
```go
// 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
```go
// 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
```go
// 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
```go
// 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
```go
// 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
```bash
export UPWORK_CLIENT_ID=your-client-id
export UPWORK_CLIENT_SECRET=your-client-secret
export UPWORK_REDIRECT_URL=http://localhost:8080/callback
```
### Organization Context
```go
// 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
```bash
# 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
```bash
# 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:
```bash
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](TESTING.md) for detailed testing documentation.
## Examples
See the [examples](examples/) directory for more detailed usage examples:
- [Basic Usage](examples/basic_usage.go) - Authentication and basic operations
- [Concurrent Operations](examples/concurrent.go) - Parallel API calls
- [Job Management](examples/jobs.go) - Creating and managing job postings
- [Messaging](examples/messaging.go) - Room and message management
- [Reports](examples/reports.go) - Analytics and reporting
## 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](LICENSE) file for details.
## Support
- 📖 [API Documentation](https://www.upwork.com/developer/documentation/graphql/api/docs/index.html)
- 💬 [Stack Overflow](https://stackoverflow.com/questions/tagged/upwork-api)
- 🐛 [Issue Tracker](https://github.com/rizome-dev/go-upwork/issues)
## Acknowledgments
- Built with concurrent design patterns for optimal performance
- Follows Go best practices and idioms
- Comprehensive GraphQL support for modern API interactions