Skip to main content

With the API

All requests go to https://prod-api.ringg.ai/ca/api/v0 with the header X-API-KEY: $RINGG_API_KEY (API key, Authentication). You need the agent’s ID (Find an agent’s ID) and either caller numbers (Get Workspace Numbers) or a pool ID (Copy pool ID on the pool list). Campaign times use the format DD/MM/YYYY, HH:MM and are read in call_config.call_time.timezone. Two flows exist: the standard one (save, then start) and the large-campaign one (upload, poll verification, then schedule), which the dashboard uses for every campaign. Both apply the same row limit.

Standard flow: save, then start

1

Upload the list and settings

Upload campaign contact list (POST /campaign/save) takes the CSV and the campaign settings as multipart/form-data. The response includes list_id, total_rows, successful_rows and failed_rows.
2

Start the calls

Pass the list_id to Start campaign (number pool) (POST /campaign/v2/start) with a number_pool_id. email_completion_user_ids (workspace user IDs to email when the campaign is scheduled and when it completes) is optional; an ID that isn’t a member of the workspace returns 404.
To pass explicit caller numbers instead, use Start campaign (POST /campaign/start) with from_numbers: number IDs, or numbers written exactly as Get Workspace Numbers returns them. Retries rotate through the list in order. It is deprecated in favour of the pool version.

Large-campaign flow

The upload is verified in the background, and you schedule the calls once it is ready. It works for a list of any size, from one row. These endpoints are Beta.
1

Upload the CSV

Upload large campaign CSV (POST /campaign/upload-csv) takes campaign_name, agent_id, country_code, variables_map, file and optionally remove_invalid_rows, transliterate_fields and transliterate_callee_name. It returns bulk_list_id, status (verifying), total_rows and campaign_name. Save the bulk_list_id; it is also the campaign ID. A list over your row limit returns 402.
2

Wait for verification

Poll Get large campaign upload status (GET /campaign/upload-status/{bulk_list_id}) every few seconds (the dashboard uses 5). Continue when status is draft; stop on failed, no_valid_contacts or insufficient_balance. The response also gives campaign_name, total_callees (valid contacts loaded) and invalidated_rows_count. The invalid rows can be downloaded from the campaign’s detail panel.
3

If balance is short

On insufficient_balance, add balance, then call Check large campaign balance (POST /campaign/check-balance/{bulk_list_id}). Nothing resumes on its own. If the balance now covers it, the response has status: "draft" and total_callees, and you continue to the next step with the same bulk_list_id. If it is still short, status stays insufficient_balance and the response gives required_credits and additional_balance_required.
4

Schedule the calls

Make large campaign calls async (POST /campaign/make-call-async) takes the schedule and exactly one of from_numbers or number_pool_id; both or neither returns 422. email_completion_user_ids and concurrency_percentage are optional. The balance is checked again here: if it no longer covers the campaign, the response is 402 and the campaign goes back to insufficient_balance. Caller numbers and email_completion_user_ids are checked after the request is accepted, so a number or user that isn’t found sets the campaign to failed instead of returning an error.
Body fields of POST /campaign/make-call-async:
string
required
The draft list ID returned by /campaign/upload-csv.
string
required
The agent ID used during upload.
string
required
Phone number country code, for example +91.
string
Start time in DD/MM/YYYY, HH:MM format. Required unless you send call_slots. Send it together with campaign_end_time.
string
End time in DD/MM/YYYY, HH:MM format. Required unless you send call_slots. Send it together with campaign_start_time.
string[]
Caller number IDs or phone numbers. Send exactly one of from_numbers or number_pool_id.
string
A number pool ID. Send exactly one of from_numbers or number_pool_id.
object
required
Retries and calling window. They replace the agent’s own call settings for this campaign.
object
Optional calling slots, read in call_time.timezone. A call is placed only inside a slot and inside the daily call_time window. Without campaign_start_time and campaign_end_time, the campaign runs from the first slot’s start to the last slot’s end; with them, every slot must fit inside. Use one of two shapes:
  • {"mode": "absolute", "intervals": [{"start": "18/10/2026, 10:00", "end": "18/10/2026, 13:00"}]}, up to 500 intervals.
  • {"mode": "weekly", "until": "31/10/2026, 21:00", "windows": [{"days": ["mon", "tue"], "start": "10:00", "end": "13:00"}]}, up to 21 windows, repeated from the campaign start (or now) until until, at most 90 days.
Each slot lasts 1 minute to 24 hours and can’t be in the past, the last must end at least 5 minutes from now, and overlapping slots are merged, up to 100 in all. Mixing the two shapes returns 422.
integer
default:"0"
0 to 100. This campaign’s share of campaign concurrency. See Manage concurrency.
string[]
Optional. Workspace members to email when the campaign is scheduled and when it completes.
Through the API you can set a different cooldown per outcome (retry_busy, retry_not_picked, retry_failed, in minutes). call_time sets one daily window; for several windows or weekly hours, send call_slots. Without call_time, the campaign calls 09:00–21:00 in Asia/Kolkata, whatever the agent’s calling window, and without call_retry_config it makes no retries, unlike the dashboard’s default of 3. Before a real run, send a 5-row list first and listen to a few calls in Logs, and set call_time in the timezone of the people you are calling.