Atendimento: Modelos de Lembrete

Endpoints da WebApiAlcance para gerenciar modelos de lembrete - templates reutilizáveis de mensagens de atendimento, com suporte a recorrência, variáveis, vínculo com departamento/obrigação e anexo de mídia. Cobrem criação, listagem paginada com filtro por departamento, detalhamento por ID, atualização parcial, upload e download de anexo, e exclusão.

Todos os endpoints exigem autenticação. Veja Autenticação para o fluxo de API Key. O Swagger oficial está em api.contabilidadealcance.com.br/docs.

Base path

/api/v1/modelos

A URL completa em produção é https://api.contabilidadealcance.com.br/api/v1/modelos.

Escopos necessários

  • modelos:read - listagem, detalhamento e download de anexo
  • modelos:write - criação, atualização, upload de anexo e exclusão

O escopo é derivado da rota: o prefixo /modelos vira o recurso modelos, e o método HTTP define a ação (read para GET, write para POST/PUT/DELETE).

Endpoints

POST /modelos/

Cria um novo modelo de lembrete. Os campos obrigatórios são titulo e mensagem; os demais têm valores default ou aceitam null.

Parâmetros

Este endpoint não recebe parâmetros de rota ou query - os dados vão no corpo da requisição (ModeloCreate). Veja o Schema ModeloCreate.

Request

{
  "titulo": "Lembrete DAS mensal",
  "mensagem": "Olá {{nome}}, o DAS de {{mes}} vence em {{vencimento}}.",
  "departamento_id": 3,
  "dia_envio": 20,
  "horario_envio": "09:00:00",
  "ajuste_dia_util": "anterior",
  "empresa_ids": [1234, 5678],
  "variaveis": ["nome", "mes", "vencimento"],
  "meses_ativos": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
  "obrigacao_nome": "DAS",
  "recorrencia_ativa": true,
  "tipo_recorrencia": "mensal",
  "vinculo_mode": "departamento"
}

Response 201 Created

{
  "success": true,
  "message": "Modelo criado com sucesso",
  "data": {
    "id": 42,
    "titulo": "Lembrete DAS mensal",
    "mensagem": "Olá {{nome}}, o DAS de {{mes}} vence em {{vencimento}}.",
    "departamento_id": 3,
    "dia_envio": 20,
    "dia_semana": null,
    "horario_envio": "09:00:00",
    "ajuste_dia_util": "anterior",
    "empresa_ids": [1234, 5678],
    "variaveis": ["nome", "mes", "vencimento"],
    "meses_ativos": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
    "obrigacao_nome": "DAS",
    "recorrencia_ativa": true,
    "telefone_avulso": null,
    "tipo_recorrencia": "mensal",
    "vinculo_mode": "departamento",
    "tipo_midia": null,
    "arquivo_url": null,
    "arquivo_nome": null,
    "legacy_uuid": null,
    "data_hora_criacao": "2026-07-03T09:00:00-03:00",
    "data_hora_atualizacao": "2026-07-03T09:00:00-03:00"
  }
}

Erro de validação retorna 422 Unprocessable Entity.

Escopo: modelos:write

GET /modelos/

Lista os modelos cadastrados, com filtro opcional por departamento e paginação. Lista vazia é um estado válido - sempre retorna 200 OK, inclusive com data: [] e a mensagem "Nenhum modelo encontrado.".

Parâmetros

ParâmetroTipoLocalObrigatórioDescrição
departamento_idintquerynãoFiltra os modelos pelo departamento vinculado.
limitintquerynãoItens por página. Default 100, mínimo 1, máximo 500.
offsetintquerynãoOffset de paginação. Default 0, mínimo 0.

Request

Sem corpo de requisição.

Response 200 OK

{
  "success": true,
  "message": "Modelos recuperados com sucesso",
  "data": [
    {
      "id": 42,
      "titulo": "Lembrete DAS mensal",
      "mensagem": "Olá {{nome}}, o DAS de {{mes}} vence em {{vencimento}}.",
      "departamento_id": 3,
      "dia_envio": 20,
      "dia_semana": null,
      "horario_envio": "09:00:00",
      "ajuste_dia_util": "anterior",
      "empresa_ids": [1234, 5678],
      "variaveis": ["nome", "mes", "vencimento"],
      "meses_ativos": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
      "obrigacao_nome": "DAS",
      "recorrencia_ativa": true,
      "telefone_avulso": null,
      "tipo_recorrencia": "mensal",
      "vinculo_mode": "departamento",
      "tipo_midia": null,
      "arquivo_url": null,
      "arquivo_nome": null,
      "legacy_uuid": null,
      "data_hora_criacao": "2026-07-03T09:00:00-03:00",
      "data_hora_atualizacao": "2026-07-03T09:00:00-03:00"
    }
  ]
}

Escopo: modelos:read

GET /modelos/anexo/{nome_disco}

Serve o arquivo de anexo (mídia) gravado em disco, protegido por autenticação e escopo. Retorna o binário do arquivo (FileResponse), não o envelope JSON.

Parâmetros

ParâmetroTipoLocalObrigatórioDescrição
nome_discostrpathsimNome do arquivo em disco a ser servido.

Request

Sem corpo de requisição.

Response 200 OK

Conteúdo binário do arquivo (FileResponse), sem envelope JSON. Quando o anexo não é encontrado, retorna 404 Not Found.

Escopo: modelos:read

GET /modelos/{modelo_id}

Detalha um modelo pelo ID inteiro. Quando não encontrado, retorna 404 Not Found.

Parâmetros

ParâmetroTipoLocalObrigatórioDescrição
modelo_idintpathsimID interno do modelo

Request

Sem corpo de requisição.

Response 200 OK

{
  "success": true,
  "message": "Modelo recuperado com sucesso",
  "data": {
    "id": 42,
    "titulo": "Lembrete DAS mensal",
    "mensagem": "Olá {{nome}}, o DAS de {{mes}} vence em {{vencimento}}.",
    "departamento_id": 3,
    "dia_envio": 20,
    "dia_semana": null,
    "horario_envio": "09:00:00",
    "ajuste_dia_util": "anterior",
    "empresa_ids": [1234, 5678],
    "variaveis": ["nome", "mes", "vencimento"],
    "meses_ativos": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
    "obrigacao_nome": "DAS",
    "recorrencia_ativa": true,
    "telefone_avulso": null,
    "tipo_recorrencia": "mensal",
    "vinculo_mode": "departamento",
    "tipo_midia": null,
    "arquivo_url": null,
    "arquivo_nome": null,
    "legacy_uuid": null,
    "data_hora_criacao": "2026-07-03T09:00:00-03:00",
    "data_hora_atualizacao": "2026-07-03T09:00:00-03:00"
  }
}

Escopo: modelos:read

PUT /modelos/{modelo_id}

Atualiza um modelo existente. O body é um ModeloUpdate com campos parciais - somente o que vier preenchido é alterado.

Parâmetros

ParâmetroTipoLocalObrigatórioDescrição
modelo_idintpathsimID do modelo

Request (ModeloUpdate - todos os campos opcionais)

{
  "titulo": "Lembrete DAS mensal (revisado)",
  "horario_envio": "08:30:00",
  "recorrencia_ativa": false
}

Response 200 OK

{
  "success": true,
  "message": "Modelo atualizado com sucesso",
  "data": {
    "id": 42,
    "titulo": "Lembrete DAS mensal (revisado)",
    "mensagem": "Olá {{nome}}, o DAS de {{mes}} vence em {{vencimento}}.",
    "departamento_id": 3,
    "dia_envio": 20,
    "dia_semana": null,
    "horario_envio": "08:30:00",
    "ajuste_dia_util": "anterior",
    "empresa_ids": [1234, 5678],
    "variaveis": ["nome", "mes", "vencimento"],
    "meses_ativos": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
    "obrigacao_nome": "DAS",
    "recorrencia_ativa": false,
    "telefone_avulso": null,
    "tipo_recorrencia": "mensal",
    "vinculo_mode": "departamento",
    "tipo_midia": null,
    "arquivo_url": null,
    "arquivo_nome": null,
    "legacy_uuid": null,
    "data_hora_criacao": "2026-07-03T09:00:00-03:00",
    "data_hora_atualizacao": "2026-07-03T11:42:00-03:00"
  }
}

Modelo inexistente retorna 404 Not Found; erro de validação retorna 422 Unprocessable Entity.

Escopo: modelos:write

POST /modelos/{modelo_id}/anexo

Envia o anexo (mídia) de um modelo. Requisição multipart/form-data. O arquivo é gravado em <STORAGE_ROOT>/atendimento/modelos-anexos/ e os campos arquivo_url, arquivo_nome e tipo_midia do modelo são atualizados.

Parâmetros

ParâmetroTipoLocalObrigatórioDescrição
modelo_idintpathsimID do modelo

O corpo é enviado como multipart/form-data com os campos:

CampoTipoObrigatórioObservações
tipo_midiastrsimUm de image, video, audio, voice, document.
arquivoUploadFilesimArquivo do anexo (até 50MB).

Request

Corpo multipart/form-data com os campos tipo_midia e arquivo (arquivo binário). Não é JSON.

Response 200 OK

{
  "success": true,
  "message": "Anexo enviado com sucesso",
  "data": {
    "id": 42,
    "titulo": "Lembrete DAS mensal",
    "mensagem": "Olá {{nome}}, o DAS de {{mes}} vence em {{vencimento}}.",
    "departamento_id": 3,
    "dia_envio": 20,
    "dia_semana": null,
    "horario_envio": "09:00:00",
    "ajuste_dia_util": "anterior",
    "empresa_ids": [1234, 5678],
    "variaveis": ["nome", "mes", "vencimento"],
    "meses_ativos": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
    "obrigacao_nome": "DAS",
    "recorrencia_ativa": true,
    "telefone_avulso": null,
    "tipo_recorrencia": "mensal",
    "vinculo_mode": "departamento",
    "tipo_midia": "image",
    "arquivo_url": "/api/v1/modelos/anexo/9f3c2a1e-lembrete.png",
    "arquivo_nome": "lembrete.png",
    "legacy_uuid": null,
    "data_hora_criacao": "2026-07-03T09:00:00-03:00",
    "data_hora_atualizacao": "2026-07-03T12:05:00-03:00"
  }
}

Modelo inexistente retorna 404 Not Found; erro de validação retorna 422 Unprocessable Entity.

Escopo: modelos:write

DELETE /modelos/{modelo_id}

Remove um modelo de lembrete pelo ID. Modelo inexistente retorna 404 Not Found.

Parâmetros

ParâmetroTipoLocalObrigatórioDescrição
modelo_idintpathsimID do modelo

Request

Sem corpo de requisição.

Response 200 OK

{
  "success": true,
  "message": "Modelo removido com sucesso",
  "data": null
}

Escopo: modelos:write

Schemas

ModeloCreate

CampoTipoObrigatórioObservações
titulostrsimTítulo do modelo. Máx. 255 caracteres.
mensagemstrsimTexto da mensagem do lembrete. Suporta variáveis (ex: {{nome}}).
departamento_idint | nullnãoDepartamento vinculado ao modelo.
dia_envioint | nullnãoDia do mês para envio.
dia_semanaint | nullnãoDia da semana para envio.
horario_enviostr | nullnãoHorário de envio (ex: 09:00:00). Máx. 8 caracteres.
ajuste_dia_utilstr | nullnãoAjuste para dia útil (ex: anterior, posterior). Máx. 20 caracteres.
empresa_idslist | nullnãoIDs de empresas/clientes vinculados.
variaveislist | nullnãoVariáveis dinâmicas usadas na mensagem.
meses_ativoslist | nullnãoMeses em que o modelo fica ativo.
obrigacao_nomestr | nullnãoNome da obrigação associada. Máx. 255 caracteres.
recorrencia_ativaboolnãoIndica recorrência ativa. Default false.
telefone_avulsostr | nullnãoTelefone avulso para envio. Máx. 50 caracteres.
tipo_recorrenciastr | nullnãoTipo de recorrência (ex: mensal). Máx. 50 caracteres.
vinculo_modestr | nullnãoModo de vínculo (ex: departamento). Máx. 50 caracteres.
tipo_midiastr | nullnãoTipo da mídia anexada. Máx. 20 caracteres.
arquivo_urlstr | nullnãoURL/caminho do anexo. Máx. 500 caracteres.
arquivo_nomestr | nullnãoNome do arquivo anexado. Máx. 255 caracteres.

ModeloUpdate

Todos os campos são opcionais; apenas os enviados são atualizados. Os campos e limites são os mesmos do ModeloCreate, com a diferença de que recorrencia_ativa também é opcional (bool | null) - quando omitido, permanece inalterado.

ModeloRead

Estende os campos do ModeloCreate com os campos abaixo:

CampoTipoNotas
idintIdentificador do modelo.
legacy_uuidstr | nullUUID de origem legada, quando aplicável.
data_hora_criacaodatetimeTimestamp de criação.
data_hora_atualizacaodatetimeTimestamp da última atualização.

Notas

  • Toda resposta segue o envelope { success, message, data } (ou { success: false, message, details } em erro).
  • GET /modelos/anexo/{nome_disco} é declarado antes da rota dinâmica GET /modelos/{modelo_id}, então anexo é resolvido como rota estática (e não interpretado como um modelo_id).
  • O download (GET /modelos/anexo/{nome_disco}) e o upload (POST /modelos/{modelo_id}/anexo) retornam formatos diferentes: o download devolve o binário do arquivo, enquanto o upload devolve o envelope JSON com o ModeloRead atualizado.

Envio com mídia

Para anexar arquivo a um modelo, use POST /modelos/{modelo_id}/anexo com multipart/form-data. Valores aceitos de tipo_midia: image, video, audio, voice, document. O arquivo é limitado a 50MB.