> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dodopayments.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Digital Product Delivery

> Antarkan file yang dapat diunduh, tautan eksternal, dan instruksi pengunduhan secara otomatis ketika pelanggan membeli. Pengiriman Produk Digital adalah jenis hak **File Digital**. File diberikan dengan URL unduhan yang presigned pada setiap pemberian dan dicabut ketika akses ditarik.

## Overview

Pengiriman Produk Digital adalah jenis hak **File Digital**. Anda unggah file Anda sekali ke hak File Digital, lampirkan hak tersebut ke produk, dan Dodo Payments mengantarkan tautan unduhan presigned ke setiap pelanggan yang membayar melalui email dan portal pelanggan.

Hak mendukung:

* **Unggahan file yang di-hosted**: menyimpan file di Dodo Payments dan melayani mereka melalui URL presigned jangka pendek.
* **Tautan unduhan eksternal**: tautkan ke file yang di-hosting di Dropbox, Google Drive, S3, atau URL lainnya.
* **Instruksi unduhan**: teks berbentuk bebas yang ditampilkan kepada pelanggan pada halaman pesanan mereka dan dalam email pengiriman.

Anda dapat mencampur ketiganya dalam satu hak.

## Fitur Utama

<CardGroup cols={2}>
  <Card title="File Upload" icon="upload">
    Unggah berkas (PDF, ZIP, gambar, video, dll.) hingga 500 MiB. Berkas dialirkan dan disimpan secara efisien.
  </Card>

  <Card title="Multiple Files" icon="files">
    Lampirkan sebanyak mungkin file yang Anda butuhkan ke satu hak.
  </Card>

  <Card title="External Links" icon="link">
    Sediakan tautan unduhan eksternal (Dropbox, Google Drive, URL S3 yang ditandatangani) sebagai alternatif atau tambahan.
  </Card>

  <Card title="Presigned URLs" icon="lock">
    File yang di-hosting dilayani melalui URL presigned jangka pendek. Setiap URL unduhan habis masa berlakunya secara otomatis setelah sekitar 15 menit.
  </Card>
</CardGroup>

***

## Mengatur Pengiriman Produk Digital

<Steps>
  <Step title="Open Entitlements">
    Buka **Hak** di dasbor Dodo Payments Anda dan klik **+** untuk membuat hak baru.
  </Step>

  <Step title="Choose Digital Files">
    Pilih **Pengiriman Produk Digital** sebagai integrasi.
  </Step>

  <Step title="Add files, links, and instructions">
    Konfigurasikan kombinasi apa pun dari:

    * **File**: unggah satu atau lebih file. Setiap unggahan mengembalikan `file_id` yang ditambahkan ke hak.
    * **URL Eksternal**: tautan HTTPS yang dapat diakses publik yang dikirimkan bersama file yang di-hosting.
    * **Instruksi**: teks berbentuk bebas yang ditampilkan kepada pelanggan (misalnya, "Unzip dan jalankan setup.sh").

    <Frame>
      <img src="https://mintcdn.com/dodopayments/do-W-dMDGVB_xzr_/images/entitlements/digital-files/create.png?fit=max&auto=format&n=do-W-dMDGVB_xzr_&q=85&s=33ad03277809d14585d247442c191462" alt="Digital Files entitlement with file upload, external URL, and instructions fields" style={{ maxHeight: '500px', width: 'auto' }} width="1669" height="989" data-path="images/entitlements/digital-files/create.png" />
    </Frame>
  </Step>

  <Step title="Save the entitlement">
    Simpan. Hak sekarang tersedia untuk dilampirkan ke produk mana pun.
  </Step>
</Steps>

## Melampirkan ke Produk

Buka produk, perluas **Pengaturan Lanjutan → Hak & Kredit**, dan pilih hak File Digital Anda. Hak diberikan pada setiap pembelian sukses atau langganan aktif yang terikat pada produk tersebut.

<Frame caption="Attaching the Digital Files entitlement to a product alongside other entitlements.">
  <img src="https://mintcdn.com/dodopayments/do-W-dMDGVB_xzr_/images/entitlements/attach-to-product.png?fit=max&auto=format&n=do-W-dMDGVB_xzr_&q=85&s=965ad78262791fa8dbb712b4fdf89538" alt="Product entitlements panel showing Digital Product Delivery selected" style={{ maxHeight: '500px', width: 'auto' }} width="2000" height="1197" data-path="images/entitlements/attach-to-product.png" />
</Frame>

***

## Cara Kerja Pengiriman

Pengiriman File Digital mengikuti standar [siklus grant](/features/entitlements/introduction#how-grants-work):

| Peristiwa                                        | Perilaku                                                                                                                                                                                 |
| ------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `payment.succeeded` (satu kali)                  | Menerbitkan basis. Basis membawa URL unduhan presigned yang berlaku selama \~15 menit; pelanggan dapat menyegarkannya dengan membuka kembali tautan email atau halaman portal pelanggan. |
| `subscription.active`                            | Menerbitkan basis. File tetap dapat diakses selama langganan aktif.                                                                                                                      |
| `subscription.renewed`                           | Tidak ada aksi. Basis yang sama berlanjut; URL presigned baru dibuat pada setiap pengambilan.                                                                                            |
| `subscription.on_hold` / `cancelled` / `expired` | Mencabut basis. URL presigned baru tidak lagi diterbitkan.                                                                                                                               |
| `subscription.plan_changed`                      | Mencabut basis lama; menerbitkan basis baru untuk hak rencana baru.                                                                                                                      |
| `refund.succeeded` (satu kali)                   | Mencabut basis.                                                                                                                                                                          |
| Pencabutan manual                                | Mencabut dengan `revocation_reason: manual`.                                                                                                                                             |

<Warning>
  Pencabutan menghentikan Dodo Payments dari penerbitan URL unduhan baru, tetapi tidak membatalkan salinan yang sudah diunduh oleh pelanggan. Perlakukan unduhan file yang di-hosting sebagai "dikirim sekali dibaca."
</Warning>

***

## Pengalaman Pelanggan

### Konfirmasi Pembelian

Setelah transaksi berhasil, pelanggan menerima email dengan tautan unduhan dan instruksi yang Anda konfigurasikan.

<Frame>
  <img src="https://mintcdn.com/dodopayments/mOQO5ej_lx0yH9p-/images/digital-product-delivery/2.png?fit=max&auto=format&n=mOQO5ej_lx0yH9p-&q=85&s=54f5247f6d67fe5bb48736682995e23e" alt="Purchase confirmation email showing download links for digital products" style={{ maxHeight: '500px', width: 'auto' }} width="1920" height="1080" data-path="images/digital-product-delivery/2.png" />
</Frame>

### Akses Portal Pelanggan

Pelanggan dapat mengambil kembali tautan unduhan kapan saja dari [Portal Pelanggan](/features/customer-portal). Halaman portal menghasilkan URL presigned baru sesuai permintaan, sehingga pembelian yang sama terus berfungsi bahkan setelah tautan email kedaluwarsa.

<Frame>
  <img src="https://mintcdn.com/dodopayments/mOQO5ej_lx0yH9p-/images/digital-product-delivery/3.png?fit=max&auto=format&n=mOQO5ej_lx0yH9p-&q=85&s=490c6755474c1f00a93f7adde7dabb63" alt="Customer portal interface showing available digital products for download" style={{ maxHeight: '500px', width: 'auto' }} width="1920" height="1080" data-path="images/digital-product-delivery/3.png" />
</Frame>

<Check>
  Pelanggan dapat mengunduh file langsung dari email konfirmasi atau mengaksesnya kapan saja melalui portal mereka.
</Check>

***

## Mengelola File Secara Program

### Unggah file ke hak

<CodeGroup>
  ```typescript TypeScript theme={null} theme={null}
  import DodoPayments from 'dodopayments';
  import fs from 'node:fs';

  const client = new DodoPayments({
    bearerToken: process.env['DODO_PAYMENTS_API_KEY'],
    environment: 'test_mode',
  });

  await client.entitlements.files.upload('ent_files_abc', {
    file: fs.createReadStream('./pro-bundle.zip'),
    filename: 'pro-bundle.zip',
  });
  ```

  ```bash cURL theme={null} theme={null}
  curl -X POST "https://test.dodopayments.com/entitlements/ent_files_abc/files" \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -F "file=@./pro-bundle.zip" \
    -F "filename=pro-bundle.zip"
  ```
</CodeGroup>

### Daftar basis dan selesaikan URL unduhan

```typescript theme={null} theme={null}
const grants = await client.entitlements.grants.list('ent_files_abc', {
  customer_id: 'cus_abc123',
});

for (const grant of grants.items) {
  for (const file of grant.digital_product_delivery.files) {
    console.log(file.filename, file.download_url, `expires in ${file.expires_in}s`);
  }
}
```

### Hapus file dari hak

```typescript theme={null} theme={null}
await client.entitlements.files.delete('ent_files_abc', 'df_a4f6c1de');
```

***

## Pertimbangan Penting

* **URL presigned cepat habis masa berlakunya.** URL unduhan yang dikembalikan dalam payload basis atau acara webhook berlaku selama \~15 menit. Jangan menyimpannya; ambil kembali ketika pelanggan perlu mengunduh lagi.
* **Memperbarui file hanya memengaruhi pembelian di masa mendatang.** Mengganti atau menghapus file tidak mengubah unduhan yang telah diterbitkan secara retroaktif. Pelanggan di masa lalu masih dapat mengambil versi yang berlaku saat basis mereka dibuat.
* **Pengembalian dana tidak membatalkan salinan yang diunduh.** Pelanggan yang sudah mengunduh file tetap memiliki salinannya. Untuk konten yang dapat dicabut (media dengan batasan lisensi, akses terbatas waktu), gabungkan File Digital dengan [Kunci Lisensi](/features/license-keys) dan validasi saat runtime.
* **Untuk konten sensitif, lebih baik gunakan URL eksternal dengan autentikasi sendiri.** URL presigned Dodo Payments adalah jangka pendek tetapi tidak terautentikasi dalam jendela waktu mereka; siapa pun dengan URL dapat mengunduh dalam jendela tersebut. Konten yang di-hosting secara eksternal dan dibatasi akun memberikan jaminan yang lebih kuat.

***

## Pengelolaan API

<CardGroup cols={2}>
  <Card title="Create Entitlement" icon="plus" href="/api-reference/entitlements/create-entitlement">
    Buat hak akses Berkas Digital dengan URL eksternal opsional dan instruksi.
  </Card>

  <Card title="Upload File" icon="upload" href="/api-reference/entitlements/upload-file">
    Unggah berkas (hingga 500 MiB) dan tambahkan ke hak akses.
  </Card>

  <Card title="Delete File" icon="trash" href="/api-reference/entitlements/delete-file">
    Hapus berkas dari hak akses.
  </Card>

  <Card title="List Grants" icon="users" href="/api-reference/entitlements/list-grants">
    Daftar pemberian hak dan baca URL unduhan yang teratasi.
  </Card>

  <Card title="Update Entitlement" icon="pen" href="/api-reference/entitlements/update-entitlement">
    Perbarui instruksi, URL eksternal, atau ganti berkas.
  </Card>

  <Card title="Revoke Grant" icon="ban" href="/api-reference/entitlements/revoke-grant">
    Cabut akses pelanggan secara manual.
  </Card>
</CardGroup>

***

## Webhook

Pengiriman file digital dan pencabutan memicu empat [acara webhook `entitlement_grant.*`](/developer-resources/webhooks/intents/entitlement-grant). Untuk grant File Digital, payload mencakup objek `digital_product_delivery` dengan daftar file yang diselesaikan (URL presigned, nama file, ukuran), `instructions` opsional, dan `external_url` opsional.

```json theme={null} theme={null}
"digital_product_delivery": {
  "files": [
    {
      "file_id": "df_a4f6c1de",
      "download_url": "https://files.dodopayments.com/.../pro-bundle.zip?Signature=...",
      "filename": "pro-bundle.zip",
      "content_type": "application/zip",
      "file_size": 18742390,
      "expires_in": 900
    }
  ],
  "instructions": "Unzip and run setup.sh from the project root.",
  "external_url": null
}
```

***

## Pengiriman Produk Digital Lama

<Note>
  Produk yang dikonfigurasi dengan blok `digital_product_delivery` lama di produk itu sendiri telah **secara otomatis dimigrasikan** ke hak File Digital. File yang ada diunggah di bawah API file produk lama dipertahankan; mereka terus dapat diunduh dan muncul dalam payload basis yang ditandai dengan `source: "legacy"`. Pembaruan di masa mendatang (menambahkan file, mengubah instruksi, mengganti URL eksternal) harus dilakukan dengan mengedit hak File Digital yang sudah dimigrasikan di bawah **Hak**.

  Bidang level produk lama (`digital_product_delivery.external_url`, `digital_product_delivery.instructions`) terus terisi pada respons produk untuk kompatibilitas mundur, tetapi hak adalah sumber kebenaran ke depan.
</Note>

***

## Praktik Terbaik

* **Anggap unduhan sebagai satu kali.** Pelanggan akan berbagi atau kehilangan tautan, jadi desain produk Anda dengan asumsi bahwa apa pun yang mereka unduh menjadi milik mereka.
* **Gunakan instruksi untuk menetapkan harapan.** Untuk paket multi-berkas, tambahkan baris `instructions` yang menjelaskan apa yang harus diinstal terlebih dahulu atau cara menggabungkan berkas.
* **Perhatikan batas 500 MiB.** Artefak yang lebih besar (dataset multi-GB, kursus video) sebaiknya dihosting secara eksternal dan ditautkan melalui `external_url` daripada diunggah.
* **Gabungkan dengan License Keys untuk akses yang bisa dicabut.** Jika Anda perlu mencabut akses ke fitur dalam produk setelah pengembalian dana, gabungkan hak akses Berkas Digital dengan hak akses License Key dan validasi kunci saat runtime.
* **Uji alur penyegaran portal pelanggan.** Pastikan pelanggan dapat kembali ke portal seminggu kemudian dan masih mendapatkan tautan unduhan yang berfungsi. Ini adalah jalur pemulihan utama ketika tautan email kedaluwarsa.
