← Início
Plataforma Semente — Cadastro de Usuários
Versão 1.0

Cadastro de Usuários — Especificação Técnica

Plataforma Semente

Versão 1.0 — Documento destinado a parceiros integradores

1. Visão Geral

1.1 Objetivo

Este documento especifica como um sistema parceiro deve notificar a Plataforma Semente sobre a criação, atualização e desativação de usuários (alunos e professores), de forma que a base de usuários da Semente permaneça sincronizada com a base do parceiro.

A integração é feita através do envio de eventos, pelo back-end do parceiro, a um endpoint HTTP da Semente. Diferente da Integração SSO, aqui a chamada é sempre servidor-a-servidor — não há geração de token, nem qualquer participação do navegador do usuário final.

1.2 Fluxo Resumido

  1. Um usuário (aluno ou professor) é criado, atualizado ou desativado no sistema do parceiro.
  2. O sistema do parceiro monta um evento contendo os dados desse(s) usuário(s), podendo agrupar vários usuários no mesmo evento.
  3. O parceiro envia o evento via POST ao endpoint de Cadastro de Usuários da Semente, autenticado pelo header apikey.
  4. A Semente valida a apikey e o corpo da requisição.
  5. A Semente processa cada usuário do evento — criando, atualizando ou desativando o cadastro, conforme o campo enabled — e responde com o resultado do processamento.
Importante: Toda a chamada deve partir do back-end do parceiro. A apikey nunca deve ser exposta no front-end, em aplicativos móveis ou em qualquer código acessível ao usuário final.

1.3 Diagrama do Fluxo

O diagrama abaixo ilustra a sequência da integração, sempre servidor-a-servidor entre o back-end do parceiro e a Plataforma Semente:

Sistema do Parceiro Plataforma Semente 1. Usuário criado, atualizado ou desativado no parceiro 2. Monta o evento (event_id, timestamp, payload.users[]) 3. POST /Integracao/User — header apikey + corpo JSON 4. Validações (apikey e JSON) 5. Processa usuários (cria / atualiza / desativa cada um) 6. 200 — resultado do processamento de cada usuário Se a validação do passo 4 falhar: a Semente responde com erro (400, 401 ou 404) ao parceiro e nenhum usuário do evento é processado. Veja os códigos possíveis na seção 4.4.

Caso a apikey seja inválida ou o corpo da requisição esteja malformado, a Semente responde com erro diretamente na chamada — o parceiro deve tratar essa resposta antes de considerar o evento como processado.

2. Pré-requisitos

2.1 Dados fornecidos pela Semente

Antes de iniciar a implementação, a Semente fornecerá ao parceiro, por canal seguro, o seguinte dado:

  • apikey: chave de identificação única da instituição parceira, enviada no header apikey em toda requisição.
Atenção: A apikey deve ser armazenada de forma segura (cofre de segredos, variável de ambiente protegida, etc.) e nunca deve ser versionada em repositórios de código.
Sem assinatura de payload: Diferente da Integração SSO (que usa um token JWT assinado com HMAC-SHA256), esta integração autentica a requisição apenas pelo header apikey — não há assinatura criptográfica do corpo da requisição.

3. Especificação do Evento

Cada requisição enviada ao endpoint representa um evento, contendo um ou mais usuários a serem sincronizados. O corpo da requisição é um JSON com a estrutura descrita a seguir.

3.1 Estrutura do Payload

Estrutura do evento
{
  "event_id": "evt_123456",
  "timestamp": "2026-01-21T14:30:00Z",
  "payload": {
    "users": [
      { "...": "ver seção 3.2" }
    ]
  }
}
CampoTipoObrigatórioDescrição
event_idstringSimIdentificador único do evento, definido pelo parceiro.
timestampstringSimData e hora do evento, em formato ISO 8601.
payload.usersarraySimLista de usuários a serem processados neste evento (ver seção 3.2). Pode conter um ou vários usuários.

3.2 Campos do Usuário

Cada item da lista payload.users representa um aluno ou professor:

CampoTipoObrigatórioDescrição
user_idstringSimIdentificador externo do usuário, definido pelo parceiro.
nomestringSimNome completo do usuário.
loginstringSimLogin de acesso do usuário na Plataforma Semente.
senhastringSimSenha inicial do usuário.
emailstringCondicionalEmail do usuário. Ver regra de obrigatoriedade na seção 3.4.
enabledstringSimStatus do usuário: ativar ou excluir. Ver semântica de criação/atualização/exclusão na seção 3.5.
rolestringSimPerfil do usuário: aluno ou professor.
generostringSimGênero: masculino, feminino ou não informar.
telefonestringCondicionalTelefone do usuário. Obrigatório se email não for informado — ver seção 3.4.
seriestringSimSérie/Ano do usuário (ex.: "6º Ano").
turmastringSimNome da turma do usuário (ex.: "Turma 2"). Os nomes válidos de turmas da instituição podem ser obtidos através do endpoint de Listagem de Turmas Ativas.
send_emailstringSimEnviar email de boas-vindas: sim ou não.

3.3 Professor Aplicador

Quando role for professor, dois campos adicionais indicam se ele é um professor aplicador — ou seja, se aplica atividades em turmas além da sua própria:

CampoTipoObrigatórioDescrição
applierstringCondicionalIndica se o professor é aplicador: sim ou não. Aplicável apenas quando role for professor.
appliesarrayCondicionalLista de séries e turmas que o professor aplica, cada item com serie e turma. Obrigatório quando applier for sim.
Exemplo — professor aplicador
{
  "user_id": "prof_001",
  "role": "professor",
  "applier": "sim",
  "applies": [
    { "serie": "6º Ano", "turma": "Turma 2" }
  ]
}

3.4 Regras de Obrigatoriedade

  • Pelo menos um entre email e telefone deve ser informado para cada usuário. Se email não for enviado (ou for enviado em branco), telefone passa a ser obrigatório.
  • applier e applies só se aplicam quando role for professor; para role: "aluno", esses campos não são necessários.
  • applies só é obrigatório quando applier for "sim".

3.5 Criação, Atualização e Exclusão

O mesmo endpoint atende os três casos — criação, atualização e exclusão de usuário — sem a necessidade de rotas ou eventos distintos. O campo login funciona como chave de identificação do usuário na Plataforma Semente:

  • Se o login enviado ainda não existe na base da Semente, o usuário é criado com os dados informados.
  • Se o login enviado já existe, o usuário é atualizado — todos os campos enviados no evento sobrescrevem os valores atualmente cadastrados para esse usuário.
Atualização é uma sobrescrita completa: Ao atualizar um usuário existente, envie sempre o conjunto completo de campos com os valores corretos — não apenas os que mudaram. Campos não enviados corretamente podem sobrescrever dados válidos já cadastrados.

A exclusão de usuário é feita de forma lógica (soft delete), através do campo enabled: ao enviar um evento para um login existente com enabled igual a excluir, a Semente marca esse usuário como desativado, sem removê-lo fisicamente da base.

4. Endpoint de Integração

4.1 URL e Método

A requisição HTTP POST com o evento deve ser enviada para:

Endpoint
POST https://sementemvc.azurewebsites.net/Integracao/User
Chamada servidor-a-servidor: Essa requisição deve partir do back-end do parceiro. Diferente da Integração SSO, aqui não há envolvimento do navegador do usuário final.

4.2 Headers Obrigatórios

HeaderValorDescrição
apikey<apikey fornecida pela Semente>Identifica a instituição parceira que está enviando o evento.
Content-Typeapplication/jsonCorpo da requisição enviado como JSON.

4.3 Formato da Requisição

Exemplo de evento contendo um aluno e um professor aplicador:

Requisição
POST /Integracao/User HTTP/1.1
Host: sementemvc.azurewebsites.net
apikey: SUA_APIKEY
Content-Type: application/json

{
  "event_id": "evt_123456",
  "timestamp": "2026-01-21T14:30:00Z",
  "payload": {
    "users": [
      {
        "user_id": "aluno_001",
        "nome": "Aluno Integração",
        "login": "aluno-integracao",
        "senha": "123456",
        "email": "aluno_integracao@escola.com",
        "enabled": "ativar",
        "role": "aluno",
        "genero": "masculino",
        "telefone": "11955555555",
        "serie": "6º Ano",
        "turma": "Turma 2",
        "send_email": "não"
      },
      {
        "user_id": "prof_001",
        "nome": "Professor Integração",
        "login": "prof-integracao",
        "senha": "123456",
        "email": "prof_integracao@escola.com",
        "enabled": "ativar",
        "role": "professor",
        "genero": "masculino",
        "telefone": "11955555555",
        "serie": "Adultos",
        "turma": "adultos",
        "send_email": "não",
        "applier": "sim",
        "applies": [
          { "serie": "6º Ano", "turma": "Turma 2" }
        ]
      }
    ]
  }
}

4.4 Respostas

Em caso de sucesso, a Semente aceita e processa o evento:

200 OK
HTTP/1.1 200 OK
Content-Type: application/json

{
  "...": "resultado do processamento de cada usuário do evento"
}
Formato do retorno de sucesso ainda sujeito a confirmação: O corpo da resposta 200 pode conter usuários que precisaram de ajuste (por exemplo, dados inconsistentes), mas a estrutura exata desse JSON ainda não está fechada. Trate o corpo do 200 como informativo e confirme o contrato mais atualizado com o time técnico da Semente antes de depender dele em produção.

Em caso de falha:

HTTPSituaçãoDescrição
200SucessoEvento aceito e processado. Ver observação acima sobre o corpo da resposta.
400Requisição inválidaCorpo da requisição em JSON malformado.
401Não autorizadoAssinatura inválida.
404Não encontradoApiKey inválida (não corresponde a nenhuma instituição cadastrada).
Sobre o 401 "Assinatura inválida": Apesar do texto de erro mencionar "assinatura", esta integração autentica a requisição apenas pelo header apikey (ver seção 2.1) — não há assinatura de payload a ser gerada pelo parceiro. Esse é o texto retornado pelo endpoint quando a apikey enviada não é aceita.

5. Exemplos de Chamada

A seguir, exemplos de como montar e enviar a requisição nas linguagens mais comuns, usando apenas bibliotecas padrão (sem dependências externas).

5.1 C# (.NET)

Biblioteca: System.Net.Http (nativa, sem dependências adicionais).

C#
using System.Net.Http;
using System.Text;

// apikey é fornecida pela Semente no provisionamento
string apikey = "SUA_APIKEY";
string url = "https://sementemvc.azurewebsites.net/Integracao/User";

string json = """
{
  "event_id": "evt_123456",
  "timestamp": "2026-01-21T14:30:00Z",
  "payload": {
    "users": [
      {
        "user_id": "aluno_001",
        "nome": "Aluno Integração",
        "login": "aluno-integracao",
        "senha": "123456",
        "email": "aluno_integracao@escola.com",
        "enabled": "ativar",
        "role": "aluno",
        "genero": "masculino",
        "telefone": "11955555555",
        "serie": "6º Ano",
        "turma": "Turma 2",
        "send_email": "não"
      }
    ]
  }
}
""";

using var client = new HttpClient();
client.DefaultRequestHeaders.Add("apikey", apikey);

var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);

5.2 Python

Biblioteca: requests (pip install requests).

Python
import requests

# apikey é fornecida pela Semente no provisionamento
apikey = "SUA_APIKEY"
url = "https://sementemvc.azurewebsites.net/Integracao/User"

body = {
    "event_id": "evt_123456",
    "timestamp": "2026-01-21T14:30:00Z",
    "payload": {
        "users": [
            {
                "user_id": "aluno_001",
                "nome": "Aluno Integração",
                "login": "aluno-integracao",
                "senha": "123456",
                "email": "aluno_integracao@escola.com",
                "enabled": "ativar",
                "role": "aluno",
                "genero": "masculino",
                "telefone": "11955555555",
                "serie": "6º Ano",
                "turma": "Turma 2",
                "send_email": "não"
            }
        ]
    }
}

response = requests.post(url, json=body, headers={"apikey": apikey})

5.3 Java

Biblioteca: java.net.http.HttpClient (nativa a partir do JDK 11).

Java
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

// apikey é fornecida pela Semente no provisionamento
String apikey = "SUA_APIKEY";
String url = "https://sementemvc.azurewebsites.net/Integracao/User";

String json = """
{
  "event_id": "evt_123456",
  "timestamp": "2026-01-21T14:30:00Z",
  "payload": {
    "users": [
      {
        "user_id": "aluno_001",
        "nome": "Aluno Integração",
        "login": "aluno-integracao",
        "senha": "123456",
        "email": "aluno_integracao@escola.com",
        "enabled": "ativar",
        "role": "aluno",
        "genero": "masculino",
        "telefone": "11955555555",
        "serie": "6º Ano",
        "turma": "Turma 2",
        "send_email": "não"
      }
    ]
  }
}
""";

HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
        .uri(URI.create(url))
        .header("apikey", apikey)
        .header("Content-Type", "application/json")
        .POST(HttpRequest.BodyPublishers.ofString(json))
        .build();

HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());

5.4 Node.js

fetch nativo (Node.js 18+, sem dependências adicionais).

Node.js
// apikey é fornecida pela Semente no provisionamento
const apikey = "SUA_APIKEY";
const url = "https://sementemvc.azurewebsites.net/Integracao/User";

const body = {
  event_id: "evt_123456",
  timestamp: "2026-01-21T14:30:00Z",
  payload: {
    users: [
      {
        user_id: "aluno_001",
        nome: "Aluno Integração",
        login: "aluno-integracao",
        senha: "123456",
        email: "aluno_integracao@escola.com",
        enabled: "ativar",
        role: "aluno",
        genero: "masculino",
        telefone: "11955555555",
        serie: "6º Ano",
        turma: "Turma 2",
        send_email: "não"
      }
    ]
  }
};

const response = await fetch(url, {
  method: "POST",
  headers: { "apikey": apikey, "Content-Type": "application/json" },
  body: JSON.stringify(body)
});

5.5 PHP

Extensão: curl (nativa em praticamente qualquer instalação PHP).

PHP
<?php

// apikey é fornecida pela Semente no provisionamento
$apikey = "SUA_APIKEY";
$url = "https://sementemvc.azurewebsites.net/Integracao/User";

$body = [
    "event_id" => "evt_123456",
    "timestamp" => "2026-01-21T14:30:00Z",
    "payload" => [
        "users" => [
            [
                "user_id" => "aluno_001",
                "nome" => "Aluno Integração",
                "login" => "aluno-integracao",
                "senha" => "123456",
                "email" => "aluno_integracao@escola.com",
                "enabled" => "ativar",
                "role" => "aluno",
                "genero" => "masculino",
                "telefone" => "11955555555",
                "serie" => "6º Ano",
                "turma" => "Turma 2",
                "send_email" => "não"
            ]
        ]
    ]
];

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($body));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    "apikey: {$apikey}",
    "Content-Type: application/json"
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($ch);
curl_close($ch);

6. Checklist de Implementação

7. Perguntas Frequentes

Sim. O campo payload.users é uma lista — é possível enviar um ou vários usuários no mesmo evento.
Envie o mesmo formato de evento com o campo enabled do usuário definido como "excluir".
Não. Pelo menos um dos dois é obrigatório — se o email não for informado, o telefone passa a ser obrigatório (seção 3.4).
Quando applier for "não", o campo applies não é necessário.
Esse contrato ainda está sujeito a confirmação com o time técnico da Semente. Esta documentação será atualizada assim que o formato estiver fechado.
Entre em contato com o time técnico da Semente através do canal combinado no momento do provisionamento da apikey.