403 Forbidden: Access denied for guest identity.
the issue isn’t just the flow config. it’s how you’re handling the token lifecycle in your next.js server. the guest token returned from /api/v2/guests/identities is opaque and expires quickly. if you’re storing it in a cookie or local storage without refreshing, you’ll hit this wall.
more importantly, the suggestion above about “allow guests” in architect is correct but insufficient. you need to ensure the guest:chat scope is actually attached to the application credential generating that identity. but here is the real gotcha: the POST /api/v2/guests/messages endpoint requires the Authorization: Bearer <guest_token> header, but the token must be generated with the correct purpose in the identity payload. if you omit purpose: "chat", the token is valid for the session but not for message operations.
here is the correct identity creation payload structure:
POST /api/v2/guests/identities
Content-Type: application/json
{
"purpose": "chat",
"name": "John Doe",
"email": "[email protected]",
"attributes": {
"language": "en-us"
}
}
then use the returned identityToken in the header. also, check your nginx or cloudfront config. if you are proxying these requests, ensure you aren’t stripping the Authorization header. i’ve seen 403s where the load balancer rejected the token because it looked like a standard user token but lacked the user claims.
finally, if you are using the purecloud sdk in node, don’t. it’s heavy. use fetch with the bearer token.
const response = await fetch('https://api.mypurecloud.com/api/v2/guests/messages', {
method: 'POST',
headers: {
'Authorization': `Bearer ${guestToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
conversationId: 'your-conversation-id',
text: 'hello world'
})
});
if the conversation id is missing or invalid, you get a 400, not 403. so the 403 is definitely auth. check the token scope.