Cria um lote persistente
Persiste a definição, os destinatários normalizados, as instâncias permitidas e a agenda opcional. Com autoStart=true, o estado inicial é QUEUED, SCHEDULED ou WAITING_FOR_WINDOW conforme a janela.
Autenticação
JWT HS256 de usuario. Deve conter userId em formato UUID e exp; a expiracao sempre e validada.
- Header
Authorization- Exemplo
Bearer <INSTANCE_TOKEN>
Request body
obrigatóriobodyobjectExemplo: {"name":"Aviso de manutenção","instances":["codechat-01","codechat-02"],"recipients":["5531999999999","5531888888888"],"message":{"type":"interactive","payload":{"title":"Confirmação","description":"Deseja continuar?","footerText":"CodeChat","buttons":[{"displayText":"Repo","url":"https://github.com/code-chat-br/whatsapp-api-go"},{"displayText":"Código de barras","copyCode":"32546413216543165489869589416558645341864321365468435469465"},{"displayText":"Sim","id":"1"},{"displayText":"Não","id":"0"},{"displayText":"Talvez","id":"-1"}]}},"options":{"replicable":true,"presence":"composing","delay":{"minMs":3000,"maxMs":12000}},"autoStart":false,"autoResume":true,"schedule":{"windowStartAt":"2026-07-16T00:00:00-03:00","windowEndAt":"2026-07-16T03:00:00-03:00","recurrence":"DAILY","timezone":"America/Sao_Paulo"},"externalAttributes":{"origin":"admin-panel"}}
bodyobjectnamestringobrigatóriominLength: 1 · maxLength: 255instancesarrayobrigatórioNomes de instâncias existentes e com autenticação disponível.
instancesarrayobrigatórioitems[]stringminLength: 1 · maxLength: 255recipientsarrayobrigatórioSomente contatos individuais. O limite é definido por MESSAGE_BATCH_MAX_RECIPIENTS e duplicados normalizados são ignorados.
recipientsarrayobrigatórioitems[]stringminLength: 1messageobjectobrigatórioMensagem persistida do lote. O payload é direto: não envie number/chat/recipient/options nem wrappers como textMessage, mediaMessage, audioMessage, contactMessage, locationMessage ou buttonMessage. Tipos aceitos: text, link, media, audio, contact, location e interactive; ptt, whatsapp-audio e whatsapp_audio são aliases de audio.
messageobjectobrigatóriotypeenum<text | link | media | audio | ptt | whatsapp-audio | whatsapp_audio | contact | location | interactive>obrigatóriopayloadoneOfobrigatórioObjeto ou array persistente conforme message.type: text={text}; link={link,thumbnailUrl,title,description}; media={mediatype,media|mediaUploadId,fileName,caption}; audio={audio} ou {mediaUploadId,ptt:true}; contact=[{fullName,phoneNumber,wuid,organization,vcard}]; location={latitude,longitude,name,address,url}; interactive segue MessageBatchInteractivePayload.
payloadoneOfobrigatórioopção 1objectopção 2array
opção 2arrayitems[]objectoptionsobject
optionsobjectreplicablebooleanPreservado no contrato; não adiciona semântica própria no worker.
presenceenum<composing | recording | paused>delayobjectCampos ausentes assumem zero. maxMs precisa ser maior ou igual a minMs e respeitar MESSAGE_BATCH_MAX_DELAY_MS.
delayobjectminMsintegerformat: int64 · padrão: 0 · mín: 0maxMsintegerformat: int64 · padrão: 0 · mín: 0quotedMessageIdintegerformat: int64quotedMessageobjectexternalAttributesobjectmentionAllbooleanSomente false é aceito; true é rejeitado porque lotes não aceitam grupos.
autoStartbooleanpadrão: falseautoResumebooleanpadrão: trueRecupera automaticamente interrupções operacionais; nunca ignora PAUSED.
scheduleobject
scheduleobjectwindowStartAtstringobrigatórioformat: date-timewindowEndAtstringobrigatórioformat: date-timerecurrenceenum<NONE | DAILY>obrigatóriotimezonestringTimezone IANA. Quando omitido, usa MESSAGE_BATCH_TIMEZONE.
externalAttributesobjectObjeto JSON com até 64 KiB.
{"name": "Aviso de manutenção","instances": ["codechat-01","codechat-02"],"recipients": ["5531999999999","5531888888888"],"message": {"type": "interactive","payload": {"title": "Confirmação","description": "Deseja continuar?","footerText": "CodeChat","buttons": [{"displayText": "Repo","url": "https://github.com/code-chat-br/whatsapp-api-go"},{"displayText": "Código de barras","copyCode": "32546413216543165489869589416558645341864321365468435469465"},{"displayText": "Sim","id": "1"},{"displayText": "Não","id": "0"},{"displayText": "Talvez","id": "-1"}]}},"options": {"replicable": true,"presence": "composing","delay": {"minMs": 3000,"maxMs": 12000}},"autoStart": false,"autoResume": true,"schedule": {"windowStartAt": "2026-07-16T00:00:00-03:00","windowEndAt": "2026-07-16T03:00:00-03:00","recurrence": "DAILY","timezone": "America/Sao_Paulo"},"externalAttributes": {"origin": "admin-panel"}}
Respostas
application/jsonLote criado em DRAFT, SCHEDULED, QUEUED ou WAITING_FOR_WINDOW
response 201object
response 201objectidstringobrigatórioformat: uuidownerUserIdstringobrigatórioformat: uuidnamestringobrigatóriostatusenum<DRAFT | SCHEDULED | QUEUED | PROCESSING | PAUSE_REQUESTED | PAUSED | WAITING_FOR_INSTANCE | WAITING_FOR_WINDOW | STOP_REQUESTED | STOPPED | INTERRUPTED | COMPLETED | COMPLETED_WITH_ERRORS | FAILED>obrigatóriomessageobjectMensagem persistida do lote. O payload é direto: não envie number/chat/recipient/options nem wrappers como textMessage, mediaMessage, audioMessage, contactMessage, locationMessage ou buttonMessage. Tipos aceitos: text, link, media, audio, contact, location e interactive; ptt, whatsapp-audio e whatsapp_audio são aliases de audio.
messageobjecttypeenum<text | link | media | audio | ptt | whatsapp-audio | whatsapp_audio | contact | location | interactive>obrigatóriopayloadoneOfobrigatórioObjeto ou array persistente conforme message.type: text={text}; link={link,thumbnailUrl,title,description}; media={mediatype,media|mediaUploadId,fileName,caption}; audio={audio} ou {mediaUploadId,ptt:true}; contact=[{fullName,phoneNumber,wuid,organization,vcard}]; location={latitude,longitude,name,address,url}; interactive segue MessageBatchInteractivePayload.
payloadoneOfobrigatórioopção 1objectopção 2array
opção 2arrayitems[]objectoptionsobject
optionsobjectreplicablebooleanPreservado no contrato; não adiciona semântica própria no worker.
presenceenum<composing | recording | paused>delayobject
delayobjectminMsintegerobrigatórioformat: int64 · padrão: 0 · mín: 0maxMsintegerobrigatórioformat: int64 · padrão: 0 · mín: 0quotedMessageIdintegerformat: int64quotedMessageobjectexternalAttributesobjectmentionAllbooleanSomente false é aceito; true é rejeitado porque lotes não aceitam grupos.
externalAttributesobjectinstancesarrayobrigatório
instancesarrayobrigatórioitems[]object
items[]objectidintegerobrigatórionamestringobrigatórioconnectionStatusstringselectedCountintegerformat: int64successCountintegerformat: int64failedCountintegerformat: int64countsobjectobrigatório
countsobjectobrigatórioreceivedintegerformat: int64 · mín: 0totalintegerobrigatórioformat: int64 · mín: 0duplicatesIgnoredintegerformat: int64 · mín: 0processedintegerobrigatórioformat: int64 · mín: 0pendingintegerobrigatórioformat: int64 · mín: 0sendingintegerobrigatórioformat: int64 · mín: 0successintegerobrigatórioformat: int64 · mín: 0failedintegerobrigatórioformat: int64 · mín: 0skippedintegerobrigatórioformat: int64 · mín: 0unknownintegerobrigatórioformat: int64 · mín: 0progressintegerobrigatóriomín: 0 · máx: 100floor(processed * 100 / total).
autoResumebooleanobrigatórioscheduleoneOfobrigatório
scheduleoneOfobrigatórioopção 1objectJanela absoluta inicial. DAILY preserva os horários locais e aceita janelas que atravessam a meia-noite.
opção 1objectwindowStartAtstringobrigatórioformat: date-timewindowEndAtstringobrigatórioformat: date-timerecurrenceenum<NONE | DAILY>obrigatóriotimezonestringobrigatórioTimezone IANA usado no cálculo da recorrência.
opção 2nullnextRunAtstring | nullobrigatórioformat: date-timelastInterruptedAtstring | nullobrigatórioformat: date-timeinterruptionReasonenum<GRACEFUL_SHUTDOWN | LEASE_EXPIRED | PROCESS_CRASH | SEND_TIMEOUT_DURING_SHUTDOWN | null>obrigatóriolastRecoveredAtstring | nullobrigatórioformat: date-timecurrentItemobject
currentItemobjectidstringobrigatórioformat: uuidpositionintegerobrigatóriomín: 0recipientstringobrigatórioinstanceNamestring | nullobrigatóriolastErrorstringcreatedAtstringobrigatórioformat: date-timestartedAtstringformat: date-timepausedAtstringformat: date-timestoppedAtstringformat: date-timecompletedAtstringformat: date-timeinterruptedAtstringformat: date-timeupdatedAtstringobrigatórioformat: date-time{"id": "01900000-0000-7000-8000-000000000001","ownerUserId": "11111111-1111-4111-8111-111111111111","name": "Aviso de manutenção","status": "DRAFT","autoResume": true,"schedule": null,"nextRunAt": null,"lastInterruptedAt": null,"interruptionReason": null,"lastRecoveredAt": null,"instances": [{"id": 1,"name": "codechat-01","connectionStatus": "offline"},{"id": 2,"name": "codechat-02","connectionStatus": "online"}],"counts": {"received": 2,"total": 2,"processed": 0,"pending": 2,"sending": 0,"success": 0,"failed": 0,"skipped": 0,"unknown": 0},"progress": 0,"externalAttributes": {"origin": "admin-panel"},"createdAt": "2026-07-13T15:00:00Z","updatedAt": "2026-07-13T15:00:00Z"}
