POST /api/v2/conversations/calls returns 403 when initiating outbound call for agent

Trying to kick off an outbound call on behalf of a logged-in agent using the Conversations API. The goal is to bypass the dialer and just fire a direct call from our custom integration.

We’re using the Genesys Cloud Python SDK. The agent is authenticated via OAuth2 client credentials, and we’ve verified the user has the calls:outbound permission set.

Here’s the snippet:

from genesyscloud import ConversationApi

conv_api = ConversationApi(config)
call_request = {
 "from": {
 "phoneNumber": "+15550199",
 "name": "Support Line"
 },
 "to": [
 {
 "phoneNumber": "+15550123",
 "name": "Customer"
 }
 ],
 "wrapUpCode": "12345",
 "queueId": "abc-123-xyz"
}

try:
 response = conv_api.post_conversations_calls(body=call_request)
 print(f"Call initiated: {response.id}")
except Exception as e:
 print(f"Error: {e}")

The API throws a 403 Forbidden immediately. The error message is generic: Access denied. I’ve checked the role assignments on the agent side and the service account side. Both have calls:outbound and calls:manage.

Is there a specific header or context we’re missing? Or does this endpoint strictly require the caller to be an agent with an active login session rather than a service account token? The docs are light on the auth requirements for this specific POST method.

The 403 is almost certainly a scope issue. calls:outbound isn’t a standard OAuth scope. You need conversation:write and user:read. Also, client credentials grants don’t map to a specific user context by default, so the API doesn’t know which agent is making the call. You have to pass the x-genesys-user-id header or use the impersonation grant type. Here’s the corrected Python setup:

from genesyscloud.conversations_api import ConversationsApi
from genesyscloud.model import CallCreateBody, CallTo

# Ensure your token has 'conversation:write' scope
api_instance = ConversationsApi(platform_client)

# Define the target
to = CallTo(to_type="phone_number", address="+15550199888")
body = CallCreateBody(to=to, from_address="+15550199889")

# Critical: Set the header to impersonate the specific agent
headers = {
 "x-genesys-user-id": "agent-uuid-here"
}

try:
 api_response = api_instance.post_conversations_calls(body=body, headers=headers)
 print("Call initiated:", api_response)
except Exception as e:
 print("Error: ", e)

Check the token scopes first. That’s usually the blocker.