OpenApi how to define with mixed body and query parameters?

The Open API Specification returns a JSON format that’s serialized using these properties, ServiceStack contains Typed DTO’s that maps 1:1 to the v2 specification, so using the available filters you should be able to return the custom Open API definition for the operation you need.

There can only be 1 body, which should be left as the Request DTO, that represents the Request body. The parameters in the /path/info are excluded in the body. For the other parameters you can make them optional Query String parameters, where they can be populated on the QueryString or sent in the Request Body as JSON, so you could try this:

[Route(
    "/surveys/{surveyId}/sendouts/{sendoutId}/respondents",
    HttpMethods.Post,
    Summary = "Adding Respondents",
    Notes = "Add a new Respondent with optional background data to a Sendout."
)]
//[Exclude(Feature.Metadata)]	// hide from OpenAPI
//[RateLimitedPerUser]
public class AddRespondentRequest : IReturn<AddRespondentResponse>
{
    [ApiMember(Name = "surveyId",
        Description = "Remarks: SurveyId of requested Survey.",
        ParameterType = "path",
        DataType = "integer", Format = "int32",
        IsRequired = true
    )]
    public int surveyId { get; set; }

    [ApiMember(Name = "sendoutId",
        Description = "Remarks: SendoutId of Sendout to which a respondent is added.",
        ParameterType = "path",
        DataType = "integer", 
        Format = "int32",
        IsRequired = true
    )]
    public int sendoutId { get; set; }

    [ApiMember(Name = "contactDetails",
        Description = "Remarks: Valid email address, SMS recipient or login identifier.",
        ParameterType = "query",
        DataType = "string",
        IsRequired = false
    )]
    public string contactDetails { get; set; }

    [ApiMember(Name = "sendMail",
        Description = "Remarks: Indicates whether Netigate should send the survey link to the respondent, or if you distribute it yourself.",
        DataType = "boolean",
        ParameterType = "query",
        IsRequired = false
    )]
    public bool sendMail { get; set; }

    [ApiMember(Name = "backgroundData",
        Description = "Remarks: Key = BGDataLabelId, Value = respondent's background data (not empty or null)",
        ParameterType = "query",
        //DataType = "object",
        IsRequired = false
    )]
    public Dictionary<int, string> backgroundData { get; set; }
}

If the purpose is just to have a Typed API it should be easier if you skip Open API altogether and use the code-first approach that ServiceStack.Stripe uses to provide a Typed API for Stripe’s 3rd Party Rest API as captured in the StripeGateway.cs DTOs.