Skip to main content
Use this guide to run one SMS conversation and one voice-call test against the PAM Outbound API with the reusable PROD_OUTBOUND_XTIME sandbox client. This sandbox is for outbound API prospects and partners who need to test direct SMS, voice, scheduling, and optional webhook behavior before their production client configuration is ready. PAM will provide:
  • API base URL
  • API key for PROD_OUTBOUND_XTIME
  • Allowed fromNumber values for SMS and voice
You will provide:
  • A test recipient phone number
  • An optional HTTPS webhook endpoint, if you want callback events

Setup

Set these values locally:
export PAM_API_BASE="https://oos.pamws.com/api/v1"
export PAM_API_KEY="replace_with_pam_api_key"
export PAM_SMS_FROM_NUMBER="+17034230644"
export PAM_VOICE_FROM_NUMBER="+17032142578"
export PAM_TEST_TO_NUMBER="+15555550199"
export PAM_SMS_TEST_RUN_ID="prod-outbound-xtime-sms-smoke-$(date +%s)"
All phone numbers must use E.164 format. All dynamicVariables values must be strings. For managed PAM agents, include the full vehicle identity:
  • vin
  • vehicle_year
  • vehicle_make
  • vehicle_model
Do not send contact_phone_number. PAM derives the customer’s phone number from toNumber.

Start a test SMS conversation

Create one SMS conversation:
curl "$PAM_API_BASE/sms-conversations" \
  -X POST \
  -H "Authorization: Bearer $PAM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "agentSlug": "sms-retention",
    "toNumber": "'"$PAM_TEST_TO_NUMBER"'",
    "fromNumber": "'"$PAM_SMS_FROM_NUMBER"'",
    "welcomeMessage": "Hi John, this is Pam from PAM Xtime Test Store. We have a $49.95 oil and filter change special for your 2015 Mercedes-Benz GLK-Class. The offer includes up to 5 quarts of conventional oil, a new oil filter, and a complimentary multi-point inspection. Reply if you want help finding a service time.",
    "dynamicVariables": {
      "contact_first_name": "John",
      "contact_last_name": "Smith",
      "contact_email": "test@example.com",
      "dealership_name": "PAM Xtime Test Store",
      "service_ids": "2323372",
      "service_names": "Replace engine oil and oil filter (6cyl)",
      "offer_description": "$49.95 oil and filter change special, including up to 5 quarts of conventional oil, a new oil filter, and a complimentary multi-point inspection. Taxes, shop supplies, synthetic oil, and diesel vehicles may be extra.",
      "vin": "WDCGG5HB4FG429584",
      "vehicle_year": "2015",
      "vehicle_make": "MERCEDES-BENZ",
      "vehicle_model": "GLK-Class",
      "vehicle_mileage": "100000",
      "transport_type": "WAITER"
    },
    "metadata": {
      "testRun": "prod-outbound-xtime-sms-smoke"
    },
    "externalReferenceId": "'"$PAM_SMS_TEST_RUN_ID"'"
  }'
Do not include idempotencyKey for manual SMS smoke tests. Use a fresh externalReferenceId each time. Reusing an idempotency key can return the original conversation instead of creating a new one. Expected result:
  • The API returns 201 Created.
  • The response includes data.conversationId.
  • The test phone receives the opening SMS.
  • If the test recipient replies, the conversation continues on the same thread.
  • If the agent calls scheduling tools, GET /sms-conversations/{conversationId} shows the tool invocation and result messages.
Use the returned conversationId to fetch state:
export SMS_CONVERSATION_ID="replace_with_conversation_id"

curl "$PAM_API_BASE/sms-conversations/$SMS_CONVERSATION_ID" \
  -H "Authorization: Bearer $PAM_API_KEY"
Close the test conversation when finished:
curl "$PAM_API_BASE/sms-conversations/$SMS_CONVERSATION_ID/close" \
  -X POST \
  -H "Authorization: Bearer $PAM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"reason":"prod_outbound_xtime_sms_smoke_complete"}'

Start a test voice call

Voice calls require an idempotency key. Use a fresh key for each manual test run. Reuse the same key only when retrying the same request after a network timeout. Create one voice call:
export PAM_CALL_TEST_RUN_ID="prod-outbound-xtime-call-smoke-$(date +%s)"

curl "$PAM_API_BASE/calls" \
  -X POST \
  -H "Authorization: Bearer $PAM_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $PAM_CALL_TEST_RUN_ID" \
  -d '{
    "agentSlug": "voice-retention",
    "toNumber": "'"$PAM_TEST_TO_NUMBER"'",
    "fromNumber": "'"$PAM_VOICE_FROM_NUMBER"'",
    "welcomeMessage": "Hi John, this is Pam from PAM Xtime Test Store. I am calling because we have a $49.95 oil and filter change special for your 2015 Mercedes-Benz GLK-Class. The offer includes up to 5 quarts of conventional oil, a new oil filter, and a complimentary multi-point inspection.",
    "dynamicVariables": {
      "contact_first_name": "John",
      "contact_last_name": "Smith",
      "contact_email": "test@example.com",
      "dealership_name": "PAM Xtime Test Store",
      "service_ids": "2323372",
      "service_names": "Replace engine oil and oil filter (6cyl)",
      "offer_description": "$49.95 oil and filter change special, including up to 5 quarts of conventional oil, a new oil filter, and a complimentary multi-point inspection. Taxes, shop supplies, synthetic oil, and diesel vehicles may be extra.",
      "vin": "WDCGG5HB4FG429584",
      "vehicle_year": "2015",
      "vehicle_make": "MERCEDES-BENZ",
      "vehicle_model": "GLK-Class",
      "vehicle_mileage": "100000",
      "transport_type": "WAITER"
    },
    "metadata": {
      "testRun": "prod-outbound-xtime-call-smoke"
    },
    "externalReferenceId": "'"$PAM_CALL_TEST_RUN_ID"'"
  }'
Expected result:
  • The API returns 202 Accepted.
  • conversationId may be null at first. PAM creates it after the call provider accepts the call.
  • The test phone receives a call from PAM_VOICE_FROM_NUMBER.

Optional webhook testing

You do not need to register a webhook for the basic SMS or voice smoke test. If you want callback events, first register a webhook:
export PAM_WEBHOOK_URL="https://your-domain.example/pam/webhooks"

curl "$PAM_API_BASE/webhooks" \
  -X POST \
  -H "Authorization: Bearer $PAM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "'"$PAM_WEBHOOK_URL"'",
    "events": [
      "call.started",
      "call.ended",
      "call.analyzed",
      "call.failed",
      "sms.message_sent",
      "sms.message_received",
      "sms.message_delivery_updated",
      "sms.tool_call_invocation",
      "sms.tool_call_result"
    ]
  }'
The response includes a webhook signing secret once. Store it securely. PAM uses that secret to sign future webhook requests. Confirm the webhook registration:
curl "$PAM_API_BASE/webhooks" \
  -H "Authorization: Bearer $PAM_API_KEY"
To send one conversation’s events to a different URL, include webhookUrl in the create request:
{
  "webhookUrl": "https://your-domain.example/pam/webhooks/test-run-123"
}
The override changes only that conversation’s destination URL. Event subscriptions and signing still come from the registered webhook.

Booking test notes

Booking creates a real appointment in the sandbox scheduler. For manual booking tests, use an internal test contact and close the conversation when finished. The PROD_OUTBOUND_XTIME sandbox lookup may not find the test contact by phone number. Include vin, vehicle_year, vehicle_make, and vehicle_model so the scheduler still has the full vehicle identity.

Troubleshooting

SymptomWhat to check
401 unauthorizedConfirm the Authorization: Bearer header uses the full API key.
400 validation_errorConfirm phone numbers are E.164 format and all required dynamic variables are present.
dynamicVariables must include vin, vehicle_year, vehicle_make, and vehicle_modelSend the full vehicle identity. V1 does not decode VIN-only direct conversations before scheduling.
API rejects contact_phone_numberRemove it. PAM derives the customer phone number from toNumber.
No SMS reply eventsConfirm the test phone replied to the same number that sent the opening SMS.
No call lifecycle eventsConfirm the test recipient answered or that a call.failed event was received.
No webhook eventsConfirm the webhook registration includes the event, the endpoint returns a 2xx, and the endpoint is publicly reachable over HTTPS.