Pular para o conteúdo

Integração

API para plataformas

Para marketplaces que vendem créditos certificados pelo RCGI-USP: leia o registro, peça autorização às empresas, reserve, transfira e aposente créditos. O RCGI é o único que fala com a blockchain — a plataforma fala com o RCGI.

Visão geral

  • Base: /api/v1, JSON em UTF-8. Respostas de sucesso vêm em { dados }; de erro, em { erro: { codigo, mensagem } }.
  • Quantidades em kg inteiros (1 crédito = 1 tCO₂e = 1000 kg). As respostas trazem as duas unidades: { kg, toneladas }.
  • Toda chamada fica na trilha de auditoria do RCGI, com a chave que a fez.
  • Escritas na blockchain são assíncronas: o evento nasce pendente e vira confirmado quando entra num bloco. Acompanhe por GET /eventos/{codigo}.

Autenticação e escopos

O admin do RCGI cadastra a plataforma e gera a chave — ela aparece uma vez só. Envie em toda chamada:

Authorization: Bearer rcgi_ab12cd34_…
Escopos da chave de API
EscopoPermite
leituraLer o registro, pedir mandatos, consultar saldos das carteiras que a plataforma opera.
custodia:escritaAbrir carteiras custodiadas, reservar, liquidar, cancelar e aposentar.

Limite: 120 chamadas por minuto por chave. Acima disso, 429 com o header Retry-After.

Idempotência

Toda escrita (POST) exige o header Idempotency-Key — use um UUID por operação. Repetir a mesma chave com o mesmo corpo devolve a resposta original, com o header Idempotent-Replay: true, sem refazer a operação. É o que torna seguro repetir depois de um timeout: a tonelada não é reservada nem aposentada duas vezes.

Fluxo do mandato

A plataforma só opera a carteira de uma empresa depois que a empresa autoriza, logada no RCGI. Sem isso, qualquer um cadastraria o CNPJ de outra empresa e venderia os créditos dela.

  1. 1

    POST /mandatos — com o CNPJ da empresa. Volta um código e o link de autorização.

  2. 2

    A empresa autoriza — no RCGI, pelo link (também recebe por e-mail). A autorização exige código de confirmação.

  3. 3

    GET /mandatos/{codigo} — até o estado virar ativo: aí vem o código da carteira.

  4. 4

    Opere a carteira — saldos, reservas, liquidação e aposentadoria. A empresa pode revogar quando quiser.

Erros

Códigos de erro da API
HTTPCódigoQuando
400jsonO corpo não é JSON válido.
400idempotency_keyEscrita sem o header Idempotency-Key (8 a 200 caracteres).
401nao_autenticadoSem chave, chave inválida ou revogada.
403escopoA chave não tem o escopo que a rota exige.
404nao_encontradoNão existe — ou existe e não é da sua plataforma. As duas respostas são iguais de propósito.
409conflitoO estado não permite a operação (ex.: liquidar reserva vencida).
409saldo_insuficienteDisponível menor que o pedido.
409em_processamentoOutra chamada com a mesma Idempotency-Key ainda está rodando. Repita em instantes.
422invalidoCampos inválidos — o detalhe vem em `erro.campos`.
422idempotency_keyA Idempotency-Key já foi usada com outro corpo ou outra rota.
429limiteMais de 120 chamadas por minuto com a mesma chave.
500internoErro nosso. A Idempotency-Key é liberada: repetir é seguro.

Registro público

O que qualquer pessoa vê nas páginas públicas, em JSON. Só lote confirmado na blockchain aparece.

GET/api/v1/projetos

Listar projetos

Projetos públicos do registro: só os validados pelo RCGI-USP. Em análise, reprovados e cancelados não são públicos.

escopo leitura
status (query)
opcional; só aceita validado (outro valor responde 422)

Requisição

curl -X GET "$RCGI/api/v1/projetos" \
  -H "Authorization: Bearer $RCGI_CHAVE"

Resposta 200

{
  "dados": [
    {
      "codigo": "RCGI-0001",
      "slug": "reflorestamento-fazenda-boa-vista",
      "nome": "Reflorestamento Fazenda Boa Vista",
      "status": "validado",
      "desenvolvedor": "Agro Exemplo S.A.",
      "protocolo": {
        "codigo": "ARR",
        "nome": "Florestamento e reflorestamento",
        "versao": "v1.0",
        "setor": "Soluções baseadas na natureza"
      },
      "bioma": "Cerrado",
      "uf": "MT",
      "municipio": "Sorriso",
      "emitido": {
        "kg": 120000,
        "toneladas": 120
      },
      "aposentado": {
        "kg": 5000,
        "toneladas": 5
      },
      "url": "https://registro.exemplo/projetos/reflorestamento-fazenda-boa-vista"
    }
  ]
}

Erros específicos: nao_autenticado, limite.

GET/api/v1/projetos/{codigo}

Obter projeto

Um projeto pelo código (RCGI-0001) ou slug, com os lotes emitidos.

escopo leitura
codigo (caminho)
Código RCGI-0001 ou slug do projeto

Requisição

curl -X GET "$RCGI/api/v1/projetos/RCGI-0001-2025-01" \
  -H "Authorization: Bearer $RCGI_CHAVE"

Resposta 200

{
  "dados": {
    "codigo": "RCGI-0001",
    "nome": "Reflorestamento Fazenda Boa Vista",
    "status": "validado",
    "lotes": [
      {
        "codigo": "RCGI-0001-2025-01",
        "vintage": 2025,
        "quantidade": {
          "kg": 120000,
          "toneladas": 120
        },
        "aposentado": {
          "kg": 5000,
          "toneladas": 5
        },
        "emitidoEm": "2026-10-02T14:03:11.000Z"
      }
    ]
  }
}

Erros específicos: nao_encontrado.

GET/api/v1/lotes/{codigo}

Obter lote

Um lote emitido: quantidade, faixa de seriais (uma por tonelada), projeto e protocolo.

escopo leitura
codigo (caminho)
Código do lote, ex.: RCGI-0001-2025-01

Requisição

curl -X GET "$RCGI/api/v1/lotes/RCGI-0001-2025-01" \
  -H "Authorization: Bearer $RCGI_CHAVE"

Resposta 200

{
  "dados": {
    "codigo": "RCGI-0001-2025-01",
    "vintage": 2025,
    "quantidade": {
      "kg": 120000,
      "toneladas": 120
    },
    "seriais": {
      "inicio": 1,
      "fim": 120,
      "unidade": "tCO2e"
    },
    "projeto": {
      "codigo": "RCGI-0001",
      "nome": "Reflorestamento Fazenda Boa Vista",
      "desenvolvedor": "Agro Exemplo S.A."
    },
    "protocolo": {
      "nome": "Florestamento e reflorestamento",
      "versao": "v1.0"
    },
    "emitidoEm": "2026-10-02T14:03:11.000Z",
    "url": "https://registro.exemplo/registro/lotes/RCGI-0001-2025-01"
  }
}

Erros específicos: nao_encontrado.

GET/api/v1/lotes/{codigo}/eventos

Cadeia de custódia do lote

Emissões, transferências e aposentadorias do lote, do mais recente ao mais antigo. Carteira custodiada aparece pela plataforma, nunca pelo nome do comprador.

escopo leitura
codigo (caminho)
Código do lote

Requisição

curl -X GET "$RCGI/api/v1/lotes/RCGI-0001-2025-01/eventos" \
  -H "Authorization: Bearer $RCGI_CHAVE"

Resposta 200

{
  "dados": [
    {
      "codigo": "trf_7KX92Q4MPA",
      "tipo": "transferencia",
      "estado": "confirmado",
      "lote": "RCGI-0001-2025-01",
      "quantidade": {
        "kg": 10000,
        "toneladas": 10
      },
      "de": {
        "codigo": "cart_A1B2C3D4E5",
        "nome": "Agro Exemplo S.A."
      },
      "para": {
        "codigo": "cart_F6G7H8J9K2",
        "nome": "Custódia · Lastro"
      },
      "certificado": null,
      "tx": {
        "hash": "0x9f…",
        "bloco": 18420012,
        "url": "https://registro.exemplo/ledger/tx/0x9f…"
      },
      "criadoEm": "2026-10-02T15:00:00.000Z",
      "confirmadoEm": "2026-10-02T15:00:05.000Z"
    }
  ]
}

Erros específicos: nao_encontrado.

GET/api/v1/eventos/{codigo}

Acompanhar um evento

Estado de um evento de custódia (iss_…, trf_…, ret_…). Use para saber quando a transação foi confirmada em bloco.

escopo leitura
codigo (caminho)
Código do evento

Requisição

curl -X GET "$RCGI/api/v1/eventos/RCGI-0001-2025-01" \
  -H "Authorization: Bearer $RCGI_CHAVE"

Resposta 200

{
  "dados": {
    "codigo": "trf_7KX92Q4MPA",
    "tipo": "transferencia",
    "estado": "pendente",
    "lote": "RCGI-0001-2025-01",
    "quantidade": {
      "kg": 10000,
      "toneladas": 10
    },
    "tx": null,
    "confirmadoEm": null
  }
}

Erros específicos: nao_encontrado.

Mandatos e carteiras

Como a plataforma ganha acesso: pede um mandato à empresa e abre carteiras custodiadas para compradores sem conta no RCGI.

POST/api/v1/mandatos

Pedir autorização a uma empresa

Cria um pedido de mandato para a organização dona do CNPJ. A empresa recebe um e-mail e autoriza logada no RCGI, pelo link devolvido. Vale 7 dias.

escopo leituraexige Idempotency-Key

Requisição

curl -X POST "$RCGI/api/v1/mandatos" \
  -H "Authorization: Bearer $RCGI_CHAVE" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"cnpj":"12.345.678/0001-95","escopos":["leitura","custodia:escrita"]}'

Resposta 201

{
  "dados": {
    "codigo": "7KX92Q4MPA3B",
    "estado": "pendente",
    "escopos": [
      "leitura",
      "custodia:escrita"
    ],
    "expiraEm": "2026-10-09T14:00:00.000Z",
    "linkAutorizacao": "https://registro.exemplo/autorizar/7KX92Q4MPA3B"
  }
}

Erros específicos: invalido, nao_encontrado, idempotency_key.

GET/api/v1/mandatos/{codigo}

Estado do mandato

Consulte até virar `ativo`: aí vem o código da carteira que a plataforma passa a operar. Pode virar `recusado`, `revogado` ou `expirado`.

escopo leitura
codigo (caminho)
Código devolvido ao pedir o mandato

Requisição

curl -X GET "$RCGI/api/v1/mandatos/RCGI-0001-2025-01" \
  -H "Authorization: Bearer $RCGI_CHAVE"

Resposta 200

{
  "dados": {
    "codigo": "7KX92Q4MPA3B",
    "estado": "ativo",
    "escopos": [
      "leitura",
      "custodia:escrita"
    ],
    "carteira": "cart_A1B2C3D4E5",
    "expiraEm": "2026-10-09T14:00:00.000Z",
    "decididoEm": "2026-10-02T14:10:00.000Z"
  }
}

Erros específicos: nao_encontrado.

POST/api/v1/carteiras

Abrir carteira custodiada

Carteira de um comprador que não tem conta no RCGI, custodiada pela plataforma. Idempotente por documento: pedir de novo devolve a mesma (200 em vez de 201).

escopo custodia:escritaexige Idempotency-Key

Requisição

curl -X POST "$RCGI/api/v1/carteiras" \
  -H "Authorization: Bearer $RCGI_CHAVE" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"titularDocumento":"98.765.432/0001-10","titularNome":"Comprador Exemplo Ltda."}'

Resposta 201

{
  "dados": {
    "codigo": "cart_F6G7H8J9K2",
    "tipo": "custodiada",
    "titular": "Comprador Exemplo Ltda.",
    "endereco": "0x4b1c…"
  }
}

Erros específicos: invalido, idempotency_key.

GET/api/v1/carteiras/{codigo}/saldos

Saldos de uma carteira

Saldo lote a lote: total, reservado, disponível e a caminho (entrada ainda não confirmada). Só de carteira custodiada pela plataforma ou com mandato ativo.

escopo leitura
codigo (caminho)
Código da carteira

Requisição

curl -X GET "$RCGI/api/v1/carteiras/RCGI-0001-2025-01/saldos" \
  -H "Authorization: Bearer $RCGI_CHAVE"

Resposta 200

{
  "dados": {
    "carteira": {
      "codigo": "cart_A1B2C3D4E5",
      "tipo": "organizacao",
      "titular": "Agro Exemplo S.A."
    },
    "saldos": [
      {
        "lote": "RCGI-0001-2025-01",
        "vintage": 2025,
        "total": {
          "kg": 120000,
          "toneladas": 120
        },
        "reservado": {
          "kg": 10000,
          "toneladas": 10
        },
        "disponivel": {
          "kg": 110000,
          "toneladas": 110
        },
        "aCaminho": {
          "kg": 0,
          "toneladas": 0
        }
      }
    ]
  }
}

Erros específicos: nao_encontrado.

Venda e aposentadoria

O ciclo de uma venda: reservar ao criar o pedido, liquidar quando o pagamento for confirmado, aposentar quando o comprador compensar.

POST/api/v1/reservas

Reservar créditos

Segura créditos de uma carteira enquanto a venda acontece. Sem saldo disponível, 409 saldo_insuficiente. Validade padrão de 7 dias, máximo 30.

escopo custodia:escritaexige Idempotency-Key

Requisição

curl -X POST "$RCGI/api/v1/reservas" \
  -H "Authorization: Bearer $RCGI_CHAVE" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"carteira":"cart_A1B2C3D4E5","lote":"RCGI-0001-2025-01","qtdKg":10000,"referenciaExterna":"pedido-1042","validadeHoras":168}'

Resposta 201

{
  "dados": {
    "codigo": "res_2Q4MPA7KX9",
    "estado": "ativa",
    "carteira": "cart_A1B2C3D4E5",
    "lote": "RCGI-0001-2025-01",
    "quantidade": {
      "kg": 10000,
      "toneladas": 10
    },
    "referenciaExterna": "pedido-1042",
    "expiraEm": "2026-10-09T14:00:00.000Z"
  }
}

Erros específicos: invalido, nao_encontrado, saldo_insuficiente, idempotency_key.

GET/api/v1/reservas/{codigo}

Estado da reserva

Inclui a transferência, depois de liquidada, com o estado da confirmação na blockchain.

escopo leitura
codigo (caminho)
Código da reserva

Requisição

curl -X GET "$RCGI/api/v1/reservas/RCGI-0001-2025-01" \
  -H "Authorization: Bearer $RCGI_CHAVE"

Resposta 200

{
  "dados": {
    "codigo": "res_2Q4MPA7KX9",
    "estado": "liquidada",
    "quantidade": {
      "kg": 10000,
      "toneladas": 10
    },
    "referenciaExterna": "pedido-1042",
    "expiraEm": "2026-10-09T14:00:00.000Z",
    "transferencia": {
      "codigo": "trf_7KX92Q4MPA",
      "estado": "confirmado",
      "txHash": "0x9f…"
    }
  }
}

Erros específicos: nao_encontrado.

POST/api/v1/reservas/{codigo}/liquidar

Liquidar reserva

A venda fechou: transfere os créditos reservados para a carteira do comprador. A transferência nasce pendente e confirma com a blockchain.

escopo custodia:escritaexige Idempotency-Key
codigo (caminho)
Código da reserva

Requisição

curl -X POST "$RCGI/api/v1/reservas/RCGI-0001-2025-01/liquidar" \
  -H "Authorization: Bearer $RCGI_CHAVE" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"carteiraDestino":"cart_F6G7H8J9K2"}'

Resposta 200

{
  "dados": {
    "codigo": "res_2Q4MPA7KX9",
    "estado": "liquidada"
  }
}

Erros específicos: nao_encontrado, conflito, invalido, idempotency_key.

POST/api/v1/reservas/{codigo}/cancelar

Cancelar reserva

Devolve os créditos ao disponível. Cancelar de novo não é erro.

escopo custodia:escritaexige Idempotency-Key
codigo (caminho)
Código da reserva

Requisição

curl -X POST "$RCGI/api/v1/reservas/RCGI-0001-2025-01/cancelar" \
  -H "Authorization: Bearer $RCGI_CHAVE" \
  -H "Idempotency-Key: $(uuidgen)"

Resposta 200

{
  "dados": {
    "codigo": "res_2Q4MPA7KX9",
    "estado": "cancelada"
  }
}

Erros específicos: nao_encontrado, conflito, idempotency_key.

POST/api/v1/aposentadorias

Aposentar créditos

Tira créditos de circulação para sempre, em nome de um beneficiário, e gera o certificado público. O documento do beneficiário entra no hash do certificado, nunca em texto aberto.

escopo custodia:escritaexige Idempotency-Key

Requisição

curl -X POST "$RCGI/api/v1/aposentadorias" \
  -H "Authorization: Bearer $RCGI_CHAVE" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"carteira":"cart_F6G7H8J9K2","lote":"RCGI-0001-2025-01","qtdKg":5000,"beneficiarioNome":"Comprador Exemplo Ltda.","beneficiarioDocumento":"98.765.432/0001-10","motivo":"Compensação das emissões de escopo 1 de 2025","anoCompensado":2025}'

Resposta 201

{
  "dados": {
    "certificado": "RCGI-APO-7KX9-2Q4M",
    "lote": "RCGI-0001-2025-01",
    "quantidade": {
      "kg": 5000,
      "toneladas": 5
    },
    "beneficiario": "Comprador Exemplo Ltda.",
    "anoCompensado": 2025,
    "hashCertificado": "3f9a…",
    "evento": "ret_PA7KX92Q4M",
    "estado": "pendente",
    "urlVerificacao": "https://registro.exemplo/verificar/RCGI-APO-7KX9-2Q4M"
  }
}

Erros específicos: invalido, nao_encontrado, saldo_insuficiente, idempotency_key.

GET/api/v1/aposentadorias/{codigo}

Obter certificado

O certificado de aposentadoria, com o estado da confirmação e o hash.

escopo leitura
codigo (caminho)
Código RCGI-APO-…

Requisição

curl -X GET "$RCGI/api/v1/aposentadorias/RCGI-0001-2025-01" \
  -H "Authorization: Bearer $RCGI_CHAVE"

Resposta 200

{
  "dados": {
    "certificado": "RCGI-APO-7KX9-2Q4M",
    "estado": "confirmado",
    "lote": "RCGI-0001-2025-01",
    "quantidade": {
      "kg": 5000,
      "toneladas": 5
    }
  }
}

Erros específicos: nao_encontrado.

Dúvidas sobre acesso? Fale com o admin do RCGI. Para ver os dados que a API devolve, explore o registro público.