API parameters often have complex structures, with a single endpoint supporting multiple different parameter combinations. For example, a login endpoint might support username-password authentication, email-password authentication, or phone number verification codes. Payment endpoints can offer various methods like credit cards, or Alipay, each requiring different fields.

Traditional API documentation approaches often simply list all possible fields and use text descriptions like "choose different fields based on different scenarios." This approach is neither precise nor developer-friendly, often leading to confusion. Apidog supports JSON Schema's oneOf, anyOf, and allOf features, allowing you to accurately describe these complex composite data structures in your API documentation.
Understanding the Three Combination Modes
In JSON Schema, oneOf, anyOf, and allOf are used to combine multiple sub-schemas, but they have different logical meanings:
- allOf: Combines multiple rules, requiring all to match
- anyOf: At least one match is required, multiple matches are acceptable
- oneOf: Must match exactly one schema, matching zero or multiple schemas will fail
Setting Up Combination Modes in Apidog
Apidog provides two ways to use these combination modes:
Visual Editor Approach
The first method uses the visual editing panel. In your project, click "Data Models" to create a new model, then find "Combination Modes" in the type selection. Choose the needed oneOf, anyOf, or allOf mode, then define specific data structures for each sub-schema.

JSON Schema Code Editor
The second approach involves directly editing JSON Schema code. In the data model editing panel, you can switch to code mode and write JSON Schema directly to define these logical combination patterns. This method is more direct for developers familiar with JSON Schema.

Applying These Patterns in API Endpoints
Once you've defined your data models, you can use them in your API documentation. When editing interface request parameters, select Body type as JSON, then in the data structure section, you can reference the "Data Models" you just created, or directly select "Combination Modes" to define complex parameter structures.

The same principle applies to response data definitions. When adding response examples in the return response section, you can use combination modes to describe response formats for different scenarios. This way, developers can clearly understand what data structure will be returned in different situations.
Real-World Use Cases
allOf: Combining Multiple Structures
allOf combines multiple structures together - it's not about selection, but about stacking. allOf doesn't change field hierarchy; all fields end up in the same object. It simply stacks multiple rules on the same data. Think of it as "logical AND" - all sub-structure constraints must be satisfied.
For example, this JSON Schema:
{
"allOf": [
{
"description": "Basic user information",
"type": "object",
"properties": {
"id": { "type": "integer" },
"name": { "type": "string" }
},
"required": ["id", "name"]
},
{
"description": "Contact information",
"type": "object",
"properties": {
"email": { "type": "string", "format": "email" },
"phone": { "type": "string" }
},
"required": ["email"]
}
]
}
This schema means: the final data must simultaneously satisfy both "basic user information" and "contact information" structures.
In other words, the request body must include id, name, and email, while phone is optional.
Valid data:
{
"id": 1001,
"name": "John Doe",
"email": "john@example.com",
"phone": "1-800-000-0000"
}
Invalid data:
{
"id": 1001,
"name": "John Doe"
}
This lacks the required email field and doesn't satisfy the second structure.
This approach is suitable for splitting complex objects. User information, order details, configuration items, etc., can all be divided into independent structures by functional modules, then combined using allOf. Other interfaces that need part of these structures can reference them directly without redundant definitions.
anyOf: Satisfying At Least One Condition
anyOf lists multiple possible structures, and data is considered valid as long as it conforms to at least one of them. It doesn't care whether multiple conditions are satisfied, nor does it require unique matching.
For example, an identifier field might be an email or a phone number. These two formats are distinctly different, but both belong to the category of "user login credentials."
You can use anyOf to clearly express this "can be A or B" intention:
{
"type": "object",
"properties": {
"identifier": {
"description": "User identifier: can be email or phone number",
"anyOf": [
{
"title": "Email format",
"description": "Must be a valid email address",
"type": "string",
"format": "email"
},
{
"title": "Phone format",
"description": "Must be a valid international phone number",
"type": "string",
"pattern": "^\\+?[1-9]\\d{1,14}$"
}
]
},
"password": {
"type": "string",
"minLength": 6,
"description": "Login password, at least 6 characters"
}
},
"required": ["identifier", "password"],
"description": "User login request parameters"
}
This structure means: identifier is a string that's considered valid as long as it satisfies either email format or phone number format.
Valid data:
{
"identifier": "test@example.com",
"password": "123456"
}
{
"identifier": "+1-800-000-0000",
"password": "123456"
}
Invalid data:
{
"identifier": "abc",
"password": "123456"
}
"abc" is neither an email nor a valid phone number format, satisfying none of the conditions.
oneOf: Choose Exactly One Option
oneOf lists multiple possible structures, and data must conform to exactly one of them. It emphasizes exclusivity - you can only choose one, not more, not less.
For example, payment methods: to complete a payment, users must choose one of credit card, WeChat Pay, or Alipay, but cannot use two methods simultaneously, nor can they choose none. You can define this "single-choice" logic using oneOf:
{
"properties": {
"paymentMethod": {
"description": "Payment method, must choose exactly one",
"oneOf": [
{
"title": "Credit Card Payment",
"description": "Pay with credit card, requires card number and expiry date",
"type": "object",
"properties": {
"type": { "const": "credit_card" },
"cardNumber": { "type": "string" },
"expiryDate": { "type": "string" }
},
"required": ["type", "cardNumber", "expiryDate"],
"additionalProperties": false
},
{
"title": "WeChat Pay",
"description": "Pay through WeChat, requires user's openid",
"type": "object",
"properties": {
"type": { "const": "wechat" },
"openid": { "type": "string" }
},
"required": ["type", "openid"],
"additionalProperties": false
},
{
"title": "Alipay Payment",
"description": "Pay through Alipay, requires account ID",
"type": "object",
"properties": {
"type": { "const": "alipay" },
"accountId": { "type": "string" }
},
"required": ["type", "accountId"],
"additionalProperties": false
}
]
}
}
}
This definition means: paymentMethod is an object that can only match one of the three sub-structures.
Valid examples:
{
"paymentMethod": {
"type": "wechat",
"openid": "wx_123456"
}
}
{
"paymentMethod": {
"type": "credit_card",
"cardNumber": "4111111111111111",
"expiryDate": "12/25"
}
}
Invalid example:
{
"paymentMethod": {
"type": "wechat",
"openid": "wx_123",
"accountId": "2088102"
}
}
Even though type is "wechat", the presence of accountId might cause it to match multiple structures, causing oneOf to fail. Adding "additionalProperties": false
prevents this confusion (meaning no additional fields are allowed), ensuring each structure only allows its own defined fields. Apidog supports visual configuration for additionalProperties.
When you need to make exclusive choices between multiple distinct types, oneOf is the most direct and reliable way to express this.
Choosing the Right Combination Mode
The choice of combination mode mainly depends on your business logic:
- Use allOf when you need to combine and inherit multiple patterns
- Use anyOf when you need flexible optional combinations
- Use oneOf when you need strict exclusive choices
Understanding their respective roles allows your API documentation to accurately describe complex data structures, making it immediately clear to interface users how to pass parameters.
Conclusion
Apidog's comprehensive JSON Schema support empowers developers to create precise, clear API documentation for even the most complex parameter structures. By leveraging oneOf, anyOf, and allOf combinations, you can eliminate ambiguity and provide crystal-clear guidance to API consumers.
Ready to experience the power of advanced API documentation? Try Apidog today and see how easy it becomes to manage complex API parameters with precision and clarity.