# API Source: https://docs.getmany.com/api Learn how to automate your workflows with Getmany Service API Getmany offers a comprehensive REST API that enables you to automate your entire Upwork workflow. With our API, you can: * Track proposal & profile analytics (views, replies, costs, response times) * Retrieve jobs feed in real-time * Integrate seamlessly with your existing tools and systems For detailed API documentation, including authentication, rate limits, and available endpoints, please refer to our [API Reference](/api-reference/introduction). # Get Agency Details Source: https://docs.getmany.com/api-reference/endpoint/agency/get GET /v1/agency Returns the complete profile of the single agency linked to the authenticated workspace. # List Agency Invitations Source: https://docs.getmany.com/api-reference/endpoint/agency/invitations GET /v1/agency/invitations Retrieves agency invitations. Supports optional `status` filter and cursor pagination. # List Agency Members Source: https://docs.getmany.com/api-reference/endpoint/agency/members GET /v1/agency/members Retrieves agency members. Supports optional `role` filter and cursor pagination. # Get Agency Proposal Source: https://docs.getmany.com/api-reference/endpoint/agency/proposal GET /v1/agency/proposals/{id} Retrieves agency proposal. # List Agency Proposals Source: https://docs.getmany.com/api-reference/endpoint/agency/proposals GET /v1/agency/proposals Retrieves agency proposals. Supports optional `status` filter and cursor pagination. # Cancel Bid Source: https://docs.getmany.com/api-reference/endpoint/bid-intent/cancel DELETE /v1/bid-intents/{id} Cancels a scheduled bid intent by its ID # List Chat Rooms Source: https://docs.getmany.com/api-reference/endpoint/master-inbox/rooms GET /v1/master-inbox/rooms Returns a paginated list of chat rooms for the workspace's agency. Supports filtering by archived status, search, participants, pipeline stages, client-only messages, and multiple sort modes with cursor-based pagination. # Send a Message Source: https://docs.getmany.com/api-reference/endpoint/master-inbox/send-story POST /v1/master-inbox/rooms/{roomId}/stories Sends a plain-text message to a specific chat room via the Upwork messaging API. Requires an authorized freelancer who is a participant in the room. The workspace must have an active Master Inbox addon subscription, trial, or feature flag. # List Chat Room Stories Source: https://docs.getmany.com/api-reference/endpoint/master-inbox/stories GET /v1/master-inbox/rooms/{roomId}/stories Returns a paginated list of messages (stories) for a specific chat room. Supports cursor-based pagination and optional text search. # Introduction Source: https://docs.getmany.com/api-reference/introduction Understand general concepts, response codes, and authentication strategies. ## Base URL The Resend API is built on **REST** principles. We enforce **HTTPS** in every request to improve data security, integrity, and privacy. The API does not support **HTTP**. All requests contain the following base URL: ``` https://api.getmany.io ``` ## Authentication To authenticate you need to add an *Authorization* header with the contents of the header being `Bearer gm_xxxxxxxxx` where `gm_xxxxxxxxx` is your [API Key](https://app.getmany.io/integrations/api). ``` Authorization: Bearer gm_xxxxxxxxx ``` ## Response codes Resend uses standard HTTP codes to indicate the success or failure of your requests. In general, `2xx` HTTP codes correspond to success, `4xx` codes are for user-related failures, and `5xx` codes are for infrastructure issues. | Status | Description | | ------ | ---------------------------------------- | | `200` | Successful request. | | `400` | Check that the parameters were correct. | | `401` | The API key used was missing. | | `403` | The API key used was invalid. | | `404` | The resource was not found. | | `429` | The rate limit was exceeded. | | `5xx` | Indicates an error with Getmany servers. | ## Rate limit The default maximum rate limit is **20 requests per minute**. This number can be increased for trusted senders by request. After that, you'll hit the rate limit and receive a `429` response error code. # Introduction Source: https://docs.getmany.com/index Getmany is your personal AI Sales Manager for Upwork Agency ## Learn Discover the full range of features and capabilities. Notify your applications and workflows about various events. Integrate with our Service API for advanced use cases. # Event Catalog Source: https://docs.getmany.com/webhooks/event-catalog List of supported event types and their payload. ### `proposal.accepted` Occurs whenever the customer **accepts a proposal on Upwork**. ```json Request data sample icon="file-json" theme={null} { "proposal": { "uid": "cf3e12b821", "coverLetter": "Hi Duja team — I specialise in crafting memorable visual identities for emerging brands. Attached are two recent logo boards that show how I translate a story into colour, typography and iconography that work across print and social. I’d love to iterate on a first concept within 48 hours and can deliver the full brand-style guide in one week.", "status": "SUBMITTED", "createdAt": "2025-06-16T07:45:00Z" }, "job": { "slug": "~021908931246561901733", "title": "Branding Specialist & Logo Design Needed", "description": "Logo Design & Branding Specialist wanted to create a unique logo plus full branding package (brand colours, style guide, banners, social media assets and invitation cards). Must have a strong portfolio, be collaborative and able to translate brand values into compelling visuals.", "createdAt": "2025-04-10T10:00:00Z" }, "freelancer": { "uid": "01921f906821a83980", "name": "Valdas D.", "photoUrl": "https://res.cloudinary.com/upwork-fp/image/upload/profile_photos/public/01921f906821a83980.jpg", "slug": "~01921f906821a83980" }, "manager": { "uid": "0186bf9bc5f75be64d", "name": "Duja Brand Ltd.", "photoUrl": "https://assets.upwork.com/uploads/user/logo/default-logo.png", "slug": "~0186bf9bc5f75be64d" }, "chat": { "id": "123456789" } } ``` ### `chat.message.sent` Occurs whenever the customer **sends you a new message in a conversation**. ```json Request data sample icon="file-json" theme={null} { "proposal": { "uid": "cf3e12b821" }, "message": { "text": "Thanks for reviewing my proposal! Let me know which of the two draft concept directions resonates more and I’ll refine colour and typography tonight." }, "chat": { "id": "123456789" } } ``` ### `bid_intent.scheduled` Occurs whenever Auto-Bidder schedules a bid. ```json Request data sample icon="file-json" theme={null} { "jobUid": "cf3e12b821", "bidId": "cf3e12b821" } ``` # Managing Webhooks Source: https://docs.getmany.com/webhooks/introduction Use webhooks to notify your application about Upwork events. ## What is a webhook? Getmany uses webhooks to push real-time notifications to you about your Upwork activity. All webhooks use HTTPS and deliver a JSON payload that can be used by your application. You can use webhook feeds to do things like: * Update lead status based on changing proposal status * Automatically handle new messages from customers ## Steps to receive webhooks You can start receiving real-time events in your app using the steps: 1. Create a local endpoint to receive requests 2. Register your development webhook endpoint 3. Test that your webhook endpoint is working properly 4. Deploy your webhook endpoint to production 5. Register your production webhook endpoint ### 1. Create a local endpoint to receive requests In your local application, create a new route that can accept POST requests. For example, you can add an API route on Express.js: ```js index.ts theme={null} import express from 'express'; const HTTP_PORT = 3000; const app = express(); app.use(express.json()); app.post('/webhook', (req, res) => { console.log("request payload", req.body); res.json({ success: true }); }); app.listen(HTTP_PORT, () => { console.log(`Example app listening on port ${HTTP_PORT}`); }); ``` On receiving an event, you should respond with an `HTTP 200 OK` to signal Getmany that the event was successfully delivered. ### 2. Register your development webhook endpoint Register your publicly accessible HTTPS URL in the Getmany dashboard. You can create a tunnel to your localhost server using a tool like [ngrok](https://ngrok.com/download). For example: `https://8733-191-204-177-89.sa.ngrok.io/api/webhooks` ### 3. Test that your webhook endpoint is working properly Send a few test emails to check that your webhook endpoint is receiving the events. ### 4. Deploy your webhook endpoint After you're done testing, deploy your webhook endpoint to production. ### 5. Register your production webhook endpoint Once your webhook endpoint is deployed to production, you can register it in the Getmany dashboard. ## FAQ If Getmany does not receive a 200 response from a webhook server, we will retry the webhooks. Each message is attempted based on the following schedule, where each period is started following the failure of the preceding attempt: * 5 seconds * 5 minutes * 30 minutes * 2 hours * 5 hours * 10 hours After the conclusion of the above attempts the message will be marked as failed, and you will get a webhook of type `message.attempt.exhausted` notifying you of this error. If your server requires an allowlist, our webhooks come from the following IP addresses: * `52.215.16.239` * `54.216.8.72` * `63.33.109.123` * `2a05:d028:17:8000::/56` # Verify Webhooks Requests Source: https://docs.getmany.com/webhooks/request-validation Learn how to use the signing secret to verify your webhooks. ## Why should I verify webhooks? Webhooks are vulnerable because attackers can send fake HTTP POST requests to endpoints, pretending to be legitimate services. This can lead to security risks or operational issues. To mitigate this, each webhook and its metadata are signed with a unique key specific to the endpoint. This signature helps verify the source of the webhook, allowing only authenticated webhooks to be processed. Another security concern is replay attacks, where intercepted valid payloads, complete with their signatures, are resent to endpoints. These payloads would pass the signature verification and be executed, posing a potential security threat. ## Verify webhooks in your app To verify the webhook request, you have to use the secret and deconstruct the Svix headers, and Base64-decode the Getmany secret. The example below is for Javascript. [Learn more and view all supported languages here.](https://docs.svix.com/receiving/verifying-payloads/how) First, install the Svix libraries. ```sh npm theme={null} npm install svix ``` ```sh yarn theme={null} yarn add svix ``` ```sh pnpm theme={null} pnpm add svix ``` Then, verify the webhooks using the code below. The payload is the raw (string) body of the request, and the headers are the headers passed in the request. Make sure that you're using the raw request body when verifying webhooks, since the cryptographic signature is sensitive to even the slightest change. Watch out for frameworks that parse the request as JSON and then stringify it, since this too will break the signature verification. ```js theme={null} import { Webhook } from 'svix'; const secret = process.env.WEBHOOK_SECRET; // These were all sent from the server const headers = { 'svix-id': 'msg_p5jXN8AQM9LWM0D4loKWxJek', 'svix-timestamp': '1614265330', 'svix-signature': 'v1,g0hM9SsE+OTPJTGt/tmIKtSyZlE3uFJELVlNIOLJ1OE=', }; const payload = '{"test": 2432232314}'; const wh = new Webhook(secret); // Throws on error, returns the verified content on success wh.verify(payload, headers); ``` If you prefer, you can also [manually verify the headers as well.](https://docs.svix.com/receiving/verifying-payloads/how-manual)