API do Énóis

Construa clientes, ferramentas e integrações para o Énóis. Esta é a documentação oficial.

Filosofia

A API existe para ampliar o acesso à informação e automatizar processos — nunca para fabricar interação social. Publicar conteúdo automaticamente (IA, bots, integrações) é proibido; criar e agendar posts pela funcionalidade oficial, com você no controle, é permitido.

Começando

Todas as rotas ficam sob https://enois.ia.br/api Respostas JSON. Timestamps em UTC (ISO-8601). Identificadores são estáveis (prefixados por tipo).

Tudo sob a mesma base da API. As rotas de leitura pública não pedem credencial; as demais usam a sessão do Énóis no header X-Session-Token — o mesmo token que o app usa, obtido no login.

# 1. Autentique-se (o mesmo token que o app usa)
curl -X POST https://enois.ia.br/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email":"ada@exemplo.com","password":"senha-forte-1"}'

# 2. Autentique cada chamada com a sessao
curl https://enois.ia.br/api/me -H "X-Session-Token: <token>"

Sem sessão você já consegue: ler post público e comentários, listar comunidades e o feed delas, vagas (com a origem), eventos, mentores, ranking, busca e estatísticas. Escrever (postar, comentar, reagir, denunciar…) pede a sessão de uma conta real.

Paginação

Listas paginam por cursor (não por offset). Use o nextCursor da resposta anterior:

GET https://enois.ia.br/api/feed/posts/$POST_ID/comments?limit=20
GET ...?cursor=<nextCursor>&limit=20

Erros

Erros têm código e mensagem estáveis, e o HTTP status correspondente:

{"code":"UNAUTHENTICATED","message":"Sessao invalida ou expirada.",
 "timestamp":"2026-10-17T14:20:39Z"}
HTTPcódigoquando
400BAD_REQUESTcorpo inválido (e Idempotency-Key ausente onde é exigida)
401UNAUTHENTICATEDsem sessão, sessão expirada ou token forjado
403FORBIDDEN / ACCOUNT_RESTRICTED / ACCOUNT_BANNEDsem permissão; conta restrita ou banida
404NOT_FOUNDrecurso inexistente (ou de outra pessoa)
409CONFLICT / ALREADY_REPORTED / APPEAL_ALREADY_PENDINGestado atual não permite a operação
422INVALID_COMMENTregra de conteúdo violada
429RATE_LIMITEDlimite de requisições excedido

Há limites de tamanho e de taxa por operação. Operações de escrita aceitam Idempotency-Key para você repetir com segurança sem duplicar. Operações de escrita aceitam Idempotency-Key: repita a chamada com a mesma chave e a operação não duplica. Em algumas rotas de escrita a chave é obrigatória.

Autenticação e conta

A sessão do Énóis é o mesmo token que o app usa. Cadastro nasce pendente de confirmação de e-mail; login responde o token que autentica todas as outras rotas pelo header X-Session-Token. Contas com segundo fator respondem um desafio (202) em vez do token.

POST/auth/signuppúblico

Cria a conta (18+, termos aceitos). O cadastro não emite sessão: envia e-mail de confirmação.

requisição

curl -X POST https://enois.ia.br/api/auth/signup \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: signup-1" \
  -d '{"name":"Ada","email":"ada@exemplo.com","password":"senha-forte-1","acceptedTerms":true}'

resposta

201 Created
{"id":"user_…","email":"ada@exemplo.com","emailVerified":false}
POST/auth/email/verifypúblico

Confirma o e-mail com o token do link recebido. Depois disso o login funciona.

requisição

curl -X POST https://enois.ia.br/api/auth/email/verify \
  -H "Content-Type: application/json" \
  -d '{"token":"<token-do-email>"}'
POST/auth/loginpúblico

Autentica com e-mail e senha e devolve a sessão. Com 2FA ativo, devolve 202 + desafio (conclua em /auth/2fa/verify).

requisição

curl -X POST https://enois.ia.br/api/auth/login \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: login-1" \
  -d '{"email":"ada@exemplo.com","password":"senha-forte-1"}'

resposta

200 OK
{"token":"sess_…","refreshToken":"…","user":{"id":"user_…","name":"Ada","username":"ada"}}
POST/auth/2fa/verifypúblico

Conclui o login com o código do segundo fator (app autenticador ou e-mail).

resposta

200 OK
{"token":"sess_…","refreshToken":"…"}
POST/auth/logoutcom sessão

Encerra a sessão atual.

GET/mecom sessão

Perfil próprio: dados completos, reputação, estado de verificação e preferências.

Feed e publicações

Leitura de publicação e comentários é pública (links compartilhados abrem sem conta). Escrever exige sessão. Posts podem ter mídia (mediaIds) e página em HTML (type PAGE, pageHtml) — a página renderiza em quadro isolado, sem script.

GET/feedcom sessão

Feed pessoal por aba: FOR_YOU (comunidades que você participa + posts fora de comunidade), FOLLOWING, ALL, DISCUSSIONS, RECENT, PROJECTS. Pagina por cursor.

requisição

curl "https://enois.ia.br/api/feed?tab=FOR_YOU&limit=20" \
  -H "X-Session-Token: $TOKEN"

resposta

200 OK
{"items":[{"id":"post_…","type":"INSIGHT","content":"…","counters":{"reactions":26,"comments":23,"saves":3,"shares":4},"createdAt":"2026-10-15T02:16:48Z"}],"nextCursor":"2026-10-15T02:16:48Z"}
GET/feed/posts/{postId}público

Publicação completa: autor, contadores, mídia, comunidade (quando houver).

requisição

curl https://enois.ia.br/api/feed/posts/post_396a12bc2bc54ad3966829c751acb021

resposta

200 OK
{"id":"post_396a12bc…","authorId":"user_…","authorUsername":"aminadojava",
 "type":"INSIGHT","content":"Pessoal. Post pra coletar ideias…","tags":[],"mediaIds":[],
 "createdAt":"2026-10-15T02:16:48Z",
 "counters":{"reactions":26,"comments":23,"saves":3,"shares":4},
 "currentUserReaction":null,"communityId":null,"community":null}
GET/users/{username}/postspúblico

Publicações de uma pessoa (perfil público).

requisição

curl "https://enois.ia.br/api/users/aminadojava/posts?limit=10"
POST/feed/postscom sessão

Publica. type: INSIGHT | QUESTION | PROJECT | PAGE. Média vai por mediaIds (ver Mídia); PAGE leva pageHtml. Em comunidades, mande communityId.

requisição

curl -X POST https://enois.ia.br/api/feed/posts \
  -H "X-Session-Token: $TOKEN" -H "Idempotency-Key: post-1" \
  -H "Content-Type: application/json" \
  -d '{"type":"INSIGHT","content":"Texto do post","tags":["java"],"mediaIds":[],"mentionedUserIds":[]}'

resposta

201 Created
{"id":"post_…","content":"Texto do post","createdAt":"…"}
PATCH/feed/posts/{postId}com sessão

Edita o próprio post (marca como editado).

DELETE/feed/posts/{postId}com sessão

Exclui o próprio post (soft delete). POST /feed/posts/{postId}/restore desfaz; bulk-delete para vários.

POST/feed/posts/{postId}/commentscom sessão

Comenta. Para responder, mande parentCommentId. Aceita até 4 mídias (mediaIds) — comentário pode ser só de mídia.

requisição

curl -X POST https://enois.ia.br/api/feed/posts/$POST_ID/comments \
  -H "X-Session-Token: $TOKEN" -H "Idempotency-Key: c-1" \
  -H "Content-Type: application/json" \
  -d '{"content":"Concordo!","parentCommentId":null,"mediaIds":[],"mentionedUserIds":[]}'

resposta

201 Created
{"id":"comment_…","postId":"post_…","content":"Concordo!","mediaIds":[],"createdAt":"…"}
GET/feed/posts/{postId}/commentspúblico

Comentários (mais recentes primeiro), com respostas aninhadas por parentCommentId.

requisição

curl "https://enois.ia.br/api/feed/posts/$POST_ID/comments?limit=20"

resposta

200 OK
{"items":[{"id":"comment_…","authorUsername":"sergio-de-souza-tomas",
  "content":"Opa eu notei que agora dá pra editar…","mediaIds":[],"createdAt":"2026-10-15T22:03:52Z"}],
 "nextCursor":"2026-10-15T22:03:52Z"}
POST/feed/posts/{postId}/reactionscom sessão

Reage ao post. Tipos: LIKE, LOVE, LAUGH, ROFL, WOW, SAD, ANGRY, DISGUST, SKEPTICAL, CELEBRATE, SUPPORT, INSIGHTFUL. Reagir de novo troca o tipo; DELETE remove. Mesmos verbos em …/comments/{commentId}/reactions.

requisição

curl -X POST https://enois.ia.br/api/feed/posts/$POST_ID/reactions \
  -H "X-Session-Token: $TOKEN" -H "Idempotency-Key: r-1" \
  -H "Content-Type: application/json" -d '{"type":"INSIGHTFUL"}'
GET/feed/posts/{postId}/reactionspúblico

Totais por tipo de reação.

POST/feed/posts/{postId}/savescom sessão

Salva o post (DELETE remove). Lista em GET /feed/saved.

POST/feed/posts/{postId}/sharescom sessão

Registra compartilhamento (contador).

Busca

Busca unificada por pessoas, publicações, comunidades e vagas.

GET/searchpúblico

Busca por termo livre. Cada item tem type (users, posts, communities, jobs) e pode ser filtrado/roteado pelo cliente.

requisição

curl "https://enois.ia.br/api/search?q=java&limit=10"

resposta

200 OK
{"items":[{"id":"user_…","type":"users","title":"JavaScript-chan","subtitle":"…","image":"…"}],
 "nextCursor":null}

Perfis e ranking

Perfis públicos com experiência, formação, certificações e emblema. O ranking é calculado pela plataforma (reputação/atividade) e é público.

GET/users/{username}público

Perfil público: headline, empresa, skills, experiências, emblema, capa em HTML (bannerHtml).

requisição

curl https://enois.ia.br/api/users/aminadojava

resposta

200 OK
{"id":"user_…","username":"aminadojava","name":"melissa monfre dos santos",
 "headline":"…","company":"…","skills":[…],"bioHtml":null,"bannerHtml":null,"openToWork":false}
GET/users/by-id/{userId}público

Perfil por id.

GET/profile/rankingpúblico

Ranking de perfis mais relevantes da rede.

requisição

curl https://enois.ia.br/api/profile/ranking

resposta

200 OK
[{"id":"user_…","username":"lucas-matheus-florentino","name":"Lucas Matheus Florentino","skills":[…]}]
PATCH/me/profilecom sessão

Edita o próprio perfil (nome, headline, skills, bio, bioHtml, bannerHtml, emblema…). Experiências, educação e certificações têm CRUD próprio em /me/experiences, /me/education, /me/certifications.

Comunidades

Listagem, detalhe e feed de comunidade são públicos; entrar, publicar e administrar pedem sessão. A capa pode ser foto (cover) ou HTML/CSS (bannerHtml) — mesma tubulação da capa de perfil.

GET/communitiespúblico

Lista comunidades (topic para filtrar, cursor para paginar). Com sessão, joined reflete participação.

requisição

curl "https://enois.ia.br/api/communities?limit=10"

resposta

200 OK
{"items":[{"id":"community_…","name":"Muita IA pouco $","description":"…","members":1,
 "topic":"TECNOLOGIA","cover":null,"bannerHtml":null,"joined":false}],"nextCursor":null}
GET/communities/{communityId}público

Detalhe da comunidade.

GET/communities/{communityId}/feedpúblico

Feed de publicações da comunidade (mesma forma do feed).

GET/communities/{communityId}/memberspúblico

Membros e papéis (ADMIN).

POST/communities/{communityId}/memberscom sessão

Entra na comunidade (DELETE sai). Publicar nela: POST /feed/posts com communityId.

POST/communitiescom sessão

Cria comunidade (o criador vira ADMIN). PATCH edita; /transfer passa a administração; /favorite + /favorites para favoritas.

Vagas

Vagas internas (criadas na plataforma) e externas convivem na mesma listagem. Externas têm id com prefixo ext_, selo de plataforma (sourcePlatform) e URL da origem (sourceUrl) — o redirecionamento é sempre para quem publicou a vaga. Busca booleana: AND, OR, NOT, "frase exata" e parênteses no parâmetro query.

GET/jobspúblico

Lista vagas. query (busca booleana no título), type, level, location e skills filtram só as internas (estruturais); sem filtros estruturais, externas entram junto.

requisição

curl "https://enois.ia.br/api/jobs?query=java%20AND%20remoto&limit=20"

resposta

200 OK
{"items":[{"id":"ext_Remotive_2091144","title":"Content Reviewer - United States","company":"TELUS Digital",
 "location":"USA","postedAt":"2026-10-17T04:00:49Z","sourcePlatform":"Remotive",
 "sourceUrl":"https://remotive.com/remote-jobs/…"}],"nextCursor":null}
GET/jobs/{jobId}público

Detalhe da vaga (interna ou externa).

POST/jobscom sessão

Publica vaga (reputação >= 150). PATCH edita, /close encerra, DELETE exclui. Candidaturas: POST /jobs/{id}/applications; status em PATCH /jobs/{id}/applications/{applicationId}; minhas candidaturas em GET /jobs/applications.

GET/jobs/applicationscom sessão

Candidaturas do próprio usuário (e as recebidas em GET /jobs/{jobId}/applications, para quem publicou).

Eventos

Vitrine de eventos profissionais. Eventos passados saem da vitrine e recusam RSVP; presença vira número agregado após 24h.

GET/eventspúblico

Lista eventos (vitrine).

resposta

200 OK
{"items":[{"id":"event_…","title":"…","date":"2029-12-31","time":"23:59","format":"ONLINE","attendees":2}]}
GET/events/{eventId}público

Detalhe do evento.

POST/eventscom sessão

Cria evento.

POST/events/{eventId}/attendeescom sessão

Confirma presença (DELETE cancela).

Mentoria

Mentores publicam horários livres; quem quer aprender pede sessão em um slot.

GET/mentorspúblico

Mentores e expertises.

resposta

200 OK
{"items":[{"id":"mentor_…","expertise":["Pentest","RedTeam","Certificações"]}]}
GET/mentors/{mentorId}/slotspúblico

Horários livres do mentor.

POST/mentorscom sessão

Torna-se mentor; POST /mentors/{id}/slots publica horários; /sessions pede/agenda sessão.

Estatísticas

Números públicos e agregados da rede — sem dado pessoal.

GET/stats/communitypúblico

Usuários ativos (janela de 30 dias) e total da rede.

requisição

curl https://enois.ia.br/api/stats/community

resposta

200 OK
{"activeUsers":1031,"totalUsers":1370,"windowDays":30,"computedAt":"2026-10-17T14:20:39Z"}

Rede (conexões e bloqueios)

Conexões bidirecionais com aceite; bloqueio é permanente e esconde os dois lados do feed, comentários, busca e sugestões.

GET/network/summarycom sessão

Resumo da sua rede (conexões, pendentes).

GET/network/suggestionscom sessão

Sugestões por afinidade (não por volume).

GET/network/requestscom sessão

Pedidos de conexão recebidos.

POST/network/connections/{targetUserId}com sessão

Pedir conexão (PUT …/accept aceita; GET …/status consulta; DELETE desfaz).

POST/network/blocks/{targetUserId}com sessão

Bloqueia (DELETE desbloqueia; GET /network/blocks lista).

Mensagens

Conversas diretas e de comunidade. Tudo aqui pede sessão — nada de mensagens é público.

GET/conversationscom sessão

Suas conversas (GET /conversations/search busca dentro delas).

GET/conversations/{id}/messagescom sessão

Mensagens da conversa.

POST/conversations/{id}/messagescom sessão

Envia mensagem (reações em …/messages/{messageId}/reactions).

POST/conversations/directcom sessão

Abre (ou recupera) a conversa direta com alguém.

POST/conversations/{id}/readcom sessão

Marca como lida; /hide apaga para você (o outro lado mantém).

Notificações e push

Notificações no app e no celular (Web Push). Cada notificação traz href de destino no formato /api/….

GET/notificationscom sessão

Notificações do usuário (cursor).

GET/push/configpúblico

Chaves públicas para assinar Web Push.

POST/push/subscriptionscom sessão

Registra a assinatura push do navegador (DELETE remove).

Mídia

Upload em três passos: (1) pede a assinatura; (2) sobe o arquivo no endereço que a resposta indicar (S3 = PUT direto na signedUrl com os headers dados; ImageKit = multipart); (3) usa o mediaId no post/comentário/perfil. Ninguém precisa de chave de terceiros — a plataforma assina.

POST/media/uploadscom sessão

Passo 1. purpose: POST_IMAGE | POST_VIDEO | AVATAR | BANNER | COVER. Teto de 500MB por arquivo (URL assinada vale 60 minutos).

requisição

curl -X POST https://enois.ia.br/api/media/uploads \
  -H "X-Session-Token: $TOKEN" -H "Idempotency-Key: up-1" \
  -H "Content-Type: application/json" \
  -d '{"fileName":"media/abc/foto.png","mimeType":"image/png","size":10240,"purpose":"POST_IMAGE"}'

resposta

201 Created
{"id":"media_…","cdnUrl":"https://…","uploadUrl":"https://…(assinada)","provider":"S3","uploadHeaders":{…}}
GET/media/{mediaId}público

Passo 3 (leitura): metadados + cdnUrl para renderizar.

DELETE/media/{mediaId}com sessão

Remove a mídia do dono.

Denúncias, moderação e recursos

Qualquer pessoa autenticada pode denunciar conteúdo; cada denúncia avisa o suporte por e-mail. Um sistema automático pré-tri por IA e, só em violação grave e inequívoca, restringe o autor — que pode recorrer. A decisão final é sempre humana: recurso aceito remove a restrição; negado converte em banimento.

POST/reportscom sessão

Denuncia. targetType: POST | COMMENT | USER | JOB; reason: AI_GENERATED, FAKE_CONTENT, SCAM, DISCRIMINATION, PREJUDICE, HARASSMENT, SPAM, VIOLENCE, COPYRIGHT, OTHER.

requisição

curl -X POST https://enois.ia.br/api/reports \
  -H "X-Session-Token: $TOKEN" -H "Idempotency-Key: rep-1" \
  -H "Content-Type: application/json" \
  -d '{"targetType":"POST","targetId":"post_…","reason":"SCAM","description":"Parece golpe de investimento"}'

resposta

201 Created
{"id":"report_…","targetType":"POST","reason":"SCAM","status":"PENDING","createdAt":"…"}
GET/reports/minecom sessão

Denúncias que VOCÊ fez (acompanhamento; sem dados de terceiros).

GET/me/sanctionscom sessão

Penalidades da sua conta e o estado dos seus recursos.

resposta

200 OK
{"sanctions":[{"id":"sanc_…","type":"RESTRICTION","status":"ACTIVE","reason":"…","createdAt":"…"}],
 "appeals":[{"id":"appl_…","status":"PENDING","message":"…"}]}
POST/me/sanctions/appealscom sessão

Recorre da restrição ativa (um recurso pendente por vez; humano decide).

requisição

curl -X POST https://enois.ia.br/api/me/sanctions/appeals \
  -H "X-Session-Token: $TOKEN" -H "Content-Type: application/json" \
  -d '{"message":"Foi discussão técnica, não discriminação."}'
GET/admin/reportsadmin

Fila de denúncias (approve aplica penalidade e remove conteúdo; dismiss arquiva).

GET/admin/appealsadmin

Fila de recursos. POST /admin/appeals/{id}/approve libera; /deny converte em banimento (sessões revogadas).

Suporte e conta

Canal de suporte responde por e-mail e fica no painel admin; exclusão de conta anonimiza o conteúdo (nada de dado pessoal órfão).

GET/support/configpúblico

Se o canal de suporte está aberto (e o e-mail público, quando houver).

POST/support/requestscom sessão

Abre pedido de suporte (vai por e-mail ao time + fila /admin/support).

PUT/me/themecom sessão

Preferências de tema que acompanham a conta entre dispositivos.

Temas (galeria da comunidade)

Pacotes de TOKENS validados por schema e com gate de contraste (>= 4.5:1) — sem CSS livre. O pacote é JSON; a instalação aplica na hora e a conta guarda o tema como preferência.

GET/temas/galeria?limit=60público

Lista os temas publicados (mais recentes primeiro).

resposta

[{"id":"tema_…","name":"Bruma Silenciosa","description":"…","packageJson":"{"palette":…}","modeDefault":"light","installs":12,"createdAt":"2026-10-17T18:20:11Z"}]
GET/temas/galeria/{themeId}público

Um tema específico com o pacote completo.

POST/temas/galeriacom sessão

Publica um tema (o gate de contraste recusa pacote ilegível com THEME_CONTRAST_LOW). Exige Idempotency-Key.

requisição

{"name":"Meu Tema","description":"Cores da minha comunidade","modeDefault":"light",
 "packageJson":"{"palette":{"background":"#f5e6c8",…}}"}

resposta

{"id":"tema_…","status":"PUBLISHED"}
GET/temas/galeria/minecom sessão

Os seus temas, em qualquer estado.

POST/temas/galeria/{themeId}/installcom sessão

Instala na conta (conta a métrica de installs).

POST/temas/galeria/{themeId}/reportcom sessão

Denuncia o tema para moderação.

POST/temas/galeria/{themeId}/hidecom sessão

O autor esconde o próprio tema.

Faísca (carteira e cotação)

A moeda interna é FRACIONADA: o ledger inteiro conta milésimos — 1 faísca = 1.000 mf (como os centavos do real). A cotação de REFERÊNCIA em BRL é publicada pela plataforma e financia a remuneração de criadores; não é câmbio — comprar faísca com dinheiro não existe. Transferências são estilo Pix: por username, instantâneas e irreversíveis, com Idempotency-Key obrigatória.

GET/coin/cotacaopúblico

A cotação de referência vigente + histórico (alimenta a mini bolsa). O total em circulação não é público.

resposta

{"brlCents":1,"escala":1000,"atualizadaEm":"2026-10-18T10:00:00Z",
 "historico":[{"brlCents":1,"em":"2026-10-18T10:00:00Z"}]}
POST/coin/cotacaoadmin

Publica nova cotação de referência (em centavos por 1 faísca).

requisição

{"brlCents":2,"note":"reajuste de referência"}

resposta

{"brlCents":2,"em":"2026-10-18T10:05:00Z"}
GET/carteiracom sessão

Saldo, chave (username) e extrato. A primeira abertura executa o genesis idempotente (100 faíscas) e marca a presença do dia.

resposta

{"balance":105000,"escala":1000,"cotacaoBrlCents":1,"chave":"ada-silva",
 "entries":[{"amount":5000,"kind":"REWARD","message":"Presença diária","createdAt":"2026-10-18T10:00:00Z"},
 {"amount":100000,"kind":"AIRDROP","message":"Distribuição inicial","createdAt":"2026-10-18T09:59:59Z"}]}
POST/carteira/transferenciascom sessão

Envia faíscas por username (amount em milésimos). Idempotency-Key obrigatória: o replay com a MESMA chave não duplica; com payload diferente, conflita.

requisição

{"toUsername":"joao-silva","amount":1500,"message":"pelo mockup lindo"}

resposta

{"status":"SENT","amount":1500,"toUsername":"joao-silva"}

Jogos (agregador)

O Énóis NÃO hospeda jogos: o criador envia o LINK de onde o jogo já está publicado (itch.io, site próprio), a moderação revisa, e o jogo roda EMBUTIDO num quadro isolado no app. A página do criador é pública em /games/{username}.

GET/games?limit=60público

Catálogo de jogos publicados.

resposta

[{"id":"game_…","userId":"user_…","username":"ada-silva","slug":"kawaii-survivors","title":"Kawaii Survivors",
 "description":"Survivor fofo com pixel art.","url":"https://ada.itch.io/kawaii","tags":"arcade,pixel","status":"PUBLISHED",
 "submittedAt":"2026-10-18T10:00:00Z"}]
GET/games/{username}público

Os jogos publicados de um criador.

GET/games/{username}/{gameSlug}público

Um jogo específico (a rota que o app embute).

GET/me/gamescom sessão

Os seus envios, em qualquer estado (dono vê o próprio não-publicado).

POST/gamescom sessão

Envia um jogo para moderação — url obrigatoriamente https; slug único por criador.

requisição

{"slug":"kawaii-survivors","title":"Kawaii Survivors","url":"https://ada.itch.io/kawaii",
 "description":"…","tags":"arcade,pixel"}

resposta

{"id":"game_…","slug":"kawaii-survivors","status":"SUBMITTED"}
POST/games/{gameId}/resubmitcom sessão

Reenvia um jogo rejeitado para nova rodada.

POST/games/{gameId}/compartilharcom sessão

G-share: publica a conquista no feed com a tag do jogo (texto ≤ 600; teto de 12/dia por pessoa). O texto/mídia vêm do JOGO por postMessage e o APP publica com o clique do jogador — a sessão nunca atravessa o iframe.

requisição

{"texto":"Peguei nível 10 na fazendinha!","mediaIds":["media_…"]}

resposta

{"postId":"post_…","status":"SHARED"}
GET/admin/games?limit=30admin

Fila de revisão.

POST/admin/games/{gameId}/approveadmin

Aprova e publica.

requisição

{"note":"carrega e roda"}

resposta

{"id":"game_…","status":"PUBLISHED"}
POST/admin/games/{gameId}/rejectadmin

Recusa — o motivo é obrigatório e o criador lê.

requisição

{"note":"o jogo não carrega"}

resposta

{"id":"game_…","status":"REJECTED"}

Marketplace (temas por faíscas, com escrow)

O criador lista um tema próprio por um preço em faíscas; a compra fica em ESCROW — as faíscas ficam retidas até o comprador confirmar (7 dias; liberação automática depois), e o criador recebe o preço menos 10% de taxa. Reembolso devolve 100%. Valores em milésimos de faísca.

GET/marketplace?limit=60público

Itens à venda.

resposta

[{"id":"mkt_…","sellerId":"user_…","itemKind":"THEME","itemId":"tema_…","title":"Tema à Venda",
 "price":40000,"status":"ACTIVE","createdAt":"2026-10-18T10:00:00Z"}]
GET/marketplace/minecom sessão

As suas listagens.

GET/marketplace/comprascom sessão

As suas compras (o painel do escrow: confirmar ou reembolso).

GET/marketplace/vendascom sessão

As suas vendas (acompanhar liberações).

POST/marketplacecom sessão

Lista um tema seu (só o autor pode; o tema precisa estar publicado na galeria).

requisição

{"itemId":"tema_…","title":"Tema à Venda","price":40000}

resposta

{"id":"mkt_…","status":"ACTIVE"}
POST/marketplace/{listingId}/buycom sessão

Compra: as faíscas saem da carteira e ficam retidas.

resposta

{"purchaseId":"mcmp_…","state":"HELD","price":40000}
POST/marketplace/purchases/{purchaseId}/confirmcom sessão

Confirmou que está tudo certo: libera 90% ao criador (10% de taxa à plataforma).

resposta

{"purchaseId":"mcmp_…","state":"RELEASED"}
POST/marketplace/purchases/{purchaseId}/refundcom sessão

Reembolso dentro de 7 dias: devolve 100%.

resposta

{"purchaseId":"mcmp_…","state":"REFUNDED"}

Serviços freelance (com escrow)

Duas faces: OFERTAR (o profissional publica o que faz, modelo Fiverr — teto de 5 abertas por conta) e PEDIR (a demanda publica o que precisa, com orçamento em faixa e entregáveis OBRIGATÓRIOS — a lição dos microprojetos). O contrato nasce HELD: entrega → aceite libera 90%; reembolso devolve 100%.

GET/servicospúblico

Catálogo: ofertas ativas e pedidos abertos.

resposta

{"ofertas":[{"id":"sl_…","category":"design","title":"Logo simples","price":30000,"deliveryDays":5,
 "deliverables":"SVG + PNG","status":"ACTIVE"}],
 "pedidos":[{"id":"sr_…","category":"código","title":"Página institucional","budgetMin":40000,"budgetMax":80000,
 "deliverables":"HTML + CSS publicados","status":"OPEN"}]}
GET/servicos/minhascom sessão

Minhas ofertas e meus contratos (como comprador e como vendedor).

POST/servicos/ofertascom sessão

Publica uma oferta.

requisição

{"category":"design","title":"Logo simples para o seu time","description":"Duas rodadas de ajuste…",
 "deliverables":"SVG + PNG em três tamanhos","price":30000,"deliveryDays":5}

resposta

{"id":"sl_…","status":"ACTIVE"}
POST/servicos/ofertas/{listingId}/contratarcom sessão

Contrata: as faíscas vão para o escrow.

resposta

{"contractId":"sc_…","state":"HELD"}
POST/servicos/pedidoscom sessão

Publica um pedido (entregáveis obrigatórios; faixa válida).

requisição

{"category":"código","title":"Página institucional","description":"…","deliverables":"HTML + CSS publicados",
 "budgetMin":40000,"budgetMax":80000}

resposta

{"id":"sr_…","status":"OPEN"}
POST/servicos/pedidos/{requestId}/propostascom sessão

Manda proposta — o preço precisa estar DENTRO da faixa.

requisição

{"message":"Entrego em uma semana, com revisão.","price":50000}

resposta

{"id":"sp_…","status":"SENT"}
GET/servicos/pedidos/{requestId}/propostascom sessão

As propostas do pedido (só quem pediu vê).

POST/servicos/pedidos/{requestId}/escolhercom sessão

Escolhe uma proposta: escrow retido e o pedido fecha.

requisição

{"proposalId":"sp_…"}

resposta

{"contractId":"sc_…","state":"HELD"}
POST/servicos/contratos/{contractId}/entregarcom sessão

O vendedor entrega (nota do que foi feito).

requisição

{"note":"SVG e PNG entregues no link X"}

resposta

{"contractId":"sc_…","state":"HELD"}
POST/servicos/contratos/{contractId}/aceitarcom sessão

O comprador aceita: libera 90% ao profissional.

resposta

{"contractId":"sc_…","state":"RELEASED"}
POST/servicos/contratos/{contractId}/reembolsocom sessão

O comprador recusa: devolve 100%.

resposta

{"contractId":"sc_…","state":"REFUNDED"}

Blogs

Um blog por pessoa, em /blog/{username}. Os posts do blog ficam fora do feed principal; quem assina o blog recebe os posts novos por e-mail (se optou por isso).

GET/blogs/{slug}público

Lê o blog e os posts publicados pelo slug do blog.

requisição

curl https://enois.ia.br/api/blogs/ada

resposta

200 OK
{"slug":"ada","username":"ada","title":"Blog da Ada","posts":[…]}
GET/blogs/mecom sessão

O blog de quem está autenticado (cria um em branco se não existir).

PUT/blogs/mecom sessão

Cria ou atualiza o próprio blog (título, descrição, tema).

POST/blogs/me/postscom sessão

Publica um post no próprio blog (markdown ou HTML sanitizado).

PATCH/blogs/me/posts/{postId}com sessão

Edita um post próprio do blog.

DELETE/blogs/me/posts/{postId}com sessão

Remove um post próprio do blog.

Grupos

Espaços privados com feed, tópicos e moderação próprios, independentes das comunidades. Entrada aberta entra na hora; entrada por pedido gera um pendente que os administradores aprovam ou recusam.

GET/groups/{slug}público

Página pública do grupo (quem não é membro vê o que o grupo expõe).

POST/groups/{groupId}/joincom sessão

Entra no grupo ou envia pedido (quando a entrada é por aprovação).

GET/groups/{groupId}/memberscom sessão

Lista de membros do grupo.

POST/groups/{groupId}/topicscom sessão

Cria um tópico dentro do grupo (os administradores do grupo fazem isso).

GET/groups/{groupId}/postscom sessão

Feed do grupo: só o conteúdo marcado com os tópicos dele.

POST/groups/{groupId}/postscom sessão

Publica no feed do grupo (membros).

POST/groups/{groupId}/requests/{requestId}/approvecom sessão

Aprova um pedido de entrada (administradores). Reject faz o simétrico.

Serviços

Ofertas de serviço entre pessoas da rede, com orçamento, contrato e entrega. O fluxo vai de pedido aberto a proposta, escolha, entrega e aceite (ou reembolso integral).

GET/services/servicospúblico

Catálogo de serviços publicados.

POST/services/servicos/ofertascom sessão

Publica uma oferta de serviço (sujeita à moderação).

POST/services/servicos/pedidoscom sessão

Abre um pedido de serviço.

POST/services/servicos/pedidos/{requestId}/propostascom sessão

Envia uma proposta para um pedido aberto.

POST/services/servicos/pedidos/{requestId}/escolhercom sessão

Escolhe a proposta e fecha o contrato (o valor fica em custódia).

POST/services/contratos/{contractId}/entregarcom sessão

Entrega o trabalho realizado (o cliente tem X dias para responder).

POST/services/contratos/{contractId}/aceitarcom sessão

Aceita a entrega e libera o pagamento ao prestador.

POST/services/contratos/{contractId}/reembolsocom sessão

Reembolso integral: devolve 100% ao cliente.

Jogos diários

Três jogos que trocam a todo dia (Blocos, Palavras e Labirinto), com ranking geral e prêmios em faíscas.

GET/daily-games/blocks/todaypúblico

O estado do jogo de Blocos de hoje (com sessão, inclui o progresso do jogador).

POST/daily-games/blocks/today/startcom sessão

Inicia a partida de hoje.

POST/daily-games/blocks/today/actionscom sessão

Executa uma ação na partida em andamento.

GET/daily-games/blocks/leaderboardpúblico

Ranking do dia (e histórico).

GET/daily-games/words/todaypúblico

Estado do jogo de Palavras de hoje.

GET/daily-games/rewards/prizespúblico

Faixas de prêmio em faíscas por desempenho.

Casos de uso

Receitas de ponta a ponta com as chamadas reais — os exemplos de resposta abaixo são capturados da produção, não inventados.

Mostrar uma publicação do Énóis em outro site

Um post público serve qualquer widget: leitura sem credencial, contadores e comentários inclusos. Roteiro de três chamadas, sem autenticação.

  1. 11. Busque o post (autor, contadores, mídia):

    curl https://enois.ia.br/api/feed/posts/post_396a12bc2bc54ad3966829c751acb021
  2. 22. Busque a primeira página de comentários:

    curl "https://enois.ia.br/api/feed/posts/post_396a12bc2bc54ad3966829c751acb021/comments?limit=20"
  3. 33. Pagina enquanto houver nextCursor (mande o valor de volta em ?cursor=):

    curl "https://enois.ia.br/api/feed/posts/post_396a12bc2bc54ad3966829c751acb021/comments?cursor=<nextCursor>&limit=20"
  4. 4Imagens de perfil e mídia vêm com caminho relativo — prefixe com https://enois.ia.br para renderizar.

Mural de vagas com link para a origem

A listagem junta vagas internas e agregadores públicos (Remotive, Jobicy, RemoteOK, Himalayas). Vagas externas têm id com prefixo ext_ e sempre uma sourceUrl — o clique vai para quem publicou a vaga.

  1. 11. Liste com busca booleana no título:

    curl "https://enois.ia.br/api/jobs?query=java%20AND%20(remoto%20OR%20h%C3%ADbrido)&limit=20"
  2. 22. Separe as externas pelo prefixo do id e use a origem:

    # externa: id "ext_Remotive_2091144" -> sourcePlatform "Remotive" + sourceUrl para redirecionar
    # interna: id "job_…"      -> aplicação pela própria API (requer sessão)
  3. 33. Pagine com nextCursor; filtros estruturais (type/level/location/skills) limitam a vagas internas.

Feed de uma comunidade

Conteúdo de uma comunidade específica, sem credencial — útil para site do evento ou da turma.

  1. 11. Encontre a comunidade:

    curl "https://enois.ia.br/api/communities?limit=20"
  2. 22. Puxe o feed dela:

    curl "https://enois.ia.br/api/communities/$COMMUNITY_ID/feed?limit=20"
  3. 33. Detalhe de cada post e comentários: mesmos endpoints do caso do widget.

Publicar com imagem (com sessão)

Upload em três passos e depois a publicação. Funciona igual para comentário (mediaIds) e avatar.

  1. 11. Autentique-se e guarde o token:

    curl -X POST https://enois.ia.br/api/auth/login -H "Content-Type: application/json" \
      -d '{"email":"ada@exemplo.com","password":"senha-forte-1"}'
  2. 22. Peça a assinatura do upload:

    curl -X POST https://enois.ia.br/api/media/uploads -H "X-Session-Token: $TOKEN" \
      -H "Content-Type: application/json" \
      -d '{"fileName":"media/abc/foto.png","mimeType":"image/png","size":10240,"purpose":"POST_IMAGE"}'
  3. 33. Suba o arquivo no uploadUrl que veio na resposta (PUT direto na S3 assinada, ou multipart no ImageKit).

  4. 44. Publique com o mediaId:

    curl -X POST https://enois.ia.br/api/feed/posts -H "X-Session-Token: $TOKEN" \
      -H "Content-Type: application/json" \
      -d '{"type":"INSIGHT","content":"Olha isso","mediaIds":["media_…"]}'

Faísca: transferência estilo Pix e a cotação

A moeda interna é fracionada (1 faísca = 1.000 mf) e transferida por username, com Idempotency-Key. A cotação de referência em BRL é pública; o total em circulação não é.

  1. 11. A cotação de referência (pública, sem token):

    curl https://enois.ia.br/api/coin/cotacao
  2. 22. Abra a carteira (a primeira abertura executa o genesis idempotente):

    curl https://enois.ia.br/api/carteira -H "X-Session-Token: $TOKEN"
  3. 33. Envie 1,5 faísca (1.500 mf) para outra pessoa:

    curl -X POST https://enois.ia.br/api/carteira/transferencias -H "X-Session-Token: $TOKEN"   -H "Idempotency-Key: pagamento-01" -H "Content-Type: application/json"   -d '{"toUsername":"joao-silva","amount":1500,"message":"pelo mockup lindo"}'
  4. 4Repetir a chamada com a MESMA chave não duplica (replay do Pix). Transferência é irreversível — reversão só por moderação, com lançamento espelho no ledger.

Escrow de ponta a ponta: comprar um tema

Compra em faíscas com escrow: as faíscas ficam retidas até o comprador confirmar (7 dias) — o criador recebe 90% e a plataforma fica com 10%.

  1. 11. Veja o que está à venda:

    curl https://enois.ia.br/api/marketplace
  2. 22. Compre (as faíscas saem da carteira e ficam retidas):

    curl -X POST https://enois.ia.br/api/marketplace/mkt_…/buy -H "X-Session-Token: $TOKEN"
  3. 33. Confirme depois de instalar o tema (libera 90% ao criador):

    curl -X POST https://enois.ia.br/api/marketplace/purchases/mcmp_…/confirm -H "X-Session-Token: $TOKEN"
  4. 4Arrependeu dentro de 7 dias? /refund devolve 100%. Sem decisão, a liberação para o criador é automática.

Jogos: compartilhar conquista no feed

O jogo roda num iframe de OUTRA origem, sem sessão nenhuma. Para oferecer "compartilhar conquista", ele fala com a página pai por postMessage; a página valida a origem, mostra a prévia e publica com o CLIQUE do jogador — o jogo nunca publica sozinho.

  1. 11. Dentro do jogo (iframe), pede o compartilhamento:

    window.parent.postMessage({
      type: "enois:share",
      texto: "Peguei nível 10 na fazendinha!",
      imagem: "data:image/png;base64,…"   // opcional
    }, "*");
  2. 22. A página do Énóis valida a origem, mostra a prévia ao jogador e, no clique, sobe a imagem pela mídia e publica:

    curl -X POST https://enois.ia.br/api/games/game_…/compartilhar -H "X-Session-Token: $TOKEN" \
      -H "Content-Type: application/json" \
      -d '{"texto":"Peguei nível 10 na fazendinha!","mediaIds":["media_…"]}'
  3. 3O post nasce no feed com as tags game + o slug do jogo. Teto de 12/dia (429 SHARE_LIMIT). Protocolo completo em docs/GAMES.md.

Painel de saúde da rede

Números públicos, agregados, sem dado pessoal — prontos para dashboard ou relatório.

  1. 11. Atividade da rede:

    curl https://enois.ia.br/api/stats/community
  2. 22. Ranking de perfis:

    curl https://enois.ia.br/api/profile/ranking
  3. 33. Pulso por tema:

    curl "https://enois.ia.br/api/search?q=ia&limit=50"

Integração de moderação (admins)

Para ferramentas do próprio time: a fila de denúncias e de recursos é acessível por sessão de administrador (REDE_ADMIN_EMAILS). O banimento só acontece por recurso negado — decisão sempre humana.

  1. 11. Veja a fila de denúncias (já com a pré-triagem da IA no campo ai_triage):

    curl "https://enois.ia.br/api/admin/reports?limit=30" -H "X-Session-Token: $ADMIN_TOKEN"
  2. 22. Decida uma denúncia:

    curl -X POST https://enois.ia.br/api/admin/reports/$REPORT_ID/approve -H "X-Session-Token: $ADMIN_TOKEN" \
      -H "Content-Type: application/json" -d '{"note":"confirmado"}'
  3. 33. Julgue recursos (aprovar libera; negar ban):

    curl -X POST https://enois.ia.br/api/admin/appeals/$APPEAL_ID/approve -H "X-Session-Token: $ADMIN_TOKEN"

Estado e contato

Esta é a versão inicial. Escopos de terceiros (OAuth) e o portal completo estão em construção — documentamos apenas o que já existe.

Vulnerabilidades: reporte em SECURITY.md descreve como reportar vulnerabilidades (resposta em até 90 dias, sem caça a recompensa).

O que a plataforma tolera (e o que não tolera) está nas Diretrizes da Comunidade