Programadores
Dezassete pontos de acesso em dez caminhos, cinco eventos de saída e uma especificação OpenAPI 3.1 pública que o Make e o n8n importam sozinhos. Está aqui tudo: cada parâmetro um a um, exemplos que funcionam tal como estão e a lista do que não faz.
Especificação OpenAPI 3.1, sem chave
https://app.blastack.com/api/openapi.json
Raiz da API
https://app.blastack.com/api/v1
Cole o primeiro endereço no importador do n8n ou do Make e os nós aparecem sozinhos. O Zapier não lê OpenAPI: é precisamente por isso que os seus passos estão escritos à parte, mais abaixo.
Num relance
Oito dados. Com estes escreve-se o pedido sem ler mais nada.
| O quê | Valor | Nota |
|---|---|---|
| Raiz da API | https://app.blastack.com/api/v1 | Vive na aplicação, não neste sítio comercial. Um só endereço, e não muda. |
| Especificação | https://app.blastack.com/api/openapi.json | Pública e sem chave, para que um importador a possa ler antes sequer de haver credenciais. |
| Autenticação | Authorization: Bearer blsk_<prefix>_<secret> | No cabeçalho, nunca no endereço. Os endereços acabam no registo do servidor, no do proxy à frente e no histórico de quem a experimentou à mão. |
| Formato | application/json; charset=utf-8 | JSON à ida e à vinda. Não há XML nem formulários. |
| Limite | 120 req/min · RateLimit-Remaining | Por chave e por minuto. Cada resposta diz quantos faltam e quando a contagem recomeça. |
| Paginação | page=1 · per_page=50 · ≤ 200 | A primeira página é a 1, não a 0. Pedir mais de duzentos é cortado em vez de recusado. |
| Erros | { error: { status, code, message } } | Sempre o mesmo objeto, com um código estável pensado para lhe escrever uma condição por cima. |
| Ambiente de testes | — | Não existe. Trabalha-se contra a produção, e é por isso que compensa começar com uma chave só de leitura. |
curl https://app.blastack.com/api/v1/people?per_page=1 \
-H "Authorization: Bearer blsk_a1b2c3d4e5f6_YOUR_SECRET"O que há
As três funcionam. O que falta está mais abaixo, na sua própria secção e dito pelo nome.
Para que o vosso sistema de pessoal crie as pessoas, as mude de departamento e as desative sem ninguém copiar nada à mão. É a metade que interessa mesmo a um departamento de informática: no dia em que dispensam alguém, a conta desativa-se sozinha.
Filtro por userName e externalId, paginação e alteração parcial. Lêem-se o departamento e a morada de trabalho, por isso quem entra por aqui nasce com o departamento e o centro de trabalho já preenchidos. A saída desativa, não apaga.
Entrar com a conta da empresa a partir do Entra ID, do Google Workspace ou do Okta. Convive com o código de adesão, que é como entra a parte do quadro de pessoal sem correio da empresa.
Configura-se colando o endereço de descoberta do fornecedor e é verificada contra ele antes de guardar. Os domínios de correio verificam-se por DNS. Não há SAML nem LDAP.
Publicar a partir do programa que já sabe que a linha 3 para na quinta-feira, desativar quem sai do sistema de pessoal, e sermos nós a ligar quando acontece algo em vez de terem de perguntar de cinco em cinco minutos.
JSON sobre HTTPS, chave de API no cabeçalho, âmbitos por chave, erros com código estável e eventos de saída assinados. É o que documenta o resto desta página.
Automatização
As três não se montam da mesma maneira, e dizê-lo poupa a tarde que se perde a descobri-lo. O Make e o n8n leem a especificação e configuram-se quase sozinhos; o Zapier não a lê, por isso ali cada chamada escreve-se à mão. As três funcionam; o trabalho não é o mesmo.
| Ferramenta | Lê a especificação? | Disparador recomendado |
|---|---|---|
| n8n | Sim, inteira | Nó «Webhook» + POST /webhooks |
| Make | Sim, no editor de aplicações próprias | «Custom webhook» + POST /webhooks |
| Zapier | Não | «Catch Hook» + POST /webhooks |
O caminho mais curto dos três. Cria-se uma credencial de cabeçalho, cola-se o endereço da especificação no importador e fica um nó por operação com os parâmetros já postos.
Passos
A ter em conta
O nó de webhook responde 200 antes de executar o resto do fluxo, que é exatamente o que faz falta aqui: ao fim de dez segundos desistimos e isso conta como falha.
O módulo genérico de HTTP chega para tudo, e quem for montar muitos cenários pode carregar a especificação no editor de aplicações próprias e ficar com um módulo por operação.
Passos
A ter em conta
O Make cobra à operação: um cenário que pergunte de cinco em cinco minutos queima oito mil operações por mês para não encontrar quase nada. Com o webhook gasta-se uma por evento.
O Zapier não importa OpenAPI. Monta-se com os passos genéricos de webhooks, ou construindo uma integração privada na plataforma de programadores deles, onde cada ponto de acesso se declara à mão.
Passos
A ter em conta
Os disparadores por sondagem gastam uma tarefa em cada passagem, encontrem alguma coisa ou não. O «Catch Hook» só gasta quando aconteceu mesmo algo.
Chaves
Hoje emitimo-las nós, à mão, e dizemos com que âmbitos. Não há ecrã de autosserviço e está dito mais abaixo, entre o que falta. Cada chave está presa a uma empresa e nenhuma rota lê um identificador de empresa do pedido: não há onde enganar-se.
Digam-nos para que é e o que tem de poder fazer, e emitimo-la com esses âmbitos e mais nenhum. Mostra-se uma só vez: dela guardamos apenas um resumo, por isso uma chave perdida revoga-se e emite-se outra.
No cabeçalho de autorização, nunca no endereço. Os endereços acabam no registo do servidor, no do proxy à frente e no histórico de quem a experimentou à mão.
No vosso gestor de segredos, não no repositório. Começa por um prefixo reconhecível precisamente para que os detetores de segredos a apanhem se escapar.
A API entra no módulo de identidade corporativa, o mesmo que abre o início de sessão único e o aprovisionamento. Se a empresa não o tiver contratado, a resposta di-lo com essas palavras e não com um erro genérico.
| Âmbito | O que abre |
|---|---|
| people:read | Ler o quadro de pessoal e os departamentos e centros de trabalho a que se pode dirigir um comunicado. É tudo o que um painel precisa. |
| people:write | Criar, alterar e desativar pessoas. Desativar fecha-lhes as sessões, por isso não vem de oferta com o de leitura. |
| announcements:read | Ler o que foi publicado e quem confirmou uma leitura obrigatória. Está à parte do das pessoas: uma lista de nomes e funções é o diretório, e o texto dos comunicados não. |
| announcements:write | Publicar no quadro de avisos. Respeita a fila de revisão da empresa, por isso uma chave não salta o circuito de aprovação de ninguém. |
| metrics:read | Os indicadores agregados. Aqui não sai o nome de ninguém. |
| webhooks:read | Ver os endereços registados e o registo de entregas. É o que responde a «porque é que não chega nada» sem abrir um pedido de apoio. |
| webhooks:write | Registar, alterar e apagar endereços de evento de saída. O mais delicado da lista: decide para que servidor da internet mandamos o conteúdo dos vossos comunicados. |
Pontos de acesso
Agrupadas por família. A coluna do âmbito é a que interessa ver ao pedir a chave: se faltar, a resposta diz qual era preciso e quais tem a vossa.
| Método | Caminho | Âmbito | O que faz |
|---|---|---|---|
| GET | /people | people:read | O quadro de pessoal, com o departamento, o centro de trabalho e o identificador que cada pessoa tem no vosso sistema de pessoal. Dezassete parâmetros, entre eles o filtro pela data da última alteração, que é o que permite sincronizar de quinze em quinze minutos sem trazer tudo. |
| GET | /people/{id} | people:read | Uma pessoa concreta, procurada pelo nosso identificador ou pelo vosso. Serve para atualizar uma ficha sem percorrer a lista toda. |
| POST | /people | people:write | Cria alguém. É para quando o vosso sistema de pessoal não fala SCIM; se falar, melhor SCIM, que também trata das saídas. O departamento e o centro de trabalho indicam-se pelo nome e criam-se se não existirem. |
| PATCH | /people/{id} | people:write | Muda só os campos que enviarem. Um que fique de fora não é tocado: uma sincronização que só conhece a função não pode apagar o centro de trabalho a ninguém. |
| DELETE | /people/{id} | people:write | Desativa; nunca apaga. As sessões fecham-se de imediato, por isso quem sai numa sexta-feira fica fora nessa sexta-feira. O que publicou fica. |
| GET | /audiences | people:read | Os departamentos e os centros de trabalho que existem, com quantas pessoas há em cada um. É daqui que saem os nomes a que se pode dirigir um comunicado, e o filtro dos grupos vazios é o que encontra um mapeamento de aprovisionamento partido. |
| GET | /announcements | announcements:read | Tudo o que foi publicado, com as leituras e as confirmações de cada peça. Inclui rascunhos e recusados para que um painel possa desenhar o funil inteiro. |
| GET | /announcements/{id} | announcements:read | Uma publicação concreta. É o passo seguinte ao identificador que uma publicação devolve ou que chega num evento de saída. |
| POST | /announcements | announcements:write | Publica no quadro de avisos. É preciso dizer quem assina e não há valor por omissão. Se essa pessoa não puder publicar sem revisão, o comunicado entra na fila e a resposta di-lo. |
| GET | /announcements/{id}/acknowledgements | announcements:read | Quem confirmou uma leitura obrigatória e quem não, com nome e hora. É a única lista nominal de toda a API, e é-o porque esse é justamente o sentido da leitura obrigatória: um ato voluntário, assinado e datado que se pode mostrar a uma inspeção. |
| GET | /metrics | metrics:read | O quadro de pessoal de hoje, as entradas, as publicações e o alcance por publicação e por departamento. Os mesmos números do ecrã de análise, calculados pelo mesmo código. |
| GET | /webhooks | webhooks:read | Os vossos endereços registados, cada um com a sua saúde: falhas seguidas, o que o vosso servidor respondeu da última vez e, se o tivermos pausado, porquê. |
| POST | /webhooks | webhooks:write | Regista um endereço e os eventos que quer. A resposta traz o segredo de assinatura, e é a única vez em que se vê. |
| GET | /webhooks/{id} | webhooks:read | Um endereço concreto, com a sua saúde. |
| PATCH | /webhooks/{id} | webhooks:write | Muda o que enviarem. Pôr o endereço outra vez ativo levanta também a pausa que tenhamos aplicado depois de falhas repetidas e põe o contador a zero. |
| DELETE | /webhooks/{id} | webhooks:write | Apaga-o com o seu histórico. Para deixar de receber durante um tempo sem perder o histórico, é melhor desativá-lo. |
| GET | /webhooks/{id}/deliveries | webhooks:read | Tudo o que tentámos mandar-vos: tentativas, o que responderam e quando é a próxima. O identificador é o mesmo que viajou no cabeçalho, por isso cruza-se com os vossos registos. |
Parâmetros
Nenhuma lista aqui está resumida: são as mesmas que o servidor verifica. Um parâmetro que não esteja aqui não existe, e escrevê-lo devolve um erro que diz quais admite esse ponto de acesso em vez de o ignorar em silêncio.
A coluna da direita está em inglês de propósito. Sai do catálogo de onde também se gera a especificação, por isso é palavra por palavra o que o n8n e o Make mostram dentro dos seus nós. Traduzi-la aqui seria ter duas versões que um dia diriam coisas diferentes.
people:read
O quadro de pessoal, com o departamento, o centro de trabalho e o identificador que cada pessoa tem no vosso sistema de pessoal. Dezassete parâmetros, entre eles o filtro pela data da última alteração, que é o que permite sincronizar de quinze em quinze minutos sem trazer tudo.
| Parâmetro | Tipo | Valores admitidos | Por omissão | Exemplo | O que faz |
|---|---|---|---|---|---|
| page | inteiromín. 1 | 1 | 2 | Page to return. The first page is 1, not 0. | |
| per_page | inteiromín. 1 · máx. 200 · fora do intervalo é cortado em vez de falhar | 50 | 100 | How many items per page. Anything above 200 is clamped to 200 rather than rejected: asking for more is a reasonable thing to want. | |
| sort | texto | created_at · updated_at · name · email | created_at | Field to sort by. Defaults to created_at. | |
| order | texto | asc · desc | asc | Sort direction. | |
| fields | texto · vários separados por vírgulas | external_id · email · name · job_title · department · center · role · status · language · created_at · updated_at | external_id,department,status | Comma-separated list of fields to return. `id` is always included. Use it to avoid pulling personal data you do not need. | |
| status | texto · vários separados por vírgulas | active · invited · disabled | active | Only people in these states. Several may be given. | |
| role | texto · vários separados por vírgulas | owner · admin · gestor_personas · responsable_local · informatico · editor · revisor · analista · employee | Only people with these roles. Several may be given. | ||
| department | texto · vários separados por vírgulas | Maintenance,Quality | Department name, or several separated by commas. Case-insensitive: your directory writing MANTENIMIENTO is not an error. | ||
| center | texto · vários separados por vírgulas | Site name, or several separated by commas. Case-insensitive. | |||
| no_department | booleano | Only people with no department. These are the ones who never see a targeted announcement, so this is the filter that finds a broken provisioning mapping. | |||
| language | texto · vários separados por vírgulas | es · ca · en · pt · fr · it · de · sv · nl · pl · ro · cs | Only people who picked this reading language. | ||
| texto | Exact email address, case-insensitive. | ||||
| external_id | texto | Exact external_id, as sent by your HR system over SCIM. | |||
| q | texto | garcia | Free text over name, email and job title. Case-insensitive, matches anywhere in the value. | ||
| updated_since | data ISO 8601 | 2026-08-01T00:00:00Z | Only people changed at or after this instant. This is the one that lets you sync every fifteen minutes without pulling two thousand rows every time. | ||
| created_since | data ISO 8601 | Only people added at or after this instant. | |||
| created_until | data ISO 8601 | Only people added before this instant. |
people:read
Uma pessoa concreta, procurada pelo nosso identificador ou pelo vosso. Serve para atualizar uma ficha sem percorrer a lista toda.
| Parâmetro | Tipo | Valores admitidos | Por omissão | Exemplo | O que faz |
|---|---|---|---|---|---|
| idObrigatório | texto | a3f1… | Blastack id (a uuid) or the person's external_id from your HR system. A Blastack id is always a uuid and yours almost never is, so they cannot be confused; if one ever were, ours wins. |
| Parâmetro | Tipo | Valores admitidos | Por omissão | Exemplo | O que faz |
|---|---|---|---|---|---|
| fields | texto · vários separados por vírgulas | external_id · email · name · job_title · department · center · role · status · language · created_at · updated_at | external_id,department,status | Comma-separated list of fields to return. `id` is always included. Use it to avoid pulling personal data you do not need. |
people:write
Cria alguém. É para quando o vosso sistema de pessoal não fala SCIM; se falar, melhor SCIM, que também trata das saídas. O departamento e o centro de trabalho indicam-se pelo nome e criam-se se não existirem.
| Parâmetro | Tipo | Valores admitidos | Por omissão | Exemplo | O que faz |
|---|---|---|---|---|---|
| nameObrigatório | textocomprimento máx. 120 | Ana García | Full name, as it should appear on the wall. | ||
| textocomprimento máx. 200 | Work email. Optional: most of the workforce this product is for has none, and they get in with an invite code instead. Unique within the company. | ||||
| external_id | textocomprimento máx. 200 | EMP-0042 | The id this person has in your system. Store it and you can cross both lists later without matching names. | ||
| job_title | textocomprimento máx. 120 | Job title. | |||
| department | textocomprimento máx. 80 | Department name. Created if it does not exist. Without one, this person only ever sees company-wide announcements. | |||
| center | textocomprimento máx. 80 | Site name. Created if it does not exist. | |||
| role | texto | admin · gestor_personas · responsable_local · informatico · editor · revisor · analista · employee | employee | What they can do. `owner` cannot be given from the API: a key pasted in a cron job must not be able to mint an account that can cancel the subscription. | |
| status | texto | active · invited · disabled | active | `active` can sign in; `invited` is created but not counted as signed up yet; `disabled` is created already deactivated, which is what a backfill of former staff needs. | |
| language | texto | es · ca · en · pt · fr · it · de · sv · nl · pl · ro · cs | Reading language. Leave it out and they read in the company's, which is what you want unless you actually know. |
people:write
Muda só os campos que enviarem. Um que fique de fora não é tocado: uma sincronização que só conhece a função não pode apagar o centro de trabalho a ninguém.
| Parâmetro | Tipo | Valores admitidos | Por omissão | Exemplo | O que faz |
|---|---|---|---|---|---|
| idObrigatório | texto | a3f1… | Blastack id (a uuid) or the person's external_id from your HR system. A Blastack id is always a uuid and yours almost never is, so they cannot be confused; if one ever were, ours wins. |
| Parâmetro | Tipo | Valores admitidos | Por omissão | Exemplo | O que faz |
|---|---|---|---|---|---|
| name | textocomprimento máx. 120 | Full name. | |||
| textocomprimento máx. 200 | Work email. | ||||
| external_id | textocomprimento máx. 200 | The id this person has in your system. | |||
| job_title | textocomprimento máx. 120 | Job title. | |||
| department | textocomprimento máx. 80 | Department name. Created if it does not exist. | |||
| center | textocomprimento máx. 80 | Site name. Created if it does not exist. | |||
| role | texto | admin · gestor_personas · responsable_local · informatico · editor · revisor · analista · employee | What they can do. `owner` cannot be given from the API. | ||
| status | texto | active · invited · disabled | Their state. `disabled` also closes their sessions. | ||
| language | texto | es · ca · en · pt · fr · it · de · sv · nl · pl · ro · cs | Reading language. |
people:write
Desativa; nunca apaga. As sessões fecham-se de imediato, por isso quem sai numa sexta-feira fica fora nessa sexta-feira. O que publicou fica.
| Parâmetro | Tipo | Valores admitidos | Por omissão | Exemplo | O que faz |
|---|---|---|---|---|---|
| idObrigatório | texto | a3f1… | Blastack id (a uuid) or the person's external_id from your HR system. A Blastack id is always a uuid and yours almost never is, so they cannot be confused; if one ever were, ours wins. |
people:read
Os departamentos e os centros de trabalho que existem, com quantas pessoas há em cada um. É daqui que saem os nomes a que se pode dirigir um comunicado, e o filtro dos grupos vazios é o que encontra um mapeamento de aprovisionamento partido.
| Parâmetro | Tipo | Valores admitidos | Por omissão | Exemplo | O que faz |
|---|---|---|---|---|---|
| type | texto | all · departments · centers | all | Return only departments, only sites, or both. | |
| q | texto | Free text over the name. Case-insensitive. | |||
| with_people | booleano | Only groups that have at least one active person. A department with nobody in it is almost always an old name left behind, and it is the usual cause of an announcement that reaches no one. | |||
| sort | texto | name · people | name | Field to sort by. Defaults to name. | |
| order | texto | asc · desc | asc | Sort direction. |
announcements:read
Tudo o que foi publicado, com as leituras e as confirmações de cada peça. Inclui rascunhos e recusados para que um painel possa desenhar o funil inteiro.
| Parâmetro | Tipo | Valores admitidos | Por omissão | Exemplo | O que faz |
|---|---|---|---|---|---|
| page | inteiromín. 1 | 1 | 2 | Page to return. The first page is 1, not 0. | |
| per_page | inteiromín. 1 · máx. 200 · fora do intervalo é cortado em vez de falhar | 50 | 100 | How many items per page. Anything above 200 is clamped to 200 rather than rejected: asking for more is a reasonable thing to want. | |
| sort | texto | published_at · created_at · updated_at · title | published_at | Field to sort by. Defaults to published_at. | |
| order | texto | asc · desc | asc | Sort direction. | |
| fields | texto · vários separados por vírgulas | title · body · status · kind · language · audience · community · section · author · notify · comments_enabled · pinned · acknowledgements · reads · published_at · created_at · updated_at · url | external_id,department,status | Comma-separated list of fields to return. `id` is always included. Use it to avoid pulling personal data you do not need. | |
| status | texto · vários separados por vírgulas | draft · pending_review · published · rejected · scheduled · archived | published,scheduled | Only these states. Several may be given. `scheduled` means it is written and waiting for its hour. | |
| author | texto | Who signs it: our id, their email or their external_id. Any of the three. | |||
| audience_type | texto | all · departments · centers | Only announcements aimed this way. | ||
| department | texto · vários separados por vírgulas | Only announcements aimed at these departments, by name. Several may be given. | |||
| center | texto · vários separados por vírgulas | Only announcements aimed at these sites, by name. | |||
| community | texto | Only announcements in this community, by id or by name. | |||
| requires_acknowledgement | booleano | Only required reading, or only the rest. This is the filter a compliance report is built on. | |||
| pinned | booleano | Only pinned announcements, or only the rest. | |||
| q | texto | Free text over title and body. Case-insensitive. | |||
| published_since | data ISO 8601 | Published at or after this instant. | |||
| published_until | data ISO 8601 | Published before this instant. | |||
| created_since | data ISO 8601 | Written at or after this instant. | |||
| updated_since | data ISO 8601 | Changed at or after this instant. |
announcements:read
Uma publicação concreta. É o passo seguinte ao identificador que uma publicação devolve ou que chega num evento de saída.
| Parâmetro | Tipo | Valores admitidos | Por omissão | Exemplo | O que faz |
|---|---|---|---|---|---|
| idObrigatório | texto | The announcement id. |
| Parâmetro | Tipo | Valores admitidos | Por omissão | Exemplo | O que faz |
|---|---|---|---|---|---|
| fields | texto · vários separados por vírgulas | title · body · status · kind · language · audience · community · section · author · notify · comments_enabled · pinned · acknowledgements · reads · published_at · created_at · updated_at · url | external_id,department,status | Comma-separated list of fields to return. `id` is always included. Use it to avoid pulling personal data you do not need. |
announcements:write
Publica no quadro de avisos. É preciso dizer quem assina e não há valor por omissão. Se essa pessoa não puder publicar sem revisão, o comunicado entra na fila e a resposta di-lo.
| Parâmetro | Tipo | Valores admitidos | Por omissão | Exemplo | O que faz |
|---|---|---|---|---|---|
| bodyObrigatório | textocomprimento máx. 8000 | The text. Plain text; line breaks are kept. | |||
| authorObrigatório | texto | EMP-0042 | Who signs it: our id, their email or their external_id. Must be an active person in this company. | ||
| title | textocomprimento máx. 160 | Headline. | |||
| audience | objeto | Who it goes to. Leave it out and it goes to everyone. Names work as well as ids, case-insensitively, because your ERP has 'Maintenance' and not a uuid of ours. Nothing is created here: an unknown name is a typo in a script, and the reply tells you which one it was. | |||
| audience.type | texto | all · departments · centers | all | Aim at everyone, at departments or at sites. | |
| audience.ids | lista | ["Maintenance","Quality"] | Department or site names, or their ids. Required unless type is `all`. | ||
| community | texto | Which community it belongs to, by id or by name. Leave it out and it goes on the main wall, which everybody sees. The author has to belong to the community, or be posting to the default one: an API key is not a way into a community its signer is not in. | |||
| section | texto | Which section it belongs to, by id or by name. It must belong to the same community. | |||
| publish_at | data ISO 8601 | 2026-09-01T06:00:00Z | Publish later, at this instant. It must be in the future. The reply comes back with `status: scheduled` and the wall shows it when the hour arrives. Leave it out to publish now. Note this means two clocks are involved — yours and ours — so if your system already schedules, prefer calling us at the right moment. | ||
| requires_acknowledgement | booleano | false | Required reading: everyone it reaches gets a notification with a confirm button, and who confirmed is on record. Only signers who can publish without review may ask for it. | ||
| notify | booleano | true | Whether it makes a sound. Written the right way round on purpose: the screen has a 'publish without notifying' checkbox because a form that loses a field should still notify, but here you write the whole JSON and a field called `silent` reads wrong at three in the morning. Default is true. | ||
| comments_enabled | booleano | true | Whether people can comment on it. | ||
| pinned | booleano | false | Keep it at the top of the wall. | ||
| language | texto | es · ca · en · pt · fr · it · de · sv · nl · pl · ro · cs | What language the text is written in. Leave it out and the company's is used. Getting this right matters: a Catalan original labelled as Spanish is shown to a Spanish reader without the 'not translated' notice that tells them nothing is broken. |
announcements:read
Quem confirmou uma leitura obrigatória e quem não, com nome e hora. É a única lista nominal de toda a API, e é-o porque esse é justamente o sentido da leitura obrigatória: um ato voluntário, assinado e datado que se pode mostrar a uma inspeção.
| Parâmetro | Tipo | Valores admitidos | Por omissão | Exemplo | O que faz |
|---|---|---|---|---|---|
| idObrigatório | texto | The announcement id. |
| Parâmetro | Tipo | Valores admitidos | Por omissão | Exemplo | O que faz |
|---|---|---|---|---|---|
| page | inteiromín. 1 | 1 | 2 | Page to return. The first page is 1, not 0. | |
| per_page | inteiromín. 1 · máx. 200 · fora do intervalo é cortado em vez de falhar | 50 | 100 | How many items per page. Anything above 200 is clamped to 200 rather than rejected: asking for more is a reasonable thing to want. | |
| state | texto | all · acknowledged · pending | all | Everyone, only those who confirmed, or only those still pending. | |
| department | texto · vários separados por vírgulas | Only people in these departments, by name. | |||
| center | texto · vários separados por vírgulas | Only people at these sites, by name. | |||
| sort | texto | name · acknowledged_at | name | Field to sort by. Defaults to name. | |
| order | texto | asc · desc | asc | Sort direction. |
metrics:read
O quadro de pessoal de hoje, as entradas, as publicações e o alcance por publicação e por departamento. Os mesmos números do ecrã de análise, calculados pelo mesmo código.
| Parâmetro | Tipo | Valores admitidos | Por omissão | Exemplo | O que faz |
|---|---|---|---|---|---|
| period_days | inteiromín. 1 · máx. 365 | 30 | 90 | How many days back the period covers. Applies to every figure with a period, including the reach lists. | |
| include | texto · vários separados por vírgulas | workforce · announcements · reach_by_announcement · reach_by_department | workforce,announcements | Which blocks to compute, comma-separated. Leave it out for all of them. `reach_by_announcement` is the expensive one: skip it if your dashboard only draws the headline figures. |
webhooks:read
Os vossos endereços registados, cada um com a sua saúde: falhas seguidas, o que o vosso servidor respondeu da última vez e, se o tivermos pausado, porquê.
| Parâmetro | Tipo | Valores admitidos | Por omissão | Exemplo | O que faz |
|---|---|---|---|---|---|
| page | inteiromín. 1 | 1 | 2 | Page to return. The first page is 1, not 0. | |
| per_page | inteiromín. 1 · máx. 200 · fora do intervalo é cortado em vez de falhar | 50 | 100 | How many items per page. Anything above 200 is clamped to 200 rather than rejected: asking for more is a reasonable thing to want. | |
| event | texto | announcement.published · announcement.pending_review · announcement.acknowledged · person.created · person.deactivated | Only endpoints subscribed to this event. | ||
| active | booleano | Only live endpoints, or only the switched-off and paused. |
webhooks:write
Regista um endereço e os eventos que quer. A resposta traz o segredo de assinatura, e é a única vez em que se vê.
| Parâmetro | Tipo | Valores admitidos | Por omissão | Exemplo | O que faz |
|---|---|---|---|---|---|
| urlObrigatório | textocomprimento máx. 500 | https://hooks.example.com/blastack | Where we POST. https only, no credentials, no fragment. | ||
| eventsObrigatório | lista | announcement.published · announcement.pending_review · announcement.acknowledged · person.created · person.deactivated | ["announcement.published"] | Which events this endpoint wants. At least one. | |
| name | textocomprimento máx. 120 | Zapier · switchboard | What it is for, in your words. It is the only thing that lets you delete the right one six months from now. | ||
| secret | textocomprimento máx. 200 | Your own signing secret, if you would rather set it than have one generated. At least 32 characters. | |||
| active | booleano | true | Start delivering straight away. |
webhooks:read
Um endereço concreto, com a sua saúde.
| Parâmetro | Tipo | Valores admitidos | Por omissão | Exemplo | O que faz |
|---|---|---|---|---|---|
| idObrigatório | texto | The webhook endpoint id. |
webhooks:write
Muda o que enviarem. Pôr o endereço outra vez ativo levanta também a pausa que tenhamos aplicado depois de falhas repetidas e põe o contador a zero.
| Parâmetro | Tipo | Valores admitidos | Por omissão | Exemplo | O que faz |
|---|---|---|---|---|---|
| idObrigatório | texto | The webhook endpoint id. |
| Parâmetro | Tipo | Valores admitidos | Por omissão | Exemplo | O que faz |
|---|---|---|---|---|---|
| url | textocomprimento máx. 500 | Where we POST. https only. | |||
| events | lista | announcement.published · announcement.pending_review · announcement.acknowledged · person.created · person.deactivated | Which events this endpoint wants. At least one. | ||
| name | textocomprimento máx. 120 | What it is for. | |||
| active | booleano | Switch delivery on or off. Turning it on clears a pause. | |||
| rotate_secret | booleano | Generate a new signing secret and return it once in this reply. |
webhooks:write
Apaga-o com o seu histórico. Para deixar de receber durante um tempo sem perder o histórico, é melhor desativá-lo.
| Parâmetro | Tipo | Valores admitidos | Por omissão | Exemplo | O que faz |
|---|---|---|---|---|---|
| idObrigatório | texto | The webhook endpoint id. |
webhooks:read
Tudo o que tentámos mandar-vos: tentativas, o que responderam e quando é a próxima. O identificador é o mesmo que viajou no cabeçalho, por isso cruza-se com os vossos registos.
| Parâmetro | Tipo | Valores admitidos | Por omissão | Exemplo | O que faz |
|---|---|---|---|---|---|
| idObrigatório | texto | The webhook endpoint id. |
| Parâmetro | Tipo | Valores admitidos | Por omissão | Exemplo | O que faz |
|---|---|---|---|---|---|
| page | inteiromín. 1 | 1 | 2 | Page to return. The first page is 1, not 0. | |
| per_page | inteiromín. 1 · máx. 200 · fora do intervalo é cortado em vez de falhar | 50 | 100 | How many items per page. Anything above 200 is clamped to 200 rather than rejected: asking for more is a reasonable thing to want. | |
| status | texto | pending · delivered · given_up | Only deliveries in this state. | ||
| event | texto | announcement.published · announcement.pending_review · announcement.acknowledged · person.created · person.deactivated | Only deliveries of this event type. | ||
| since | data ISO 8601 | Only events that happened at or after this instant. |
Exemplos
Com o pedido inteiro e a resposta inteira. Mudem a chave e os nomes; o resto funciona tal como está.
Quando a manutenção fecha a ordem de paragem
É o caso que pedem sempre. O vosso sistema já sabe que a linha 3 para na quinta-feira; com esta chamada publica-o ele, dirigido aos departamentos certos e a pedir confirmação de leitura, sem ninguém escrever nada duas vezes.
Pedido
curl -X POST https://app.blastack.com/api/v1/announcements \
-H "Authorization: Bearer blsk_a1b2c3d4e5f6_YOUR_SECRET" \
-H "Content-Type: application/json" \
-d '{
"author": "EMP-0042",
"title": "Paragem da linha 3 na quinta-feira",
"body": "Na quinta-feira dia 4, às 06:00, a linha 3 para para manutenção programada. O turno da manhã entra à hora do costume e passa para a linha 2.",
"audience": {
"type": "departments",
"ids": [
"Manutenção",
"Qualidade"
]
},
"requires_acknowledgement": true,
"notify": true,
"language": "pt"
}'Resposta · 201
{
"id": "6b1f0f1e-0c2a-4c5e-9a3d-2f5b8c7d1e40",
"title": "Paragem da linha 3 na quinta-feira",
"body": "Na quinta-feira dia 4, às 06:00, a linha 3 para para manutenção programada. O turno da manhã entra à hora do costume e passa para a linha 2.",
"status": "published",
"kind": "news",
"language": "pt",
"audience": {
"type": "departments",
"ids": [
"9c1d7e5f-2a3b-4c5d-8e9f-0a1b2c3d4e5f",
"44ab7e5f-2a3b-4c5d-8e9f-0a1b2c3d4e5f"
],
"names": [
"Manutenção",
"Qualidade"
]
},
"community": null,
"section": null,
"author": {
"id": "3f2a1b0c-9d8e-4f7a-8b6c-5d4e3f2a1b0c",
"name": "Ana García",
"email": "ana.garcia@empresa.com",
"external_id": "EMP-0042"
},
"notify": true,
"comments_enabled": true,
"pinned": false,
"acknowledgements": {
"required": true,
"confirmed": 0
},
"reads": 0,
"published_at": "2026-09-01T06:00:00.000Z",
"created_at": "2026-09-01T06:00:00.000Z",
"updated_at": "2026-09-01T06:00:00.000Z",
"url": "https://app.blastack.com/inicio#post-6b1f0f1e-0c2a-4c5e-9a3d-2f5b8c7d1e40"
}O destino vai por nome e não por identificador, porque é o que o vosso sistema tem à mão. Se o nome não existir, a resposta diz qual era e não publica nada: meia publicação seria pior.
Quando o sistema de pessoal marca a saída
Se o vosso sistema falar SCIM, isto já acontece sozinho e esta chamada não é precisa. Se não falar — o normal numa fábrica —, com uma linha a pessoa fica desativada e com as sessões fechadas de imediato. O caminho aceita o vosso próprio identificador, por isso não é preciso manter uma tabela de equivalências.
Pedido
curl -X DELETE https://app.blastack.com/api/v1/people/EMP-0042 \
-H "Authorization: Bearer blsk_a1b2c3d4e5f6_YOUR_SECRET"Resposta · 200
{
"id": "3f2a1b0c-9d8e-4f7a-8b6c-5d4e3f2a1b0c",
"external_id": "EMP-0042",
"email": "ana.garcia@empresa.com",
"name": "Ana García",
"job_title": "Chefe de turno",
"department": "Manutenção",
"center": "Nave 2",
"role": "editor",
"status": "disabled",
"language": null,
"created_at": "2026-02-11T08:14:00.000Z",
"updated_at": "2026-09-01T07:40:22.000Z"
}Desativa; não apaga. O que publicou fica, porque um quadro cheio de buracos não ajuda ninguém. Chamar duas vezes não é erro.
Todas as manhãs, ou na véspera de uma auditoria
Um cenário do Make ou um fluxo do n8n que peça os pendentes e os escreva numa folha: nome, departamento e se confirmaram. É o relatório que uma auditoria pede, e o que evita andar atrás de alguém pelo corredor.
Pedido
curl -G https://app.blastack.com/api/v1/announcements/6b1f0f1e-0c2a-4c5e-9a3d-2f5b8c7d1e40/acknowledgements \
--data-urlencode "state=pending" \
--data-urlencode "department=Manutenção" \
--data-urlencode "per_page=200" \
-H "Authorization: Bearer blsk_a1b2c3d4e5f6_YOUR_SECRET"Resposta · 200
{
"announcement": {
"id": "6b1f0f1e-0c2a-4c5e-9a3d-2f5b8c7d1e40",
"title": "Paragem da linha 3 na quinta-feira"
},
"summary": {
"recipients": 34,
"acknowledged": 27,
"pending": 7
},
"data": [
{
"person": {
"id": "3f2a1b0c-9d8e-4f7a-8b6c-5d4e3f2a1b0c",
"name": "Ana García",
"email": "ana.garcia@empresa.com",
"external_id": "EMP-0042",
"department": "Manutenção",
"center": "Nave 2"
},
"acknowledged": false,
"acknowledged_at": null
}
],
"page": 1,
"per_page": 200,
"total": 7
}O resumo conta-se sobre a população inteira e não sobre a página nem sobre o filtro, para que o «12 de 30» continue a querer dizer alguma coisa. A hora da confirmação é a da primeira vez e nunca mais se toca.
Eventos de saída
É o que torna isto verdadeiramente ligável. Sem eventos de saída, o disparador do vosso cenário tem de ser «de cinco em cinco minutos, pergunta», e isso é lento, paga-se à passagem e quase nunca encontra nada.
| Evento | Quando dispara |
|---|---|
| announcement.published | Saiu alguma coisa no quadro de avisos, venha por onde vier: o compositor, o editor completo, esta API, a fila de revisão ou uma publicação agendada que chegou à sua hora. O tipo viaja lá dentro, caso só vos interessem os comunicados simples e não os inquéritos ou os eventos. |
| announcement.pending_review | Uma publicação espera aprovação. Só dispara em empresas que têm a fila de revisão ligada. |
| announcement.acknowledged | Alguém confirmou uma leitura obrigatória. Um evento por pessoa, com quem e quando. |
| person.created | Alguém foi criado, tanto faz por onde: aprovisionamento, código de adesão, início de sessão único, ecrã de administração ou esta API. |
| person.deactivated | Alguém foi desativado. Como aqui não se apaga ninguém, este é o sinal de saída. |
{
"id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
"type": "announcement.published",
"occurred_at": "2026-09-01T06:00:00.000Z",
"organization_id": "0a9b8c7d-6e5f-4a3b-8c9d-0e1f2a3b4c5d",
"data": {
"announcement": {
"id": "6b1f0f1e-0c2a-4c5e-9a3d-2f5b8c7d1e40",
"title": "Parada de la línea 3 el jueves",
"body": "El jueves 4 a las 06:00 para la línea 3 por mantenimiento programado.",
"kind": "news",
"language": "es",
"requires_acknowledgement": true,
"audience": {
"type": "departments",
"names": [
"Mantenimiento",
"Calidad"
]
},
"community": "Planta de Getafe",
"author": {
"id": "3f2a1b0c-9d8e-4f7a-8b6c-5d4e3f2a1b0c",
"name": "Ana García",
"email": "ana.garcia@empresa.com",
"external_id": "EMP-0042"
},
"url": "https://app.blastack.com/inicio#post-6b1f0f1e-0c2a-4c5e-9a3d-2f5b8c7d1e40",
"status": "published"
}
}
}O que vai lá dentro muda com o evento; o sobrescrito não. O identificador não muda entre tentativas, por isso descartar um repetido é uma condição de uma linha do vosso lado.
| Cabeçalho | Para que serve |
|---|---|
| blastack-event | O que aconteceu. É o valor por onde se ramifica. |
| blastack-event-id | O identificador do evento. Não muda entre tentativas: é aquele em que assentar para nunca executar duas vezes a mesma coisa. |
| blastack-delivery-attempt | Que tentativa é esta, a começar na primeira. |
| blastack-signature | A assinatura. É a única coisa que separa um envio nosso de um inventado por quem descobrir o vosso endereço. |
A assinatura é HMAC-SHA256 sobre a marca temporal, um ponto e o corpo em bruto, sem interpretar. É o mesmo formato que usam as plataformas de pagamento, ou seja, aquele que provavelmente já escreveram uma vez.
import { createHmac, timingSafeEqual } from "node:crypto";
export function verify(rawBody, headers, secret) {
const sent = headers["blastack-signature"] ?? "";
const t = /t=(\d+)/.exec(sent)?.[1];
const v1 = /v1=([0-9a-f]+)/.exec(sent)?.[1];
if (!t || !v1) return false;
const mine = createHmac("sha256", secret)
.update(`${t}.${rawBody}`, "utf8")
.digest("hex");
if (v1.length !== mine.length) return false;
if (!timingSafeEqual(Buffer.from(v1, "hex"), Buffer.from(mine, "hex"))) {
return false;
}
return Math.abs(Date.now() / 1000 - Number(t)) < 300;
}Comparem em tempo constante e recusem tudo o que tenha uma marca com mais de alguns minutos. Sem essa segunda verificação, uma cópia de um envio antigo pode ser-vos reenviada durante anos e a assinatura continua válida.
Erros
Todo o erro devolve o mesmo objeto, com um código pensado para lhe escreverem uma condição por cima. Os códigos nunca mudam de nome: acrescentam-se. A mensagem ao lado é para quem lê o registo, e essa pode mudar.
{
"error": {
"status": 403,
"code": "insufficient_scope",
"message": "This API key does not have the \"metrics:read\" scope.",
"required_scope": "metrics:read",
"granted_scopes": [
"people:read"
]
},
"documentation": "https://blastack.com/en/developers"
}Um parâmetro desconhecido é recusado, não ignorado. Um filtro descartado em silêncio devolve-vos mais dados do que pediram e nada vos avisa.
RateLimit-Limit · RateLimit-Remaining · RateLimit-Reset · Retry-After
| Código | Quando sai |
|---|---|
| invalid_token | 401 · A chave falta, está mal escrita ou foi revogada. Não dizemos qual das três. |
| insufficient_scope | 403 · A chave é válida mas não tem o âmbito que essa chamada pede. A resposta diz qual era preciso e quais tem. |
| module_required | 403 · A empresa não tem contratado o módulo de identidade corporativa, que é aquele a que a API pertence. |
| read_only | 403 · O período experimental acabou e a empresa está só de leitura. Só afeta o que escreve. |
| rate_limited | 429 · Mais pedidos do que o permitido num minuto. A resposta diz quantos segundos esperar. |
| invalid_request | 400 · Falta um campo, sobra ou não se entende. A mensagem nomeia o parâmetro exato e lista os valores que admite. |
| not_found | 404 · Não há nada vosso com esse identificador. É também o que se recebe por algo de outra empresa: distinguir os dois casos seria uma forma de descobrir o que existe lá fora. |
| conflict | 409 · Choca com algo que já existe: duas pessoas com o mesmo correio, dois endereços de evento iguais. A resposta traz o identificador do que já estava, para se poder continuar. |
| server_error | 500 · Partiu-se algo do nosso lado. Nada do erro sai na resposta; inteiro fica no nosso registo. |
Limites
O que não faz
Quem vai integrar precisa dos limites antes de começar, não quando já tem meio cenário montado. Esta lista é o que um programador vai procurar e não vai encontrar, e atualiza-se quando alguma coisa deixa de ser verdade.
Para máquinas
Metade de uma avaliação de compra é hoje alguém a perguntar a um assistente se isto se liga a alguma coisa. Por isso a resposta está escrita para se poder ler sem conta e sem adivinhar nada.
O que mais for pedido é o próximo a escrever-se. E se algo desta página não bater certo com o que o servidor responde, é uma falha nossa e queremos sabê-lo no mesmo dia.