Referência da API

Cancelar uma fatura

POST/v1/invoices/{id}/cancel

Contrato v1 / 1.0.0 62 / 2026-10-10

Nesta página

Cancele uma fatura aberta sem a eliminar. Continua disponível para reconciliação. Um estado fechado incompatível devolve 409.

Permissões da chave: invoices / write / payments.

Parâmetros

ParâmetroEntradaObrigatórioDescrição
idpathSimID opaco do recurso.
string minLength: 1

Exemplos de pedidos

Os exemplos executam uma operação real na conta. Defina as variáveis de ambiente indicadas no código. Mantenha a chave privada; pedidos de escrita não são repetidos automaticamente.

Shell / cURL
#!/usr/bin/env bash
set -euo pipefail
: "${CRYPTANIO_RESOURCE_ID:?Set CRYPTANIO_RESOURCE_ID}"
: "${CRYPTANIO_API_KEY:?Set CRYPTANIO_API_KEY}"
urlencode() {
  local LC_ALL=C text="$1" char index
  for ((index=0; index<${#text}; index++)); do
    char="${text:index:1}"
    case "$char" in [a-zA-Z0-9.~_-]) printf '%s' "$char" ;; *) printf '%%%02X' "'$char" ;; esac
  done
}
response_file="$(mktemp)"
trap 'rm -f "$response_file"' EXIT
transfer_status=0
http_status="$(curl \
  --silent --show-error --max-time 30 --request POST \
  --header "Authorization: Bearer $CRYPTANIO_API_KEY" \
  --header 'Accept: application/json' \
  "https://api.cryptanio.com/v1/invoices/$(urlencode "$CRYPTANIO_RESOURCE_ID")/cancel" \
  --output "$response_file" --write-out '%{http_code}')" || transfer_status=$?
if [[ "$http_status" == 2?? ]]; then
  cat "$response_file"
  exit "$transfer_status"
fi
printf 'HTTP %s\n' "$http_status" >&2
cat "$response_file" >&2
exit 1
Transferir exemplo
Go
// Go; standard library only. Run: go run request.go
package main

import (
    "fmt"
    "io"
    "net/http"
    "net/url"
    "os"
    "strings"
    "time"
)

func env(name string) string {
    value := os.Getenv(name)
    if value == "" { fmt.Fprintln(os.Stderr, "Set", name); os.Exit(1) }
    return value
}
func run() error {
    path := "/v1/invoices/{id}/cancel"
    path = strings.ReplaceAll(path, "{id}", url.PathEscape(env("CRYPTANIO_RESOURCE_ID")))
    endpoint, err := url.Parse("https://api.cryptanio.com" + path)
    if err != nil { return err }
    query := endpoint.Query()

    endpoint.RawQuery = query.Encode()

    request, err := http.NewRequest("POST", endpoint.String(), nil)
    if err != nil { return err }
    request.Header.Set("Authorization", "Bearer " + env("CRYPTANIO_API_KEY"))
    request.Header.Set("Accept", "application/json")
    client := &http.Client{Timeout: 30 * time.Second, CheckRedirect: func(*http.Request, []*http.Request) error { return http.ErrUseLastResponse }}
    response, err := client.Do(request)
    if err != nil { return err }
    defer response.Body.Close()
    if response.StatusCode < 200 || response.StatusCode >= 300 {
        body, err := io.ReadAll(response.Body)
        if err != nil { return err }
        return fmt.Errorf("HTTP %d: %s", response.StatusCode, body)
    }
    _, err = io.Copy(os.Stdout, response.Body)
    return err
}
func main() {
    if err := run(); err != nil { fmt.Fprintln(os.Stderr, err); os.Exit(1) }
}
Transferir exemplo
Rust
// Cargo.toml dependencies:
// reqwest = { version = "=0.12.24", features = ["blocking", "json"] }
// serde_json = "=1.0.145"
use std::{error::Error, io, time::Duration};
use reqwest::{blocking::Client, redirect::Policy, Method, Url};

fn env(name: &str) -> Result<String, Box<dyn Error>> {
    let value = std::env::var(name)?;
    if value.is_empty() { return Err(format!("Set {name}").into()); }
    Ok(value)
}
fn run() -> Result<(), Box<dyn Error>> {
    let mut url = Url::parse("https://api.cryptanio.com")?;
    {
        let mut segments = url.path_segments_mut().map_err(|_| "Invalid base URL")?;
        segments.clear();
        segments.push("v1");
        segments.push("invoices");
        segments.push(&env("CRYPTANIO_RESOURCE_ID")?);
        segments.push("cancel");
    }
    let client = Client::builder().timeout(Duration::from_secs(30)).redirect(Policy::none()).build()?;
    let request = client.request(Method::POST, url)
        .header("Authorization", format!("Bearer {}", env("CRYPTANIO_API_KEY")?))
        .header("Accept", "application/json".to_owned());
    let mut response = request.send()?;
    let status = response.status();
    if !status.is_success() { return Err(format!("HTTP {}: {}", status.as_u16(), response.text()?).into()); }
    io::copy(&mut response, &mut io::stdout())?;
    Ok(())
}
fn main() {
    if let Err(error) = run() { eprintln!("{error}"); std::process::exit(1); }
}
Transferir exemplo
PHP
<?php
// PHP 8 with the cURL extension. Run this on your server.
function env(string $name): string {
    $value = getenv($name);
    if ($value === false || $value === '') throw new RuntimeException('Set ' . $name);
    return $value;
}
try {
    $path = '/v1/invoices/{id}/cancel';
    $path = str_replace('{id}', rawurlencode(env('CRYPTANIO_RESOURCE_ID')), $path);
    $query = [

    ];
    $url = 'https://api.cryptanio.com' . $path . ($query ? '?' . http_build_query($query, '', '&', PHP_QUERY_RFC3986) : '');
    $headers = [
        'Authorization: ' . 'Bearer ' . env('CRYPTANIO_API_KEY'),
        'Accept: ' . 'application/json',
    ];
    $curl = curl_init($url);
    curl_setopt_array($curl, [
        CURLOPT_CUSTOMREQUEST => 'POST',
        CURLOPT_HTTPHEADER => $headers,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_FOLLOWLOCATION => false,
        CURLOPT_CONNECTTIMEOUT => 10,
        CURLOPT_TIMEOUT => 30,
    ]);
    $response = curl_exec($curl);
    if ($response === false) throw new RuntimeException(curl_error($curl));
    $status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
    if ($status < 200 || $status >= 300) throw new RuntimeException('HTTP ' . $status . ': ' . $response);
    echo $response;
} catch (Throwable $error) {
    fwrite(STDERR, $error->getMessage() . PHP_EOL);
    exit(1);
}
Transferir exemplo
Python
# Python 3; standard library only.
import json
import os
import sys
from urllib.error import HTTPError, URLError
from urllib.parse import quote, urlencode
from urllib.request import HTTPRedirectHandler, Request, build_opener

def env(name):
    result = os.environ.get(name)
    if not result:
        raise ValueError("Set " + name)
    return result

class NoRedirect(HTTPRedirectHandler):
    def redirect_request(self, req, fp, code, msg, headers, newurl):
        return None

try:
    path = "/v1/invoices/{id}/cancel"
    path = path.replace("{id}", quote(env("CRYPTANIO_RESOURCE_ID"), safe=""))
    query = {

    }
    url = "https://api.cryptanio.com" + path + ("?" + urlencode(query) if query else "")
    headers = {
        "Authorization": "Bearer " + env("CRYPTANIO_API_KEY"),
        "Accept": "application/json",
    }
    data = None
    request = Request(url, data=data, headers=headers, method="POST")
    with build_opener(NoRedirect()).open(request, timeout=30) as response:
        if not 200 <= response.status < 300:
            raise ValueError("HTTP " + str(response.status))
        sys.stdout.buffer.write(response.read())
except HTTPError as error:
    print("HTTP " + str(error.code) + ": " + error.read().decode("utf-8", errors="replace"), file=sys.stderr)
    sys.exit(1)
except (ValueError, URLError, OSError) as error:
    print(str(error), file=sys.stderr)
    sys.exit(1)
Transferir exemplo
Node.js
// Node.js 18+. Run on your server, never in a browser.
const env = name => {
  const result = process.env[name];
  if (!result) throw new Error(`Set ${name}`);
  return result;
};
try {
  let path = "/v1/invoices/{id}/cancel";
  path = path.replace("{id}", encodeURIComponent(env("CRYPTANIO_RESOURCE_ID")));
  const url = new URL(path, "https://api.cryptanio.com");

  const headers = {
    "Authorization": "Bearer " + env("CRYPTANIO_API_KEY"),
    "Accept": "application/json",
  };
  const response = await fetch(url, {
    method: "POST", headers, redirect: "manual",
    signal: AbortSignal.timeout(30_000),
  });
  if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
  if (response.body) {
    for await (const chunk of response.body) process.stdout.write(chunk);
  }
} catch (error) {
  console.error(error.message);
  process.exitCode = 1;
}
Transferir exemplo

Respostas e erros

200 Resposta bem-sucedida.
CampoTipoObrigatórioDescrição
checkout_urlstringNãoPágina de pagamento hospedada pelo Cryptanio. A criação ou repetição de uma fatura com escolha de método devolve um link de acesso interativo que permite a escolha até que um pagamento seja detectado. A criação com método fixo e todos os GET e listagens devolvem um link separado somente de leitura. Compartilhe ambos apenas com o pagador pretendido; nenhum concede acesso à conta ou à chave API. Confirme o pagamento pela API de faturas ou por um webhook verificado, não por um redirecionamento do navegador.
uri
idstringSimIdentificador opaco; mantenha-o como cadeia.
minLength: 1
statusstringSimpending aguarda pagamento; seen detetado; partial parcialmente pago; paid liquidado; underpaid/overpaid/late exigem decisão; expired prazo terminado; canceled anulado.
pending, seen, paid, underpaid, partial, overpaid, expired, late, canceled
project_idstringSimIdentificador opaco; mantenha-o como cadeia.
minLength: 1
referencestringNãoReferência da encomenda.
customerobjectNão
productobjectNão
payerobjectNão
metadataobjectNãoAté 20 pares, no máximo 8192 bytes JSON. Não inclua segredos.
invoice_currencystringNãoMoeda da cotação da encomenda.
invoice_amountstringNãoMontante decimal exato como cadeia; não use vírgula flutuante.
pattern: ^[0-9]+(?:\.[0-9]+)?$
chainstringSimCódigo da rede.
assetstringSimAtivo do pagamento.
addressstringSimEndereço de pagamento.
payment_routeobjectNãoIdentificador obrigatório do pagamento na blockchain quando uma fonte automática emite um tag, memo, comentário TON ou referência Solana Pay. Guarde-o com o endereço de recebimento; a referência do pedido do comerciante é um campo separado.
payment_uristringNãoPedido de transferência Solana Pay com o destinatário, valor exato, mint do token suportado e referência obrigatória. Codifique este URI no QR de pagamento em vez do endereço de recebimento simples.
uri
amountstring | stringSimValor real que o comprador deve enviar; pode diferir do solicitado para distinguir faturas. Vazio até a escolha de um método.
amount_rawstring | stringSimValor inteiro na menor unidade, como texto. Vazio até a escolha de um método.
askedstring | stringSimValor em criptomoeda solicitado originalmente. Vazio até a escolha de um método.
decimalsintegerSimCasas decimais do ativo.
minimum: 0
tolerancestringNãoTolerância em unidades mínimas; diferente de request.tolerance.
pattern: ^[0-9]+$
sandboxbooleanSimUma fatura de teste não comprova um pagamento real na blockchain.
needs_decisionbooleanNãoÉ necessária uma decisão para underpaid, overpaid ou late.
paidstringNãoMontante recebido em unidades mínimas.
pattern: ^[0-9]+$
tx_idstringNãoIdentificador da transação de pagamento.
paid_atstringNãoData e hora UTC em RFC 3339.
date-time
expires_atstringSimData e hora UTC em RFC 3339.
date-time
created_atstringSimData e hora UTC em RFC 3339.
date-time
200 application/json
{
  "id": "2100",
  "status": "pending",
  "project_id": "2002",
  "reference": "order-42",
  "chain": "ethereum",
  "asset": "USDC",
  "address": "0x52908400098527886E0F7030069857D2E4169EE7",
  "amount": "12.5",
  "amount_raw": "12500000",
  "asked": "12.5",
  "decimals": 6,
  "sandbox": true,
  "expires_at": "2026-10-06T11:00:00Z",
  "created_at": "2026-10-06T10:00:00Z"
}
400 Pedido inválido (bad_request, unsupported_asset).
CampoTipoObrigatórioDescrição
errorobjectSim
400 application/json
{
  "error": {
    "code": "forbidden",
    "message": "this API key is read-only"
  }
}
401 Nenhuma chave API ativa válida (unauthorized).
CampoTipoObrigatórioDescrição
errorobjectSim
401 application/json
{
  "error": {
    "code": "forbidden",
    "message": "this API key is read-only"
  }
}
403 Chave não permite operação, projeto, serviço ou IP; email não confirmado.
CampoTipoObrigatórioDescrição
errorobjectSim
403 application/json
{
  "error": {
    "code": "forbidden",
    "message": "this API key is read-only"
  }
}
404 Objeto não encontrado no âmbito da chave (not_found).
CampoTipoObrigatórioDescrição
errorobjectSim
404 application/json
{
  "error": {
    "code": "forbidden",
    "message": "this API key is read-only"
  }
}
409 Conflito de estado, parâmetros de repetição incompatíveis ou limite de recursos de pagamento (conflict, limit_reached, service_inactive).
CampoTipoObrigatórioDescrição
errorobjectSim
409 application/json
{
  "error": {
    "code": "forbidden",
    "message": "this API key is read-only"
  }
}
429 Demasiados pedidos (rate_limited); repita após Retry-After.
CampoTipoObrigatórioDescrição
errorobjectSim
429 application/json
{
  "error": {
    "code": "forbidden",
    "message": "this API key is read-only"
  }
}
500 Erro interno (internal).
CampoTipoObrigatórioDescrição
errorobjectSim
500 application/json
{
  "error": {
    "code": "forbidden",
    "message": "this API key is read-only"
  }
}
503 Indisponibilidade temporária (unavailable); repita com espera progressiva.
CampoTipoObrigatórioDescrição
errorobjectSim
503 application/json
{
  "error": {
    "code": "forbidden",
    "message": "this API key is read-only"
  }
}

Tratar erros e repetir com segurança

Objetos aninhados

Invoice

CampoTipoObrigatórioDescrição
checkout_urlstringNãoPágina de pagamento hospedada pelo Cryptanio. A criação ou repetição de uma fatura com escolha de método devolve um link de acesso interativo que permite a escolha até que um pagamento seja detectado. A criação com método fixo e todos os GET e listagens devolvem um link separado somente de leitura. Compartilhe ambos apenas com o pagador pretendido; nenhum concede acesso à conta ou à chave API. Confirme o pagamento pela API de faturas ou por um webhook verificado, não por um redirecionamento do navegador.
uri
idstringSimIdentificador opaco; mantenha-o como cadeia.
minLength: 1
statusstringSimpending aguarda pagamento; seen detetado; partial parcialmente pago; paid liquidado; underpaid/overpaid/late exigem decisão; expired prazo terminado; canceled anulado.
pending, seen, paid, underpaid, partial, overpaid, expired, late, canceled
project_idstringSimIdentificador opaco; mantenha-o como cadeia.
minLength: 1
referencestringNãoReferência da encomenda.
customerobjectNão
productobjectNão
payerobjectNão
metadataobjectNãoAté 20 pares, no máximo 8192 bytes JSON. Não inclua segredos.
invoice_currencystringNãoMoeda da cotação da encomenda.
invoice_amountstringNãoMontante decimal exato como cadeia; não use vírgula flutuante.
pattern: ^[0-9]+(?:\.[0-9]+)?$
chainstringSimCódigo da rede.
assetstringSimAtivo do pagamento.
addressstringSimEndereço de pagamento.
payment_routeobjectNãoIdentificador obrigatório do pagamento na blockchain quando uma fonte automática emite um tag, memo, comentário TON ou referência Solana Pay. Guarde-o com o endereço de recebimento; a referência do pedido do comerciante é um campo separado.
payment_uristringNãoPedido de transferência Solana Pay com o destinatário, valor exato, mint do token suportado e referência obrigatória. Codifique este URI no QR de pagamento em vez do endereço de recebimento simples.
uri
amountstring | stringSimValor real que o comprador deve enviar; pode diferir do solicitado para distinguir faturas. Vazio até a escolha de um método.
amount_rawstring | stringSimValor inteiro na menor unidade, como texto. Vazio até a escolha de um método.
askedstring | stringSimValor em criptomoeda solicitado originalmente. Vazio até a escolha de um método.
decimalsintegerSimCasas decimais do ativo.
minimum: 0
tolerancestringNãoTolerância em unidades mínimas; diferente de request.tolerance.
pattern: ^[0-9]+$
sandboxbooleanSimUma fatura de teste não comprova um pagamento real na blockchain.
needs_decisionbooleanNãoÉ necessária uma decisão para underpaid, overpaid ou late.
paidstringNãoMontante recebido em unidades mínimas.
pattern: ^[0-9]+$
tx_idstringNãoIdentificador da transação de pagamento.
paid_atstringNãoData e hora UTC em RFC 3339.
date-time
expires_atstringSimData e hora UTC em RFC 3339.
date-time
created_atstringSimData e hora UTC em RFC 3339.
date-time
ID

Identificador opaco. Formato não garantido; não converta em número.

string Identificador opaco. Formato não garantido; não converta em número.

InvoiceStatus

pending aguarda pagamento; seen detetado; partial parcialmente pago; paid liquidado; underpaid/overpaid/late exigem decisão; expired prazo terminado; canceled anulado.

string pending aguarda pagamento; seen detetado; partial parcialmente pago; paid liquidado; underpaid/overpaid/late exigem decisão; expired prazo terminado; canceled anulado.

Customer

CampoTipoObrigatórioDescrição
idstringSimIdentificador do cliente no seu sistema.
maxLength: 120
Product

CampoTipoObrigatórioDescrição
idstringNãoIdentificador do produto no seu sistema.
maxLength: 120
namestringNãoNome do produto.
maxLength: 200
quantityintegerNãoQuantidade.
minimum: 1; maximum: 1000000
Payer

CampoTipoObrigatórioDescrição
commentstringSimComentário do pagador.
maxLength: 500
InvoiceMetadata

Até 20 pares, no máximo 8192 bytes JSON. Não inclua segredos.

object Até 20 pares, no máximo 8192 bytes JSON. Não inclua segredos.

Decimal

string

RawAmount

string

Error

CampoTipoObrigatórioDescrição
errorobjectSim