list_participants applies an exact, case-insensitive email filter. Test and panel invitations are excluded before total_count and pagination are calculated. Each record has a personal interview_link, status, and interview_count of visible non-test sessions. Status is created when no email was sent, then invited, started, completed, or screened_out. A silent invitation starts as created but still has a personal link. Use the returned participant ID as list_interviews.participant_id to page through its interviews; the count is sessions, not unique people.
Creating participants
create_participants accepts a study_id and a participants array. Email addresses must be unique case-insensitively. Each participant supports silent: true to create the record without sending an invitation email.
Create and finish the study first. Call get_study, return the complete persisted plan to the user, and obtain explicit approval of that exact version. Only call create_participants after the study is provisioned and the current plan is approved. Approval to create a draft or answer Customize Plan questions is not plan approval.
Updates and rewards
Callget_participant before update_participant. Rewards are BYOP-only and can have a real financial side effect. Call send_participant_reward only after the user explicitly asks and after confirming the participant is the intended recipient. The backend prevents duplicate payment for an already-paid participant.
delete_participant requires an explicit user request. If the invitation has interviews, deletion returns a conflict. Only set cascade_interviews: true after the user separately approves deletion of those interviews; the database soft-deletes them with the invitation.
