ai newsMo., 2. Nov.
EilmeldungAnthropic verzwölffacht den Umsatz, macht aber 23 Milliarden Dollar Verlust

Claude Batch API: V reduziert Kosten für Massenabfragen

Claude Batch API: Halbe Kosten für Massenabfragen

dev.toMontag 08:34 · 02.11.DE9 Min. Lesezeit
Bild: dev.to

Veröffentlicht am 2. Nov. • Ursprünglich publiziert auf apidog.com

Kurzantwort: Die Claude Batch API verarbeitet Anfragen der Messages API asynchron mit 50 Prozent Rabatt auf sowohl Eingabe- als auch Ausgabe-Tokens. Sie senden bis zu 100.000 Anfragen (oder 256 MB) in einem einzigen Aufruf, führen Polling durch, bis der Batch abgeschlossen ist, und lesen anschließend die Ergebnisse, die über Ihre eigene custom_id indiziert sind. Die meisten Batches sind in weniger als einer Stunde fertig, das Maximum beträgt 24 Stunden.

Sie haben 40.000 Support-Tickets zu klassifizieren, oder einen Produktkatalog neu zu formulieren, oder einen Monat an Transkriptionen zusammenzufassen. Nichts davon ist dringend. Jede dieser Anfragen wird trotzdem zum vollen Preis abgerechnet, wenn Sie sie einzeln abschicken, und Sie verbringen den Nachmittag damit, Wiederholungsversuche gegen Ihr Rate-Limit zu überwachen.

Die Claude Batch API existiert genau für diese Art von Arbeit. Sie übergeben Anthropic eine Liste von Anfragen, kümmern sich um Ihre Angelegenheiten und kehren zu einer Ergebnisdatei zurück, die die Hälfte dessen gekostet hat, was dieselben Anfragen synchron gekostet hätten. Ohne Warteschlange, ohne Feintuning der Nebenläufigkeit, ohne Backoff-Logik.

Dieser Leitfaden behandelt, was der Batch-Endpoint tut, was er kostet, wie man einen Job sendet und einsammelt und wie man seinen Coding-Agenten alles mit dem Apidog CLI testen lässt, bevor man ihn auf echte Daten loslässt.

Die Claude Batch API ist ein asynchroner Endpoint unter /v1/messages/batches, der viele Anfragen der Messages API in einer einzigen Übermittlung entgegennimmt und deren Ergebnisse zurückgibt, sobald die Verarbeitung abgeschlossen ist. Sie tauscht Latenz gegen einen Rabatt von 50 Prozent. Anthropic dokumentiert sie unter batch processing.

Die Einschränkungen, für die Sie entwerfen müssen:

Dieser letzte Punkt ist es, der Leute erwischt. Ein Batch ist ein Sack, keine Warteschlange.

Der Rabatt ist ein fester Wert von 50 Prozent auf sowohl Eingabe- als auch Ausgabe-Tokens, angewendet auf das Modell, das jede Anfrage benennt. Sie können Modelle innerhalb desselben Batches mischen, sodass ein billiger Klassifikator und ein teurer Zusammenfasser zusammen laufen können.

Lesen Sie die Zeilen zu Haiku aufmerksam. Haiku 5.5 hat eine Preisgestaltung nach Prompt-Größe, sodass ein Prompt, der 100.000 Tokens überschreitet, mit dem 5-fachen des Tarifs für kurze Prompts abgerechnet wird, mit oder ohne Batch-Rabatt. Kalkulieren Sie Arbeit mit Haiku bei langem Kontext mit 0,25 / 1,25 Dollar, nicht mit 0,05 / 0,25 Dollar. Prüfen Sie die Preisseite von Anthropic, bevor Sie eine Kalkulation mit diesen Zahlen erstellen, und lesen Sie unsere Analyse, wohin die Ausgaben für die Claude API fließen, falls die Rechnung der Grund ist, warum Sie hier sind.

Der Batch-Preis stapelt sich zudem mit Prompt-Caching, wo die echten Einsparungen liegen. Mehr dazu weiter unten.

Installieren Sie das offizielle Python-SDK und stellen Sie eine Liste von Anfragen zusammen. Jede trägt eine custom_id, die Sie selbst wählen, und ein params-Objekt, das exakt wie ein normaler Aufruf von messages.create() aussieht.

import anthropic from anthropic.types.message_create_params import MessageCreateParamsNonStreaming from anthropic.types.messages.batch_create_params import Request client = anthropic. Anthropic () tickets = [ " Card declined three times, support chat timed out. ", " Love the new dashboard, the export button is hidden though.

", " Webhook stopped firing after the 2.4 upgrade. ", ] batch = client. messages. batches. create ( requests = [ Request ( custom_id = f " ticket- { i } ", params = MessageCreateParamsNonStreaming ( model = " claude-haiku-5-5 ", max_tokens = 1024, output_config = { " effort ": " low " }, messages = [{ " role ": " user ", " content ": f " Label this ticket billing, bug, or praise. One word. \n\n { text } ", }], ), ) for i, text in enumerate ( tickets ) ] ) print ( batch. id, batch. processing_status ) Enter fullscreen mode Exit fullscreen mode Geben Sie der custom_id eine Bedeutung.

Ein Datenbank-Primärschlüssel oder ein Dateipfad erspart später einen Join, und sie ist das einzige Element, das ein Ergebnis mit Ihrer Eingabe verknüpft.

Wenn Sie rohes HTTP bevorzugen, geht derselbe Payload per POST an https://api.anthropic.com/v1/messages/batches mit Ihren Headern x-api-key und anthropic-version. Die Referenz zur Erstellung von Message-Batches enthält das vollständige Schema.

Rufen Sie den Batch so lange ab, bis processing_status den Wert ended zeigt, und verarbeiten Sie dann die Ergebnisse. Jedes Ergebnis trägt die custom_id, die Sie festgelegt haben, und einen result.type von succeeded, errored, canceled oder expired.

import time while True: batch = client. messages. batches. retrieve ( batch. id ) if batch. processing_status == " ended ": break print ( " still working: ", batch. request_counts. processing ) time. sleep ( 30 ) labels, retry = {}, [] for result in client. messages. batches. results ( batch. id ): if result. result. type == " succeeded ": msg = result. result. message labels [ result. custom_id ] = next ( b. text for b in msg. content if b. type == " text " ) elif result. result. type == " errored ": retry. append ( result. custom_id ) print ( f " { len ( labels ) } labeled, { len ( retry ) } need another pass " ) Enter fullscreen mode Exit fullscreen mode Zwei Fehlerarten verdienen eine gesonderte Behandlung. Ein Fehler invalid_request bedeutet, dass der Anfragekörper fehlerhaft war, korrigieren Sie ihn also vor dem erneuten Senden. Alles andere liegt serverseitig und kann unverändert wiederholt werden.

Ein Ergebnis expired bedeutet, dass das 24-Stunden-Fenster geschlossen wurde, bevor diese Anfrage lief, und auch diese senden Sie erneut.

Führen Sie Polling in einem Intervall von 30 bis 60 Sekunden durch. Den Retrieve-Endpoint jede Sekunde zu bombardieren bringt nichts und zählt gegen Ihre Rate-Limits der Claude API.

Der größte Gewinn entsteht durch die Kombination der beiden Rabatte. Wenn alle Anfragen in Ihrem Batch ein langes gemeinsames Präfix teilen, einen Styleguide, eine Taxonomie, einen 40-seitigen Vertrag, markieren Sie dieses Präfix mit cache_control und senden Sie dasselbe markierte Präfix in allen 10.000 Anfragen.

shared_system = [ { " type ": " text ", " text ": " You are a support triage analyst. " }, { " type ": " text ", " text ": taxonomy_document, # thousands of tokens, identical every time " cache_control ": { " type ": " ephemeral " }, }, ] Enter fullscreen mode Exit fullscreen mode Setzen Sie diesen Systemblock in jede Request des Batches. Jede Anfrage, deren Präfix Byte für Byte einem aktiven Cache-Eintrag entspricht, wird mit Cache-Read-Tarifen für dieses Präfix abgerechnet, und der Batch-Rabatt von 50 Prozent gilt sowohl für Cache-Lese- als auch für Cache-Schreibvorgänge.

Kalkulieren Sie nicht mit einer perfekten Trefferquote: Ein Batch verarbeitet seine Anfragen parallel statt in Reihenfolge, sodass Cache-Treffer innerhalb eines Batches nach bestem Bemühen erfolgen. Der Prompt-Caching-Leitfaden von Anthropic behandelt die Präfix-Regeln: Jedes Byte, das sich vor Ihrem Breakpoint ändert, invalidiert alles danach, halten Sie also Zeitstempel und text je Element hinter dem gecachten Block.

Bevor Sie Geld für 100.000 echte Anfragen ausgeben, wollen Sie einen Regressionstest über den Batch-Lebenszyklus: erstellen, abrufen, Ergebnisse. Das von Hand in einer GUI zu schreiben ist mühsam. Lassen Sie Ihren Coding-Agenten das mit dem Apidog CLI erledigen.

npm install -g apidog-cli@latest apidog auth login --with-token <YOUR_TOKEN> apidog skill install # pick Claude Code when prompted Enter fullscreen mode Exit fullscreen mode Dann ein Prompt für Claude Code:

In Apidog project 4820193, create a test case for POST https://api.anthropic.com/v1/messages/batches that submits two Haiku 5.5 requests with custom_id ticket-0 and ticket-1, asserts the response has an id and processing_status, then polls GET /v1/messages/batches/{id} until processing_status is ended. Run it against the anthropic-staging environment and summarize failures. Enter fullscreen mode Exit fullscreen mode Der Agent liest das Schema des Payloads, validiert sein eigenes JSON und erstellt und führt dann den Fall aus:

apidog cli-schema get test-case-create apidog cli-schema validate test-case-create --file batch-case.json apidog test-case create --project 4820193 --file batch-case.json apidog run --test-case 77214 --project 4820193 -e 992301 -r cli,json Enter fullscreen mode Exit fullscreen mode Ihr API-Schlüssel liegt in einer Umgebungsvariable von Apidog und gelangt so nie in einen Prompt oder ein Repository. Wechseln Sie den Reporter auf -r junit, und derselbe Befehl läuft in der CI bei jedem Merge, was der Aufbau in unserem Leitfaden zur Apidog-CLI-Pipeline ist. Falls Sie den CLI noch nicht mit Ihrem Agenten verbunden haben, beginnen Sie mit der Verwendung des Apidog CLI in Claude Code.

Einige Dinge funktionieren dort ebenfalls nicht. Der schnelle Modus ist in der Batch API nicht verfügbar, serverseitige Refusal-Fallbacks werden dort abgelehnt, und bei Claude Opus 5.5 und Claude Sonnet 5.5 gibt ein erzwungenes tool_choice von any oder tool innerhalb eines Batches einen 400er zurück, genau wie bei einem normalen Aufruf. Verwenden Sie stattdessen tool_choice: auto mit strict: true.

Wenn Sie Multi-Provider-Infrastruktur betreiben, existiert dasselbe Muster auch woanders: siehe die OpenAI Batch API und den Batch-Modus der Gemini API. Die Formen unterscheiden sich, die Ersparnis nicht.

Es ist ein asynchroner Endpoint, der Standard-Anfragen der Messages API massenweise zu 50 Prozent der normalen Token-Preise ausführt. Sie senden eine Liste von Anfragen mit Ihren eigenen IDs, führen Polling durch, bis der Batch abgeschlossen ist, und lesen die Ergebnisse innerhalb von bis zu 29 Tagen.

Die halbe Standardtarifrate sowohl für die Eingabe als auch für die Ausgabe. Beim Claude Sonnet 5.5 entspricht das 1,00 US-Dollar pro Million Eingabe-Tokens und 5,00 US-Dollar pro Million Ausgabe-Tokens, gegenüber 2,00 und 10,00 US-Dollar bei synchroner Verarbeitung.

Die meisten Batches sind innerhalb einer Stunde abgeschlossen. Das Maximum liegt bei 24 Stunden, danach gibt jede nicht verarbeitete Anfrage ein Ergebnis mit dem Status expired zurück, das Sie anschließend erneut einreichen.

Ja, und die Rabatte summieren sich. Markieren Sie ein gemeinsames Präfix mit cache_control, wiederholen Sie dieses identische Präfix in jeder Anfrage, und Cache-Lesevorgänge werden zu einem Bruchteil des Eingabepreises zusätzlich zum Batch-Rabatt abgerechnet.

Nur diese eine Anfrage schlägt fehl. Ihr Ergebnis enthält type: "errored" mit einem Fehlerobjekt; alles Übrige wird weiterhin erfolgreich verarbeitet. Validierungsfehler erfordern eine korrigierte Payload, während Serverfehler ohne Änderungen sicher wiederholt werden können.

Ja. client.messages.batches.cancel(batch_id) versetzt den Batch in den Zustand canceling. Bereits abgeschlossene Anfragen behalten ihre Ergebnisse; der Rest kommt als canceled zurück.

Ja. Alle Funktionen der Messages API funktionieren innerhalb eines Batches, einschließlich Vision, Tool-Definitionen und System-Prompts. Ausgenommen sind der schnelle Modus, serverseitige Fallbacks und die erzwungene Tool-Auswahl bei den Modellen 5.5.

Die Batch-Verarbeitung ist nach dem Prompt Caching die zweitgrößte kostenlose Ersparnis bei der Claude API und kostet nichts an Qualität: dieselben Modelle, dieselben Funktionen, der halbe Preis, bezahlt mit Latenz, die Sie wahrscheinlich ohnehin nicht genutzt haben. Indizieren Sie Ihre Ergebnisse über custom_id, cachen Sie das gemeinsame Präfix und behandeln Sie expired als Wiederholungsversuch statt als Fehler.

Testen Sie den Lebenszyklus, bevor Sie ihn skalieren. Installieren Sie das Apidog CLI, verweisen Sie Ihren Coding-Agenten auf die Batch-Endpunkte und lassen Sie den generierten Testfall in CI weiterlaufen, damit Sie eine Schema-Änderung nie mit 100.000 Anfragen überrascht. Der kostenlose Tarif umfasst 4 Nutzer, und Sie können Apidog herunterladen und den ersten Testfall in wenigen Minuten zum Laufen bringen.

Automatisch übersetzt. Das Original auf Englisch ist unten aufklappbar.

Original (Englisch) anzeigen

Posted on Nov 2 • Originally published at apidog.com

Resposta rápida: A Claude Batch API processa requisições da Messages API de forma assíncrona com 50% de desconto tanto nos tokens de entrada quanto nos de saída. Você envia até 100.000 requisições (ou 256 MB) em uma única chamada, faz polling até o batch terminar e então lê os resultados indexados pelo seu próprio custom_id. A maioria dos batches termina em menos de uma hora, e o teto máximo é 24 horas.

Você tem 40.000 tickets de suporte para classificar, ou um catálogo de produtos para reescrever, ou um mês de transcrições para resumir. Nada disso é urgente. Cada uma dessas chamadas ainda é cobrada a preço cheio quando você as dispara uma de cada vez, e você passa a tarde vigiando retentativas contra seu rate limit.

A Claude Batch API existe exatamente para esse tipo de trabalho. Você entrega ao Anthropic uma lista de requisições, vai cuidar da vida e volta para um arquivo de resultados que custou metade do que as mesmas chamadas teriam custado de forma síncrona. Sem fila para rodar, sem ajuste de concorrência, sem lógica de backoff.

Este guia cobre o que o endpoint de batch faz, quanto custa, como enviar e coletar um job, e como deixar seu agente de codificação testar tudo isso com o Apidog CLI antes de apontá-lo para dados reais.

A Claude Batch API é um endpoint assíncrono em /v1/messages/batches que aceita muitas requisições da Messages API em um único envio e retorna seus resultados quando o processamento termina. Ela troca latência por um desconto de 50%. A Anthropic a documenta em batch processing.

As restrições com as quais você precisa projetar:

Esse último ponto é o que pega as pessoas. Um batch é um saco, não uma fila.

O desconto é um valor fixo de 50% tanto nos tokens de entrada quanto de saída, aplicado ao modelo que cada requisição nomeia. Você pode misturar modelos dentro de um mesmo batch, então um classificador barato e um resumidor caro podem andar juntos.

Leia as linhas do Haiku com atenção. O Haiku 5.5 tem preço por tamanho de prompt, então um prompt que ultrapassa 100.000 tokens é cobrado 5x a tarifa de prompt curto, com ou sem desconto de batch. Faça a previsão de trabalho com Haiku de contexto longo a $0.25 / $1.25, não $0.05 / $0.25. Confira a página de preços da Anthropic antes de construir uma previsão com esses números, e leia nossa análise de para onde vai o gasto com a Claude API se a fatura é o motivo de você estar aqui.

O preço de batch também se acumula com prompt caching, que é onde estão as economias reais. Mais sobre isso abaixo.

Instale o SDK oficial de Python e monte uma lista de requisições. Cada uma carrega um custom_id que você escolhe e um objeto params que se parece exatamente com uma chamada normal de messages.create().

import anthropic from anthropic.types.message_create_params import MessageCreateParamsNonStreaming from anthropic.types.messages.batch_create_params import Request client = anthropic. Anthropic () tickets = [ " Card declined three times, support chat timed out. ", " Love the new dashboard, the export button is hidden though.

", " Webhook stopped firing after the 2.4 upgrade. ", ] batch = client. messages. batches. create ( requests = [ Request ( custom_id = f " ticket- { i } ", params = MessageCreateParamsNonStreaming ( model = " claude-haiku-5-5 ", max_tokens = 1024, output_config = { " effort ": " low " }, messages = [{ " role ": " user ", " content ": f " Label this ticket billing, bug, or praise. One word. \n\n { text } ", }], ), ) for i, text in enumerate ( tickets ) ] ) print ( batch. id, batch. processing_status ) Enter fullscreen mode Exit fullscreen mode Faça o custom_id carregar significado.

Uma chave primária de banco de dados ou um caminho de arquivo economiza um join depois, e é a única coisa que liga um resultado de volta à sua entrada.

Se você preferir HTTP puro, o mesmo payload vai para POST https://api.anthropic.com/v1/messages/batches com seus cabeçalhos x-api-key e anthropic-version. A referência de criação de message batch tem o schema completo.

Recupere o batch até que processing_status leia ended, então transmita os resultados. Cada resultado carrega o custom_id que você definiu e um result.type de succeeded, errored, canceled ou expired.

import time while True: batch = client. messages. batches. retrieve ( batch. id ) if batch. processing_status == " ended ": break print ( " still working: ", batch. request_counts. processing ) time. sleep ( 30 ) labels, retry = {}, [] for result in client. messages. batches. results ( batch. id ): if result. result. type == " succeeded ": msg = result. result. message labels [ result. custom_id ] = next ( b. text for b in msg. content if b. type == " text " ) elif result. result. type == " errored ": retry. append ( result. custom_id ) print ( f " { len ( labels ) } labeled, { len ( retry ) } need another pass " ) Enter fullscreen mode Exit fullscreen mode Dois modos de falha merecem tratamento separado. Um erro invalid_request significa que o corpo da requisição estava errado, então corrija antes de reenviar. Qualquer outra coisa é do lado do servidor e segura de repetir como está.

Um resultado expired significa que a janela de 24 horas se fechou antes de aquela requisição rodar, e você reenvia essas também.

Faça polling em um temporizador de 30 a 60 segundos. Martelar o endpoint de retrieve a cada segundo não te dá nada e conta contra seus rate limits da Claude API.

O maior ganho vem de combinar os dois descontos. Se toda requisição no seu batch compartilha um prefixo longo, um guia de estilo, uma taxonomia, um contrato de 40 páginas, marque esse prefixo com cache_control e envie o mesmo prefixo marcado em todas as 10.000 requisições.

shared_system = [ { " type ": " text ", " text ": " You are a support triage analyst. " }, { " type ": " text ", " text ": taxonomy_document, # thousands of tokens, identical every time " cache_control ": { " type ": " ephemeral " }, }, ] Enter fullscreen mode Exit fullscreen mode Coloque esse bloco system em cada Request do batch. Qualquer requisição cujo prefixo corresponda byte a byte a uma entrada de cache ativa é cobrada com tarifas de cache-read para esse prefixo, e o desconto de 50% do batch se aplica tanto a leituras quanto a escritas de cache.

Não orce para uma taxa de acerto perfeita: um batch processa suas requisições de forma concorrente em vez de em ordem, então acertos de cache dentro de um batch são o melhor esforço. O guia de prompt caching da Anthropic cobre as regras de prefixo: qualquer byte que mude antes do seu breakpoint invalida tudo depois dele, então mantenha timestamps e texto por item depois do bloco cacheado.

Antes de gastar dinheiro com 100.000 requisições reais, você quer um teste de regressão sobre o ciclo de vida do batch: criar, recuperar, resultados. Escrever isso à mão em uma GUI é lento. Deixe seu agente de codificação fazer isso com o Apidog CLI.

npm install -g apidog-cli@latest apidog auth login --with-token <YOUR_TOKEN> apidog skill install # pick Claude Code when prompted Enter fullscreen mode Exit fullscreen mode Então um prompt para o Claude Code:

In Apidog project 4820193, create a test case for POST https://api.anthropic.com/v1/messages/batches that submits two Haiku 5.5 requests with custom_id ticket-0 and ticket-1, asserts the response has an id and processing_status, then polls GET /v1/messages/batches/{id} until processing_status is ended. Run it against the anthropic-staging environment and summarize failures. Enter fullscreen mode Exit fullscreen mode O agente lê o schema do payload, valida o próprio JSON, então cria e executa o caso:

apidog cli-schema get test-case-create apidog cli-schema validate test-case-create --file batch-case.json apidog test-case create --project 4820193 --file batch-case.json apidog run --test-case 77214 --project 4820193 -e 992301 -r cli,json Enter fullscreen mode Exit fullscreen mode Sua API key fica em uma variável de ambiente do Apidog, então nunca cai em um prompt ou em um repositório. Troque o reporter para -r junit e o mesmo comando roda em CI a cada merge, que é a configuração do nosso guia de pipeline do Apidog CLI. Se você ainda não conectou o CLI ao seu agente, comece com usando o Apidog CLI no Claude Code.

Algumas coisas também não atravessam. O modo rápido não está disponível na Batch API, fallbacks de recusa do lado do servidor são rejeitados lá, e no Claude Opus 5.5 e no Claude Sonnet 5.5 um tool_choice forçado de any ou tool retorna um 400 dentro de um batch exatamente como faria em uma chamada normal. Use tool_choice: auto com strict: true em vez disso.

Se você opera infraestrutura multi-provedor, o mesmo padrão existe em outros lugares: veja a OpenAI Batch API e o modo batch da Gemini API. As formas diferem, a economia não.

É um endpoint assíncrono que executa requisições padrão da Messages API em massa a 50% dos preços normais de tokens. Você envia uma lista de requisições com seus próprios IDs, faz polling até o batch terminar e lê os resultados em até 29 dias.

Metade da tarifa padrão tanto na entrada quanto na saída. No Claude Sonnet 5.5 isso é $1.00 por milhão de tokens de entrada e $5.00 por milhão de tokens de saída, contra $2.00 e $10.00 de forma síncrona.

A maioria dos batches termina em até uma hora. O máximo é 24 horas, após o que qualquer requisição não processada retorna um resultado expired e você a reenvia.

Sim, e os descontos se acumulam. Marque um prefixo compartilhado com cache_control, repita esse prefixo idêntico em cada requisição, e leituras em cache são cobradas a uma fração do preço de entrada além do desconto de batch.

Apenas aquela requisição falha. Seu resultado carrega type: "errored" com um objeto de erro; todo o resto ainda tem sucesso. Erros de validação precisam de um payload corrigido, erros de servidor são seguros de repetir sem alterações.

Sim. client.messages.batches.cancel(batch_id) move o batch para canceling. Requisições já finalizadas mantêm seus resultados; o resto volta como canceled.

Sim. Todos os recursos da Messages API funcionam dentro de um batch, incluindo visão, definições de ferramentas e system prompts. As exceções são modo rápido, fallbacks do lado do servidor e escolha forçada de ferramenta nos modelos 5.5.

O processamento em batch é a segunda maior economia gratuita na Claude API, depois do prompt caching, e não custa nada em qualidade: mesmos modelos, mesmos recursos, metade do preço, pago em latência que você provavelmente não estava usando. Indexe seus resultados por custom_id, faça cache do prefixo compartilhado e trate expired como uma retentativa em vez de uma falha.

Teste o ciclo de vida antes de escalá-lo. Instale o Apidog CLI, aponte seu agente de codificação para os endpoints de batch e mantenha o caso de teste gerado rodando em CI para que uma mudança de schema nunca te surpreenda com 100.000 requisições. O plano gratuito cobre 4 usuários, e você pode baixar o Apidog e ter o primeiro caso rodando em alguns minutos.

Originaltitel: API em Lote do Claude: Execute Tarefas Assíncronas pela Metade do CustoQuelle: dev.to (dev.to). Original öffnen