Skip to content

GET /app/versions

Resumo

Informa ao app mobile se há uma atualização publicada para a plataforma do dispositivo e se a atualização é obrigatória. O app consulta este endpoint ao abrir e ao voltar para foreground, antes mesmo de autenticar.

Auth

Rota pública (@Public() + @SkipCompany()). Não exige token JWT nem header x-company-id. O app pode chamar antes do login.

Query params

CampoTipoObrigatórioDescrição
currentVersionstring (semver)SimVersão nativa instalada
platformios | androidSimPlataforma do dispositivo
runtimeVersionstringNãoRuntime do Expo Updates
updateIdstringNãoID do bundle OTA atual

Resposta

json
{
  "data": {
    "updateAvailable": true,
    "version": {
      "id": "uuid",
      "version": "1.2.0",
      "launchAt": "2026-06-20T12:00:00.000Z",
      "type": "feature",
      "forceUpdate": false,
      "title": "Nova atualização disponível",
      "description": "Texto exibido no modal",
      "storeUrl": "https://apps.apple.com/br/app/contrasync/id6782732793",
      "delivery": "store",
      "minSupportedVersion": "1.0.0",
      "deprecatedAt": null,
      "platform": "ios",
      "createdAt": "2026-06-20T12:00:00.000Z"
    }
  }
}

Quando não houver atualização pendente:

json
{
  "data": {
    "updateAvailable": false,
    "version": null
  }
}
typescript
interface AppVersionCheckResponse {
  data: {
    updateAvailable: boolean;
    version: AppVersion | null;
  };
}

interface AppVersion {
  id: string;
  version: string;
  launchAt: string;
  type: 'feature' | 'bug_fix' | 'release';
  forceUpdate: boolean;
  title: string;
  description: string;
  storeUrl: string | null;
  delivery: 'store' | 'ota';
  minSupportedVersion: string;
  deprecatedAt: string | null;
  platform: 'ios' | 'android';
  createdAt: string;
}

Resolução no backend

  1. Seleciona as versões da platform recebida que já foram lançadas (launchAt <= agora) e não estão removidas (deletedAt = null).
  2. Escolhe a maior version por comparação semver.
  3. updateAvailable = maiorVersao > currentVersion. Se a instalada já for a maior, responde updateAvailable: false e version: null.
  4. Calcula o forceUpdate efetivo da versão retornada (ver abaixo).

Cálculo do forceUpdate

O campo forceUpdate da resposta é computado pelo backend, não simplesmente copiado do registro:

  1. type = bug_fixtrue.
  2. currentVersion < minSupportedVersiontrue (versão instalada abaixo do mínimo suportado).
  3. deprecatedAt definido e já no passado → true.
  4. Caso contrário → o forceUpdate armazenado no registro (false para feature; false para release enquanto suportada).

Tabela app_versions

ColunaTipoNullableNotas
idUUIDnãoPK
versiontextnãoSemver exibida ao usuário
platformAppPlatform (ios | android)nãoUm registro por plataforma
typeAppVersionType (feature | bug_fix | release)não
deliveryAppVersionDelivery (store | ota)nãodefault store
forceUpdatebooleannãodefault false; base do cálculo efetivo
titletextnãoTítulo do modal
descriptiontextnãoTexto do modal
storeUrltextsimURL da loja correspondente à plataforma
minSupportedVersiontextnãoVersão mínima ainda suportada
runtimeVersiontextsimRuntime do bundle (Expo Updates)
updateIdtextsimID do bundle OTA
launchAttimestamptznãoData de publicação
deprecatedAttimestamptzsimA partir desta data, versões antigas deixam de ser aceitas
createdAttimestamptznão
updatedAttimestamptznão
deletedAttimestamptzsimsoft delete

Índice: (platform, launchAt).

Regras de negócio

As regras de produto (tipos de atualização, persistência do adiamento, revalidação no foreground) estão em business/app-versions.md.