# Primeiros passos (/docs/conta-digital/getting-started)

<QuickLinks>
  <QuickLink href="/docs/conta-digital/endpoints/authentication/post_oauth_token" title="Obter token de acesso" method="POST" path="/oauth/token" />

  <QuickLink href="/docs/conta-digital/endpoints/webhooks/post_webhook" title="Cadastrar endpoint de webhook" method="POST" path="/transactions/webhooks" />

  <QuickLink href="/docs/conta-digital/endpoints/charges/post_payment" title="Criar cobrança Pix" method="POST" path="/transactions/payment" />
</QuickLinks>

<Mermaid
  chart="`
flowchart LR
  A[&#x22;Credencial no painel&#x22;] --> B[&#x22;Token&#x22;]
  B --> C[&#x22;Cadastro do webhook&#x22;]
  C --> D[&#x22;Cobrança&#x22;]
  D --> E[&#x22;Webhook PAYMENT_PAID&#x22;]

  click A &#x22;https://hub.payzu.com.br&#x22; &#x22;Painel&#x22;
  click B &#x22;/docs/conta-digital/endpoints/authentication/post_oauth_token&#x22; &#x22;Obter token de acesso&#x22;
  click C &#x22;/docs/conta-digital/endpoints/webhooks/post_webhook&#x22; &#x22;Cadastrar endpoint de webhook&#x22;
  click D &#x22;/docs/conta-digital/endpoints/charges/post_payment&#x22; &#x22;Criar cobrança Pix&#x22;
  click E &#x22;/docs/conta-digital/webhooks&#x22; &#x22;Webhooks&#x22;

  style A fill:#f59e0b,stroke:#d97706,color:#ffffff
  style E fill:#14ce71,stroke:#0eb464,color:#ffffff
`"
/>

<Callout type="warn">
  As chamadas deste guia vão para produção: a cobrança criada aqui é real.
</Callout>

<Steps>
  <Step>
    ### Criar a credencial [#criar-a-credencial]

    No painel da Conta Digital, em [hub.payzu.com.br](https://hub.payzu.com.br), abra a área de credenciais e crie uma com os escopos que a integração usa. A criação pede o PIN de operação do titular.

    Para este guia, marque `PAYMENT_WRITE`, `PAYMENT_READ` e `WEBHOOK_WRITE`. O que cada escopo libera está em [Escopos](/docs/conta-digital/authentication#escopos).

    A tela mostra o `client_id`, o `client_secret` e o token da credencial (`pzu_…`).

    <Callout type="warn">
      O `client_secret` aparece uma vez só. Guarde-o antes de sair da tela.
    </Callout>
  </Step>

  <Step>
    ### Trocar a credencial por um token [#trocar-a-credencial-por-um-token]

    Mande o `client_id` e o `client_secret` para [`POST /oauth/token`](/docs/conta-digital/endpoints/authentication/post_oauth_token). O token devolvido vale 15 minutos.

    <Tabs items="['curl', 'Node.js']">
      <Tab value="curl">
        ```bash
        curl -X POST https://api.hub.payzu.com.br/api/v1/oauth/token \
          -u "$PAYZU_CLIENT_ID:$PAYZU_CLIENT_SECRET" \
          -d 'grant_type=client_credentials'
        ```
      </Tab>

      <Tab value="Node.js">
        ```ts
        const credentials = Buffer.from(`${process.env.PAYZU_CLIENT_ID}:${process.env.PAYZU_CLIENT_SECRET}`).toString('base64');

        const response = await fetch('https://api.hub.payzu.com.br/api/v1/oauth/token', {
          method: 'POST',
          headers: {
            Authorization: `Basic ${credentials}`,
            'Content-Type': 'application/x-www-form-urlencoded',
          },
          body: 'grant_type=client_credentials',
        });

        const { access_token, expires_in } = await response.json();
        ```
      </Tab>
    </Tabs>

    ```json
    {
      "access_token": "eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIn0..mQ3Zy1hbVhpbXBsZQ.ZXhlbXBsbw.c2lnbmF0dXJl",
      "token_type": "Bearer",
      "expires_in": 900,
      "scope": "PAYMENT_WRITE PAYMENT_READ WEBHOOK_WRITE"
    }
    ```

    Mande o `access_token` em `Authorization: Bearer` nas outras chamadas. Nos exemplos a seguir, ele está em `$PAYZU_TOKEN`. Quando o token vence, a API responde `401` com `TOKEN_INVALID`: peça outro na mesma rota.
  </Step>

  <Step>
    ### Cadastrar o webhook [#cadastrar-o-webhook]

    Cadastre a URL do seu servidor que vai receber os webhooks, com [`POST /transactions/webhooks`](/docs/conta-digital/endpoints/webhooks/post_webhook) (escopo `WEBHOOK_WRITE`). A URL precisa ser HTTPS e pública.

    <Tabs items="['curl', 'Node.js']">
      <Tab value="curl">
        ```bash
        curl -X POST https://api.hub.payzu.com.br/api/v1/transactions/webhooks \
          -H "Authorization: Bearer $PAYZU_TOKEN" \
          -H "Content-Type: application/json" \
          -d '{
            "url": "https://sualoja.com.br/webhooks/payzu",
            "events": ["PAYMENT_PAID", "PAYMENT_EXPIRED"]
          }'
        ```
      </Tab>

      <Tab value="Node.js">
        ```ts
        const res = await fetch('https://api.hub.payzu.com.br/api/v1/transactions/webhooks', {
          method: 'POST',
          headers: {
            Authorization: `Bearer ${process.env.PAYZU_TOKEN}`,
            'Content-Type': 'application/json',
          },
          body: JSON.stringify({
            url: 'https://sualoja.com.br/webhooks/payzu',
            events: ['PAYMENT_PAID', 'PAYMENT_EXPIRED'],
          }),
        });
        const { id, secret } = await res.json();
        ```
      </Tab>
    </Tabs>

    A resposta `201` traz o `secret` que assina cada webhook. Ele só aparece nessa resposta: guarde-o. O cadastro também pode ser feito no painel.

    Se vier `403` com `TOKEN_MISSING_SCOPE`, falta um escopo na credencial; o nome dele vem em `details.scope`.
  </Step>

  <Step>
    ### Criar a cobrança [#criar-a-cobrança]

    Crie uma cobrança com [`POST /transactions/payment`](/docs/conta-digital/endpoints/charges/post_payment) (escopo `PAYMENT_WRITE`). O valor vai em centavos: `1500` é R$ 15,00.

    <Tabs items="['curl', 'Node.js']">
      <Tab value="curl">
        ```bash
        curl -X POST https://api.hub.payzu.com.br/api/v1/transactions/payment \
          -H "Authorization: Bearer $PAYZU_TOKEN" \
          -H "Content-Type: application/json" \
          -d '{
            "amount": 1500,
            "method": "PIX",
            "description": "Pedido 4821",
            "externalRef": "pedido-4821",
            "metadata": { "pedido": "4821", "canal": "checkout-web" },
            "customer": { "name": "Maria Souza", "document": "52998224725" }
          }'
        ```
      </Tab>

      <Tab value="Node.js">
        ```ts
        const res = await fetch('https://api.hub.payzu.com.br/api/v1/transactions/payment', {
          method: 'POST',
          headers: {
            Authorization: `Bearer ${process.env.PAYZU_TOKEN}`,
            'Content-Type': 'application/json',
          },
          body: JSON.stringify({
            amount: 1500,
            method: 'PIX',
            description: 'Pedido 4821',
            externalRef: 'pedido-4821',
            metadata: { pedido: '4821', canal: 'checkout-web' },
            customer: { name: 'Maria Souza', document: '52998224725' },
          }),
        });
        const cobranca = await res.json();
        ```
      </Tab>
    </Tabs>

    A resposta `201` traz a cobrança com `status: "PENDING"` e o Pix copia e cola em `pix.qrCodeText`. Mostre-o ao cliente e gere o QR Code a partir dele. Repetir a chamada com o mesmo `externalRef` devolve a mesma cobrança (`200`), sem criar outra.
  </Step>

  <Step>
    ### Receber o `PAYMENT_PAID` [#receber-o-payment_paid]

    Quando o cliente paga, o seu servidor recebe o `PAYMENT_PAID`:

    ```http
    POST /webhooks/payzu
    Content-Type: application/json
    X-Payzu-Event: PAYMENT_PAID
    X-Payzu-Delivery: cmu1r7x2k000a01s6h4f2b9qd
    X-Payzu-Timestamp: 1791210790441
    X-Payzu-Signature: sha256=8f3b2c1d...

    {
      "event": "PAYMENT_PAID",
      "id": "cmu1r7x2k000a01s6h4f2b9qd",
      "sentAt": "2026-10-05T14:33:10.441Z",
      "accountId": "cmu0z8k2a000001s6acct0001",
      "data": {
        "paymentId": "cmu2wbljx0000e8gtlic8q1gi",
        "status": "PAID",
        "amount": 1500,
        "serviceFee": 105,
        "netAmount": 1395,
        "metadata": { "pedido": "4821", "canal": "checkout-web" },
        "externalRef": "pedido-4821",
        "endToEndId": "E99999999202610051433a1b2c3d4e5f"
      }
    }
    ```

    Confira a assinatura com o `secret` do cadastro do webhook, como em [Webhooks](/docs/conta-digital/webhooks#assinatura), e responda com qualquer `2xx` em até 10 segundos. Libere o pedido aqui, no `PAYMENT_PAID`: o `externalRef` e o `metadata` da criação voltam em `data`.
  </Step>
</Steps>

## Consultar sem esperar o webhook [#consultar-sem-esperar-o-webhook]

Consulte a cobrança em [`GET /transactions/payment/{paymentId}`](/docs/conta-digital/endpoints/charges/get_payment) (escopo `PAYMENT_READ`), com o `id` da resposta de criação ou o `paymentId` do webhook:

<Tabs items="['curl', 'Node.js']">
  <Tab value="curl">
    ```bash
    curl https://api.hub.payzu.com.br/api/v1/transactions/payment/hubp-20261005K7Q2M9XB4T127431 \
      -H "Authorization: Bearer $PAYZU_TOKEN"
    ```
  </Tab>

  <Tab value="Node.js">
    ```ts
    const res = await fetch('https://api.hub.payzu.com.br/api/v1/transactions/payment/hubp-20261005K7Q2M9XB4T127431', {
      headers: {
        Authorization: `Bearer ${process.env.PAYZU_TOKEN}`,
      },
    });
    const cobranca = await res.json();
    ```
  </Tab>
</Tabs>

Para achar a cobrança de um pedido, use [Listar cobranças](/docs/conta-digital/endpoints/charges/get_payments) com `?externalRef=`.

## Próximos passos [#próximos-passos]

<QuickLinks>
  <QuickLink href="/docs/conta-digital/charges" title="Cobranças Pix" />

  <QuickLink href="/docs/conta-digital/webhooks" title="Webhooks" />

  <QuickLink href="/docs/conta-digital/withdrawals" title="Saques Pix" />

  <QuickLink href="/docs/conta-digital/error-codes" title="Códigos de erro" />
</QuickLinks>