---
updatedAt: 2026-08-24T09:14:57.000Z
agentTools:
  projectIndex: https://developers.vibe.co/llms.txt
---

# Upload a batch for an audience sync

Operational limits: max batch size 10,000 records; 
max request size 1 MB; 
rate limit 1 request per second.
**Scopes:**
`audiences:write`
<br>*Rate limits*:<br>Burst: `1/s`<br>Steady: `60/m`


# OpenAPI definition

```json
{
  "openapi": "3.1.0",
  "paths": {
    "/audiences/{audience_id}/syncs/{sync_id}/batches": {
      "post": {
        "description": "Operational limits: max batch size 10,000 records; \nmax request size 1 MB; \nrate limit 1 request per second.\n**Scopes:**\n`audiences:write`\n<br>*Rate limits*:<br>Burst: `1/s`<br>Steady: `60/m`\n",
        "operationId": "uploadAudienceSyncBatch",
        "parameters": [
          {
            "name": "audience_id",
            "required": true,
            "in": "path",
            "description": "Stable identifier of the audience",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sync_id",
            "required": true,
            "in": "path",
            "description": "Stable identifier of the sync operation",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AudienceSyncBatchCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Batch upload response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AudienceSyncBatch"
                }
              }
            }
          },
          "400": {
            "description": "Bad request error response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "missingApiKey": {
                    "summary": "Missing API key",
                    "value": {
                      "error": {
                        "type": "validation",
                        "message": "Missing API Key",
                        "status": 400,
                        "detail": null,
                        "request_id": "req_8f3a4b2c",
                        "doc_url": null
                      }
                    }
                  },
                  "validationError": {
                    "summary": "Validation error",
                    "value": {
                      "error": {
                        "type": "validation",
                        "message": "Validation error",
                        "status": 400,
                        "detail": {
                          "validation": [
                            "id must be a string"
                          ]
                        },
                        "request_id": "req_8f3a4b2c",
                        "doc_url": null
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized error response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "invalidApiKey": {
                    "summary": "Invalid API key",
                    "value": {
                      "error": {
                        "type": "invalid_token",
                        "message": "Unauthorized",
                        "status": 401,
                        "detail": null,
                        "request_id": "req_8f3a4b2c",
                        "doc_url": "https://developers.vibe.co/errors/invalid-token"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient scope error response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "insufficientScope": {
                    "summary": "Missing required scope",
                    "value": {
                      "error": {
                        "type": "insufficient_scope",
                        "message": "Missing required scope",
                        "status": 403,
                        "detail": {
                          "required": "audiences:write",
                          "granted": [
                            "test"
                          ]
                        },
                        "request_id": "req_8f3a4b2c",
                        "doc_url": "https://developers.vibe.co/reference/oauth2token"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "summary": "Upload a batch for an audience sync",
        "tags": [
          "Audiences"
        ],
        "x-rate-limit": {
          "rps": 1,
          "rpm": 60
        },
        "x-scopes": [
          "audiences:write"
        ]
      }
    }
  },
  "info": {
    "title": "Vibe Public API",
    "description": "Vibe Public API revision 2026-06-01",
    "version": "2026-06-01",
    "contact": {}
  },
  "tags": [
    {
      "name": "Audiences",
      "description": "An Audience is a list of user identifiers Vibe can target or exclude. You populate an audience by opening a **sync**, uploading one or more **batches** of identifiers, then marking the final batch with `last_batch_flag: true`.\n\nConcurrency: only one non-terminal sync may exist per audience at a time. Syncs expire after 24 hours of inactivity.\n\n> ⚠️ **Gotcha — silent zero-match failures**\n>\n> If your identifiers are hashed with the wrong algorithm or normalization, the sync will succeed and the audience will show as Active, but it will match zero CTV profiles. There is no error signal. See the [HEM format specification](https://developers.vibe.co/docs/hem-format) for the exact requirements."
    }
  ],
  "servers": [
    {
      "url": "https://api.vibe.co",
      "description": "Production API"
    }
  ],
  "components": {
    "securitySchemes": {
      "bearer": {
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "type": "http"
      }
    },
    "schemas": {
      "ErrorDetail": {
        "type": "object",
        "properties": {
          "required": {
            "type": "string",
            "example": "audiences:write"
          },
          "granted": {
            "example": [
              "audiences:read",
              "reporting:read"
            ],
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "required",
          "granted"
        ]
      },
      "ApiError": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "insufficient_scope",
              "invalid_token",
              "validation",
              "internal_error"
            ]
          },
          "message": {
            "type": "string"
          },
          "status": {
            "type": "number",
            "example": 403
          },
          "detail": {
            "nullable": true,
            "allOf": [
              {
                "$ref": "#/components/schemas/ErrorDetail"
              }
            ]
          },
          "request_id": {
            "type": "string",
            "example": "req_8f3a4b2c"
          },
          "doc_url": {
            "type": "string",
            "example": "https://developers.vibe.co/reference/oauth2token",
            "nullable": true
          }
        },
        "required": [
          "type",
          "message",
          "status",
          "request_id"
        ]
      },
      "ErrorResponse": {
        "type": "object",
        "properties": {
          "error": {
            "$ref": "#/components/schemas/ApiError"
          }
        },
        "required": [
          "error"
        ]
      },
      "AudienceMember": {
        "type": "object",
        "properties": {
          "hashed_emails": {
            "description": "Hashed email identifiers for a single person. Each entry MUST be a SHA-256 hex digest (64 hex chars, case-insensitive). Multiple hashed emails are accepted.",
            "type": "array",
            "items": {
              "type": "string",
              "pattern": "^[a-fA-F0-9]{64}$"
            }
          },
          "hashed_phone_numbers": {
            "description": "Hashed phone identifiers for a single person. Each entry MUST be a SHA-256 hex digest (64 hex chars, case-insensitive).",
            "type": "array",
            "items": {
              "type": "string",
              "pattern": "^[a-fA-F0-9]{64}$"
            }
          },
          "external_ids": {
            "description": "Optional caller-defined person-level identifiers for deterministic deduplication on the caller side.",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "ips": {
            "description": "IP address identifiers for the audience member.",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "ifas": {
            "description": "Identifiers for Advertising for the audience member.",
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "AudienceSyncBatchCreate": {
        "type": "object",
        "properties": {
          "batch_index": {
            "type": "number",
            "minimum": 0,
            "description": "Zero-based index of the uploaded batch"
          },
          "record_count": {
            "type": "number",
            "minimum": 0,
            "description": "Number of audience records included in this batch"
          },
          "last_batch_flag": {
            "type": "boolean",
            "description": "Whether this is the final batch for the sync"
          },
          "idempotency_key": {
            "type": "string",
            "description": "Idempotency key for safe batch upload retries"
          },
          "records": {
            "description": "Audience membership records for this batch",
            "maxItems": 10000,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AudienceMember"
            }
          }
        },
        "required": [
          "batch_index",
          "record_count",
          "last_batch_flag",
          "idempotency_key",
          "records"
        ]
      },
      "AudienceSyncBatch": {
        "type": "object",
        "properties": {
          "sync_id": {
            "type": "string",
            "description": "Stable identifier of the sync operation"
          },
          "batch_index": {
            "type": "number",
            "minimum": 0,
            "description": "Zero-based index of the uploaded batch"
          },
          "accepted": {
            "type": "boolean",
            "description": "Whether the batch was accepted for asynchronous processing"
          }
        },
        "required": [
          "sync_id",
          "batch_index",
          "accepted"
        ]
      }
    }
  },
  "security": [
    {
      "bearer": []
    }
  ]
}
```