Documentação

Cartões: comandos da CLI

Encontre tipos de cartão, crie um cartão, defina parâmetros e dados ao vivo, visualize-o e atualize os dados por webhooks assinados.

Cada comando funciona como descrito na referência da CLI: flags globais, saída JSON, códigos de saída, revisões e tentativas.

Cartões

Conheça os tipos de cartões, crie uma instância e atualize seus dados ao vivo. Uma playlist posiciona o ID do cartão retornado.

screenrig cards list --category ops
screenrig cards show gauge
screenrig card create --type gauge --file gauge-params.json
screenrig card list
screenrig card show crd_01EXAMPLEGAUGE000000000
screenrig card params crd_01EXAMPLEGAUGE000000000 --file gauge-params.json
screenrig card data get crd_01EXAMPLEGAUGE000000000
screenrig card data put crd_01EXAMPLEGAUGE000000000 --file gauge-data.json --ttl 30m --expect-rev 1
screenrig card preview crd_01EXAMPLEGAUGE000000000 --output gauge.png
screenrig card delete crd_01EXAMPLEGAUGE000000000
ParâmetroTipoObrigatórioPadrãoNotas
cards list --tag TAGstringnãonenhumCorresponde a uma tag do catálogo.
cards list --category CATEGORYstringnãonenhumCorresponde a uma categoria do catálogo. Com --tag, um cartão precisa corresponder a ambas.
cards show <id>stringsimnenhumO id de cartão do catálogo obtido de cards list, como gauge.
card create --type IDstringsimnenhumO id de cartão do catálogo obtido de cards list.
card create --major Nintegernãoversão principal atualFixa uma versão principal do catálogo.
card create --file FILEcaminhosimnenhumOs parâmetros estáticos como objeto JSON de no máximo 1 MiB, ou - para stdin.
<id>stringsimnenhumO id de cartão crd_ que card show, card params, card delete e card data aceitam.
card params --file FILEcaminhosimnenhumOs novos parâmetros estáticos, lidos como em card create. Substituem os antigos imediatamente.
card data put --file FILEcaminhosimnenhumO documento de dados como objeto JSON, ou - para stdin. Substitui todo o documento.
card data put --ttl DURATIONstringnãonenhumDeixa os dados em branco depois desse tempo, inclusive nas telas offline: 30m, 12h ou 1d, de 1s a 365d. Não se combina com --expires-at.
card data put --expires-at INSTANTstringnãonenhumDeixa os dados em branco neste carimbo de data e hora ISO 8601, que traz um fuso horário. Uma gravação sem nenhuma das duas opções limpa a expiração anterior.
card data put --expect-rev REVISIONstringnãonenhumGrava somente se os dados ainda estiverem nesta revisão, conforme mostrada por card data get. Um valor desatualizado é revision_conflict (saída 6).
card preview <type|id>stringsimnenhumUm id de cartão do catálogo, ou um id de cartão crd_ para desenhar essa instância com seus próprios parâmetros e dados.
card preview --output FILEcaminhosimnenhumGrava o PNG aqui. Os diretórios pai são criados.
card preview --params FILEcaminhonãonenhumPropriedades estáticas como um objeto JSON.
card preview --data FILEcaminhonãonenhumO documento dinâmico como objeto JSON.
card preview --feed FILEcaminhonãonenhumO documento de feed do host como objeto JSON. Um feed de que o cartão precisa e que você omite é informado.
card preview --width PX / --height PXintegernão1920 / 1080Tamanho da imagem, de 1 a 8192.
card preview --layout LAYOUTstringnãofullfull, free, center, wide, header, footer, corner, chip ou strip: o layout a desenhar.
card preview --anchor ANCHORstringnãonenhumO canto de um layout corner ou chip, ou a borda de um strip.
card preview --now ISOstringnãoa hora atualCongela o relógio neste instante ISO 8601.
card preview --timezone ZONEstringnãoo desta máquinaDesenha neste fuso horário IANA, como America/Vancouver.

cards show mostra o params_schema e o data_schema do cartão, suas propriedades estáticas e dinâmicas, nível, layouts e feed, e um exemplo para copiar em uma página de playlist. card create retorna o id crd_ da instância, e uma nova execução idêntica após uma resposta perdida reutiliza a chave de idempotência salva.

card data put substitui o documento imediatamente, sem republicar a playlist. A validação do próprio cartão recusa um documento que ele não consegue mostrar (card_data_invalid), e uma expiração deixa os dados em branco em todas as telas quando nada os renova. card delete exclui a instância e seus dados, e responde resource_conflict (saída 5) enquanto uma playlist a posicionar.

card preview desenha o cartão em um Chromium ou Chrome local e grava um PNG; não publica nada. Defina SCREENRIG_BROWSER com o caminho do navegador quando nenhum dos habituais estiver instalado. data.file é o caminho gravado e data.unrendered lista o que a pré-visualização não conseguiu desenhar, como um feed do host que você não forneceu. Abra a imagem antes de publicar. Cartões embutidos descreve os layouts, as propriedades e os feeds de cada cartão.

Webhooks de cartão

Um webhook de cartão é uma URL que grava o documento de dados de um cartão, de modo que um sistema externo, como um CMS, um ponto de venda ou um script, envia dados para um cartão com um único POST HTTP. kv webhook create, list, rotate-secret e delete aceitam --card CARD_ID no lugar de --app-id, nunca os dois; update e deliveries abaixo funcionam apenas com cartões. Um cartão tem no máximo 20 webhooks.

kv webhook create --card CARD_ID [--description TEXT] [--map FILE|-] [--key-template TEMPLATE] [--signing]
                  [--verify VENDOR [--verify-secret-file FILE|-] [--verify-header NAME] [--verify-encoding hex|base64]
                   [--verify-timestamp-header NAME] [--verify-tolerance SECONDS]] [--handshake VENDOR]
kv webhook list --card CARD_ID
kv webhook rotate-secret <webhook_id> --card CARD_ID [--signing]
kv webhook delete <webhook_id> --card CARD_ID

Criar um webhook de cartão não exige chave. --map FILE (ou - para stdin) é o mapeamento, --key-template grava documentos por chave, --signing ativa a assinatura, e --verify e --handshake aceitam as postagens próprias de um fornecedor (Assinaturas e handshakes dos fornecedores). A resposta traz data.secret e, quando o webhook assina, data.signing_secret, cada um exibido uma única vez.

O remetente se autentica como em um webhook de aplicativo: Authorization: Bearer <secret> com o segredo srkw_…, ou HTTP Basic com o ID do webhook como nome de usuário, então https://kvw_ID:srkw_…@api.screenrig.ai/… serve para um remetente que aceita apenas uma URL. O corpo, de no máximo 1 MiB, é JSON ou application/x-www-form-urlencoded; um nome de formulário repetido vira um array. Sem mapeamento, o objeto enviado é o documento de dados do cartão.

Um mapeamento é um modelo JSON que constrói o documento a partir do corpo. Uma string com marcadores como {{body.alert.title}} ou {{body.items[0].name}} é texto, e uma string que é exatamente um marcador mantém o tipo do valor. Um caminho começa com body ou query (os parâmetros de consulta da URL), e um caminho que não contém nada fica vazio no texto e omite um valor isolado. $each mapeia um array com item e index no escopo, $group com $by agrupa na ordem da primeira ocorrência, $number lê 1,234.50, $3.50, 3,50 € ou 12% (adicione "$decimal": "," para uma vírgula decimal), $bool lê true, yes, y, 1 e x, e $text com $max corta o texto. O modelo é verificado ao salvar: invalid_request indica o lugar que falhou.

{
  "title": "{{body.alert.title}}",
  "body": "{{body.alert.message}}",
  "items": { "$each": "{{body.items}}", "$limit": 20, "$template": { "text": "{{item.name}}" } }
}
curl https://api.screenrig.ai/api/cards/crd_01EXAMPLEBOARD0000000000/kv-webhooks/kvw_01EXAMPLEWEBHOOK00000/write \
  -H "Authorization: Bearer $CARD_WEBHOOK_SECRET" \
  -H "Content-Type: application/json" \
  --data '{"alert":{"title":"Fire drill","message":"Leave by the east door"},"items":[{"name":"Floor 2"}]}'

--key-template TEMPLATE grava documentos por chave no lugar do documento próprio do cartão. O modelo é uma chave de dados do cartão com tokens {screen.field.NAME}, como room-{screen.field.room}, e o objeto mapeado (ou o corpo postado, sem mapeamento) contém apenas um array documents de objetos {fields, document}: cada objeto fields preenche o modelo e cada document é gravado na chave que ele produz. Um item de página que informa o mesmo modelo como seu data mostra a cada tela o documento dos seus próprios campos. Cada documento é verificado antes de gravar qualquer um, e uma chave repetida é recusada. Uma falha de armazenamento pode deixar parte do lote gravada: reenvie o mesmo corpo com o mesmo Idempotency-Key. As chaves que uma postagem omite mantêm seus dados, e um webhook não define expiração. Documentos por chave mostra um mapeamento.

Cada envio é verificado como dados do próprio cartão: card_data_invalid nomeia o caminho e nada é gravado. Um documento igual ao atual do cartão recebe a resposta unchanged e não grava nada, então nenhuma tela é acordada. Um envio aceito não conta no limite de solicitações de agente, um webhook aceita no máximo 120 envios por minuto e um cabeçalho Idempotency-Key deduplica as novas tentativas de um remetente por 24 horas.

Um endereço errado, um segredo errado ou ausente, um webhook desativado, uma assinatura ausente ou errada e todo GET recebem a mesma resposta 404, então uma pré-visualização de link ou um palpite não revela nada. kv webhook deliveries informa o motivo.

Com --signing, cada envio também deve levar ScreenRig-Signature: t=<unix seconds>,v1=<hex>, em que v1 é o HMAC-SHA256 de t, um ponto e o corpo bruto com o segredo de assinatura whsec_…, e t deve estar a no máximo cinco minutos do relógio do servidor. É o formato das assinaturas de webhook do próprio screenRIG.

Assinaturas e handshakes dos fornecedores

Os fornecedores assinam suas postagens do seu jeito, e alguns não conseguem enviar o seu segredo de jeito nenhum. Um webhook de cartão pode verificar a assinatura do fornecedor no lugar do segredo e responder ao handshake de configuração do fornecedor, então GitHub, Stripe, Shopify, Slack, Linear, Vercel, Asana, Microsoft Graph, monday.com, Trello e Azure Event Grid postam direto nele, sem intermediário. Qualquer outro remetente que assine com HMAC também funciona. Defina-os com --verify e --handshake em kv webhook create e altere-os com kv webhook update.

  • --verify VENDOR aceita a assinatura própria de um fornecedor, com --verify-secret-file FILE (ou - para stdin, nunca como argumento) contendo o segredo que o fornecedor mostra. Para generic_hmac, --verify-header NAME nomeia o cabeçalho que carrega a assinatura, --verify-encoding é hex (o padrão) ou base64, --verify-timestamp-header NAME nomeia um cabeçalho que carrega a hora Unix, e --verify-tolerance SECONDS é o quanto ela pode se afastar do relógio do servidor (300 por padrão). Uma postagem que traz a assinatura válida do fornecedor é aceita sem o segredo srkw_ do próprio webhook, que continua funcionando ao lado. O segredo do fornecedor é armazenado selado e mostrado apenas como set e uma hint dos seus quatro últimos caracteres. Em kv webhook update, --verify sem --verify-secret-file mantém o segredo armazenado enquanto o fornecedor for o mesmo, e --clear-verify remove a verificação e seu segredo. --verify e --signing se excluem mutuamente.
  • --handshake VENDOR é microsoft_graph, monday, trello ou azure_event_grid, e --clear-handshake o remove. O Slack e o Asana respondem aos próprios handshakes por --verify.
--verifyCabeçalhoO que é assinadoCarimbo de data e hora
githubX-Hub-Signature-256HMAC-SHA256 do corpoNenhum
stripeStripe-SignatureHMAC-SHA256 do carimbo de data e hora, um ponto e o corpo; qualquer v1 pode corresponder5 minutos
shopifyX-Shopify-Hmac-Sha256HMAC-SHA256 do corpo, em base64Nenhum
slackX-Slack-SignatureHMAC-SHA256 de v0:, o carimbo de data e hora, dois-pontos e o corpoX-Slack-Request-Timestamp, 5 minutos
linearLinear-SignatureHMAC-SHA256 do corpowebhookTimestamp no corpo, 1 minuto
vercelx-vercel-signatureHMAC-SHA1 do corpoNenhum
asanaX-Hook-SignatureHMAC-SHA256 do corpo, com o X-Hook-Secret do handshake como chaveNenhum
generic_hmacO --verify-header que você nomeiaHMAC-SHA256 do corpo ou, com um --verify-timestamp-header, do carimbo de data e hora, um ponto e o corpo--verify-tolerance

A chave de cada HMAC é o texto do segredo como o fornecedor o mostra (o do Stripe inclui whsec_). Uma assinatura é conferida no corpo exatamente como chegou, em tempo constante, antes de a postagem consumir orçamento de escrita, e é julgada antes do seu carimbo de data e hora: timestamp_stale sempre significa que o segredo estava certo. Um corpo pode ser JSON, um formulário ou multipart/form-data, em que um campo de texto é body.FIELD e os arquivos são contados, não lidos.

FornecedorO screenRIG respondePostagens seguintes
Slack (--verify slack)O url_verification assinado com o seu challenge; uma pessoa que testa com curl pode enviar o segredo do webhook no lugarAssinadas com o segredo de assinatura
Asana (--verify asana)O X-Hook-Secret do handshake, que ele guarda selado como chave de cada X-Hook-Signature. O mesmo segredo de novo é uma nova tentativa; um diferente é recusado como handshake_invalidX-Hook-Signature
Microsoft Graph (--handshake microsoft_graph)O ?validationToken= decodificado como text/plainLevam o segredo do webhook
monday.com (--handshake monday)O challenge que ele posta, devolvido como JSONLevam o segredo do webhook
Trello (--handshake trello)Uma verificação HEAD responde 200 sem corpo, só para este webhookLevam o segredo do webhook
Azure Event Grid (--handshake azure_event_grid){"validationResponse": "CODE"}Levam o segredo do webhook

Um handshake só é respondido para um webhook configurado para esse fornecedor, antes de qualquer credencial ser pedida, a uma solicitação que é esse handshake, e nunca por um webhook desativado. Ele não grava nada, nunca é cobrado e não gasta orçamento de taxa. O Microsoft Graph, o monday.com, o Trello e o Azure Event Grid não enviam nenhum cabeçalho que o screenRIG verifique, então as entregas deles só são aceitas com o segredo do webhook. O Azure Event Grid o leva como um cabeçalho de entrega estático, Authorization: Bearer srkw_…, marcado como segredo, e seus eventos chegam como um array, então um mapeamento lê body[0].

FornecedorNas configurações do fornecedor
GitHubSettings, Webhooks, Add webhook: a Payload URL é a url do webhook, o tipo de conteúdo é application/json, e o mesmo segredo. O ping do GitHub é assinado e aceito
StripeWorkbench, Webhooks: adicione a url e revele o segredo de assinatura dela. Enquanto o Stripe faz a rotação de um segredo, ele envia um v1 para cada um e qualquer um é aceito; depois substitua o segredo armazenado com kv webhook update --verify stripe --verify-secret-file FILE
ShopifyAssine com a url no formato JSON. O segredo é o segredo de cliente do aplicativo
SlackA Request URL da Events API é a url, e o segredo é o segredo de assinatura do aplicativo. Um comando de barra posta um formulário: {{body.text}}, {{body.user_name}}
LinearNas configurações da API, crie um webhook com a url e copie o segredo de assinatura dele. O webhookTimestamp do corpo precisa estar a até um minuto do relógio do servidor
VercelTeam settings, Webhooks: crie um com a url. O Vercel mostra o segredo uma única vez
AsanaCrie o webhook com --verify asana: ele ainda não tem segredo e recusa eventos como secret_pending. Depois crie o webhook do Asana com target definido como a url, e o handshake define o segredo. Para adotar um novo segredo, execute kv webhook update com --clear-verify e depois de novo com --verify asana
Microsoft GraphCrie a assinatura com notificationUrl definido como a url
monday.comExecute create_webhook com a url
TrelloPOST /1/webhooks com callbackURL definido como a url
Azure Event GridCrie a assinatura de eventos com a url como endpoint do webhook, e adicione o cabeçalho de entrega acima
echo '{"title":"{{body.repository.full_name}}","body":"{{body.head_commit.message}}"}' |
  screenrig kv webhook create --card crd_01EXAMPLEBOARD0000000000 --description "Pushes" \
    --verify github --verify-secret-file github.secret --map -

Um remetente que assina com o próprio HMAC nomeia o cabeçalho, a codificação e, se assina um carimbo de data e hora, o cabeçalho do carimbo:

echo '{"title":"{{body.sensor}}","body":"{{body.state}}"}' |
  screenrig kv webhook create --card crd_01EXAMPLEBOARD0000000000 --verify generic_hmac --verify-secret-file acme.secret \
    --verify-header X-Acme-Signature --verify-encoding base64 --verify-timestamp-header X-Acme-Time --verify-tolerance 120 \
    --map -
ts=$(date +%s); body='{"sensor":"door","state":"open"}'
sig=$(printf '%s.%s' "$ts" "$body" | openssl dgst -sha256 -hmac "$SECRET" -binary | openssl base64 -A)
curl "$URL" -H "Content-Type: application/json" -H "X-Acme-Time: $ts" -H "X-Acme-Signature: $sig" -d "$body"

Toda falha dá o mesmo 404 de qualquer outra recusa. kv webhook deliveries mostra o motivo, e um handshake aparece com o resultado handshake:

MotivoSignificado
signature_missingHá uma verificação de fornecedor definida e a postagem não trazia nem o segredo nem o cabeçalho do fornecedor
signature_invalidO cabeçalho está malformado ou não corresponde ao corpo
timestamp_missingA assinatura precisa de um carimbo de data e hora que a postagem não trazia
timestamp_staleA assinatura é válida e o carimbo de data e hora dela está fora da janela
secret_pendingUma verificação do Asana ainda está esperando o handshake
handshake_invalidA solicitação é o handshake de um fornecedor e não pode ser respondida

kv webhook update#

Alterar um webhook de cartão: sua descrição, mapeamento, documentos por chave, estado ativado, assinatura, verificação de fornecedor ou handshake.

kv webhook update <webhook_id> --card CARD_ID [--description TEXT] [--map FILE|-] [--clear-map]
                   [--key-template TEMPLATE] [--clear-key-template] [--enable|--disable] [--signing|--no-signing]
                   [--verify VENDOR [--verify-secret-file FILE|-] [--verify-header NAME] [--verify-encoding hex|base64]
                    [--verify-timestamp-header NAME] [--verify-tolerance SECONDS]] [--clear-verify]
                   [--handshake VENDOR] [--clear-handshake]
ParâmetroTipoObrigatórioPadrãoNotas
<webhook_id>stringsimnenhumO id do webhook kvw_.
--card CARD_IDstringsimnenhumO ID de cartão crd_.
--description TEXTstringnãonenhumO que envia para ele, no máximo 200 bytes. Não deve conter credenciais.
--map FILEcaminhonãonenhumSubstituir o mapeamento por um objeto JSON lido de um arquivo, ou - para stdin. Não se combina com --clear-map.
--clear-mapbooleannãodesligadoRemover o mapeamento: o objeto enviado passa a ser o documento.
--key-template TEMPLATEstringnãonenhumDefine o modelo de chave que dá a chave aos documentos, como room-{screen.field.room}. Não se combina com --clear-key-template.
--clear-key-templatebooleannãodesligadoVolta a gravar o documento próprio do cartão.
--enable / --disablebooleannãodesligado--disable responde a cada envio como a um segredo errado até --enable.
--signing / --no-signingbooleannãodesligado--signing exige o cabeçalho de assinatura e mostra o segredo de assinatura uma vez; um webhook que já assina mantém o seu segredo, que kv webhook rotate-secret --signing substitui. --no-signing deixa de exigi-lo. Não se combina com --verify.
--verify VENDORstringnãonenhumSubstitui a verificação do fornecedor: github, stripe, shopify, slack, linear, vercel, asana ou generic_hmac. Sem --verify-secret-file, o segredo armazenado é mantido se o fornecedor for o mesmo, de modo que um cabeçalho ou uma janela pode mudar sozinho; um fornecedor diferente precisa do seu. Não se combina com --clear-verify.
--verify-secret-file FILEcaminhonãoo segredo armazenadoLê o segredo do fornecedor de um arquivo, ou - para stdin (nunca como argumento). asana não aceita nenhum. Apenas uma opção lê stdin.
--verify-header NAMEstringcom generic_hmacnenhumO cabeçalho que carrega a assinatura, de 1 a 100 letras, dígitos, - ou _.
--verify-encoding ENCODINGstringnãohexCom generic_hmac: hex ou base64; pode começar com sha256=.
--verify-timestamp-header NAMEstringnãonenhumCom generic_hmac: um cabeçalho que carrega a hora Unix em segundos ou em milissegundos com 13 dígitos.
--verify-tolerance SECONDSintegernão300Com --verify-timestamp-header: o quanto o carimbo de data e hora pode se afastar do relógio do servidor, de 1 a 86400.
--clear-verifybooleannãodesligadoDeixa de aceitar a assinatura do fornecedor e esquece seu segredo. Uma verificação do Asana só aceita um novo handshake depois de --clear-verify e de novo --verify asana.
--handshake VENDORstringnãonenhumDefine o handshake que a URL responde: microsoft_graph, monday, trello ou azure_event_grid. Não se combina com --clear-handshake.
--clear-handshakebooleannãodesligadoDeixa de responder ao handshake do fornecedor.

Pelo menos uma alteração é obrigatória.

screenrig kv webhook update kvw_01EXAMPLEWEBHOOK00000 --card crd_01EXAMPLEBOARD0000000000 --map alert-map.json
screenrig kv webhook update kvw_01EXAMPLEWEBHOOK00000 --card crd_01EXAMPLEBOARD0000000000 --verify stripe --verify-secret-file stripe.secret
screenrig kv webhook update kvw_01EXAMPLEWEBHOOK00000 --card crd_01EXAMPLEBOARD0000000000 --clear-verify

O envelope é o webhook. data.signing_secret aparece uma só vez, na resposta que ativou a assinatura. Após uma atualização interrompida ou ambígua, execute novamente o comando idêntico: ele reutiliza a chave de idempotência salva.

kv webhook deliveries#

Ler o log de entregas de um webhook de cartão, do mais recente para o mais antigo, dos últimos sete dias.

kv webhook deliveries <webhook_id> --card CARD_ID [--limit N]
ParâmetroTipoObrigatórioPadrãoNotas
<webhook_id>stringsimnenhumO id do webhook kvw_.
--card CARD_IDstringsimnenhumO ID de cartão crd_.
--limit Nnumbernão100Quantas entregas retornar, de 1 a 100.
screenrig kv webhook deliveries kvw_01EXAMPLEWEBHOOK00000 --card crd_01EXAMPLEBOARD0000000000

Cada item tem at, outcome (written, unchanged, refused, invalid ou handshake), reason (credentials, signature para uma ScreenRig-Signature que falhou, disabled, body, mapping, card_data_invalid, rate_limited, internal ou um motivo de fornecedor da tabela acima), detail, status, bytes, files (as partes de arquivo de uma postagem multipart, que são ignoradas), revision e request_id. Nenhum corpo, cabeçalho ou credencial é armazenado, e uma postagem para um endereço errado não deixa linha.

Outros grupos de comandos