Cara Menggunakan AWS Lambda API untuk Serverless di Tahun 2026

Ashley Innocent

Ashley Innocent

25 March 2026

Cara Menggunakan AWS Lambda API untuk Serverless di Tahun 2026

Apidog untuk Perusahaan

Penerapan On-Premises

SSO & RBAC

Sesuai SOC 2

Jelajahi Apidog Enterprise

TL;DR

API AWS Lambda memungkinkan pengembang untuk menerapkan, mengelola, dan memanggil fungsi tanpa server (serverless) secara terprogram. API ini menggunakan autentikasi IAM, endpoint RESTful untuk pengelolaan fungsi, opsi pemanggilan asinkron dan sinkron, dengan batas konkurensi tingkat akun. Panduan ini mencakup penyiapan autentikasi, deployment fungsi, pola pemanggilan, pemetaan sumber peristiwa, dan strategi arsitektur tanpa server untuk produksi.

Pendahuluan

AWS Lambda memproses triliunan permintaan setiap bulan untuk lebih dari 1 juta pengguna aktif. Bagi pengembang yang membangun aplikasi tanpa server, alat otomatisasi, atau arsitektur berbasis peristiwa, integrasi API Lambda bukan lagi pilihan—ini sangat penting untuk infrastruktur sebagai kode dan pipeline CI/CD.

Inilah kenyataannya: tim yang mengelola 50+ fungsi Lambda secara manual kehilangan 10-15 jam setiap minggu untuk deployment, pembaruan konfigurasi, dan pemantauan. Integrasi API Lambda yang solid mengotomatiskan deployment, mengimplementasikan rilis blue-green, dan memungkinkan penskalaan dinamis berdasarkan permintaan.

Panduan ini akan memandu Anda melalui proses integrasi API AWS Lambda secara lengkap. Anda akan mempelajari autentikasi IAM, pembuatan dan deployment fungsi, pola pemanggilan (sinkron/asinkron), pemetaan sumber peristiwa, arsitektur berlapis, dan strategi deployment produksi. Pada akhirnya, Anda akan memiliki integrasi Lambda yang siap produksi.

tombol

Apa Itu API AWS Lambda?

AWS Lambda menyediakan API RESTful untuk mengelola fungsi komputasi tanpa server. API ini menangani:

Fitur Utama

Fitur Deskripsi
API RESTful Endpoint HTTPS standar
Autentikasi IAM AWS Signature Versi 4
Pemanggilan Asinkron Pemrosesan peristiwa "fire-and-forget"
Pemanggilan Sinkron Pola permintaan-respons
Sumber Peristiwa 200+ integrasi layanan AWS
Layer Kode dan dependensi bersama
Versi/Alias Pergeseran lalu lintas dan rollback
Konkurensi Terprovisi Menghilangkan cold start

Dukungan Runtime Lambda

Runtime Versi Kasus Penggunaan
Node.js 18.x, 20.x Backend API, pemrosesan peristiwa
Python 3.9, 3.10, 3.11 Pemrosesan data, inferensi ML
Java 11, 17, 21 Aplikasi enterprise
Go 1.x API berperforma tinggi
Rust 1.x Fungsi latensi rendah
.NET 6, 8 Beban kerja Windows
Ruby 3.x Aplikasi web
Kustom Apapun Runtime berbasis kontainer

Ikhtisar Arsitektur API

Lambda menggunakan struktur API layanan AWS:

https://lambda.{region}.amazonaws.com/2015-03-31/

Versi API

Versi Status Kasus Penggunaan
2015-03-31 Saat ini Semua operasi Lambda
2018-01-31 API Runtime Antarmuka runtime kustom

Memulai: Penyiapan Autentikasi

Langkah 1: Buat Akun AWS dan Pengguna IAM

Sebelum mengakses API:

  1. Kunjungi Konsol AWS
  2. Buat akun AWS
  3. Pergi ke Konsol IAM > Pengguna > Buat Pengguna
  4. Lampirkan kebijakan eksekusi Lambda

Langkah 2: Hasilkan Kredensial IAM

Buat kunci akses untuk akses terprogram:

# Metode AWS CLI
aws iam create-access-key --user-name lambda-deployer

# Output: Simpan ini dengan aman
{
  "AccessKey": {
    "AccessKeyId": "AKIAIOSFODNN7EXAMPLE",
    "SecretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
  }
}

Catatan keamanan: Simpan kredensial dengan aman:

# ~/.aws/credentials
[lambda-deployer]
aws_access_key_id = AKIAIOSFODNN7EXAMPLE
aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY

# Atau gunakan variabel lingkungan
export AWS_ACCESS_KEY_ID="AKIAIOSFODNN7EXAMPLE"
export AWS_SECRET_ACCESS_KEY="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
export AWS_DEFAULT_REGION="us-east-1"

Langkah 3: Pahami AWS Signature Versi 4

Semua permintaan API Lambda memerlukan penandatanganan SigV4:

const crypto = require('crypto');

class AWSSigner {
  constructor(accessKeyId, secretAccessKey, region, service = 'lambda') {
    this.accessKeyId = accessKeyId;
    this.secretAccessKey = secretAccessKey;
    this.region = region;
    this.service = service;
  }

  sign(request, body = null) {
    const now = new Date();
    const amzDate = now.toISOString().replace(/[:-]|\.\d{3}/g, '');
    const dateStamp = amzDate.slice(0, 8);

    // Tugas 1: Buat permintaan kanonis
    const hashedPayload = body ? crypto.createHash('sha256').update(body).digest('hex') : 'UNSIGNED-PAYLOAD';
    const canonicalUri = request.path;
    const canonicalQuerystring = request.query || '';
    const canonicalHeaders = `host:${request.host}\nx-amz-date:${amzDate}\n`;
    const signedHeaders = 'host;x-amz-date';
    const canonicalRequest = `${request.method}\n${canonicalUri}\n${canonicalQuerystring}\n${canonicalHeaders}\n${signedHeaders}\n${hashedPayload}`;

    // Tugas 2: Buat string untuk ditandatangani
    const algorithm = 'AWS4-HMAC-SHA256';
    const credentialScope = `${dateStamp}/${this.region}/${this.service}/aws4_request`;
    const hash = crypto.createHash('sha256').update(canonicalRequest).digest('hex');
    const stringToSign = `${algorithm}\n${amzDate}\n${credentialScope}\n${hash}`;

    // Tugas 3: Hitung tanda tangan
    const kDate = this.hmac(`AWS4${this.secretAccessKey}`, dateStamp);
    const kRegion = this.hmac(kDate, this.region);
    const kService = this.hmac(kRegion, this.service);
    const kSigning = this.hmac(kService, 'aws4_request');
    const signature = this.hmac(kSigning, stringToSign, 'hex');

    // Tugas 4: Tambahkan header otorisasi
    const authorizationHeader = `${algorithm} Credential=${this.accessKeyId}/${credentialScope}, SignedHeaders=${signedHeaders}, Signature=${signature}`;

    return {
      'Authorization': authorizationHeader,
      'X-Amz-Date': amzDate,
      'X-Amz-Content-Sha256': hashedPayload
    };
  }

  hmac(key, string, encoding = 'buffer') {
    return crypto.createHmac('sha256', key).update(string).digest(encoding);
  }
}

// Penggunaan
const signer = new AWSSigner(
  process.env.AWS_ACCESS_KEY_ID,
  process.env.AWS_SECRET_ACCESS_KEY,
  'us-east-1'
);

Langkah 4: Buat Klien API Lambda

const LAMBDA_BASE_URL = 'https://lambda.us-east-1.amazonaws.com/2015-03-31';

const lambdaRequest = async (path, options = {}) => {
  const url = new URL(`${LAMBDA_BASE_URL}${path}`);
  const method = options.method || 'GET';
  const body = options.body ? JSON.stringify(options.body) : null;

  const signer = new AWSSigner(
    process.env.AWS_ACCESS_KEY_ID,
    process.env.AWS_SECRET_ACCESS_KEY,
    'us-east-1'
  );

  const headers = signer.sign({ method, host: 'lambda.us-east-1.amazonaws.com', path }, body);

  const response = await fetch(url.toString(), {
    method,
    headers: {
      'Content-Type': 'application/json',
      ...headers,
      ...options.headers
    },
    body
  });

  if (!response.ok) {
    const error = await response.json();
    throw new Error(`Lambda API Error: ${error.Message}`);
  }

  return response.json();
};

// Penggunaan
const functions = await lambdaRequest('/functions');
console.log(`Ditemukan ${functions.Functions.length} fungsi`);

Alternatif: Gunakan AWS SDK

Untuk penggunaan produksi, AWS SDK menangani penandatanganan secara otomatis:

const { LambdaClient, ListFunctionsCommand, CreateFunctionCommand, InvokeCommand } = require('@aws-sdk/client-lambda');

const lambda = new LambdaClient({ region: 'us-east-1' });

// Daftar fungsi
const listCommand = new ListFunctionsCommand({});
const result = await lambda.send(listCommand);

// Buat fungsi
const createCommand = new CreateFunctionCommand({
  FunctionName: 'my-function',
  Runtime: 'nodejs20.x',
  Role: 'arn:aws:iam::123456789012:role/lambda-execution-role',
  Handler: 'index.handler',
  Code: {
    S3Bucket: 'my-bucket',
    S3Key: 'function.zip'
  }
});

const fn = await lambda.send(createCommand);

Pengelolaan Fungsi

Membuat Fungsi

Buat fungsi Lambda melalui API:

const createFunction = async (functionConfig) => {
  const response = await lambdaRequest('/functions', {
    method: 'POST',
    body: {
      FunctionName: functionConfig.name,
      Runtime: functionConfig.runtime || 'nodejs20.x',
      Role: functionConfig.roleArn,
      Handler: functionConfig.handler || 'index.handler',
      Code: {
        S3Bucket: functionConfig.s3Bucket,
        S3Key: functionConfig.s3Key
      },
      Description: functionConfig.description || '',
      Timeout: functionConfig.timeout || 3,
      MemorySize: functionConfig.memorySize || 128,
      Environment: {
        Variables: functionConfig.environment || {}
      },
      Tags: functionConfig.tags || {}
    }
  });

  return response;
};

// Penggunaan
const fn = await createFunction({
  name: 'order-processor',
  roleArn: 'arn:aws:iam::123456789012:role/lambda-execution-role',
  handler: 'index.handler',
  runtime: 'nodejs20.x',
  s3Bucket: 'my-deployments-bucket',
  s3Key: 'order-processor/v1.0.0.zip',
  description: 'Memproses pesanan dari antrean SQS',
  timeout: 30,
  memorySize: 512,
  environment: {
    DB_HOST: 'db.example.com',
    LOG_LEVEL: 'info'
  }
});

console.log(`Fungsi dibuat: ${fn.FunctionArn}`);

Mengunggah Kode Secara Langsung

Untuk fungsi kecil (<50MB terkompresi):

const fs = require('fs');
const path = require('path');

const createFunctionWithZip = async (functionName, zipPath) => {
  const zipBuffer = fs.readFileSync(zipPath);
  const base64Code = zipBuffer.toString('base64');

  const response = await lambdaRequest('/functions', {
    method: 'POST',
    body: {
      FunctionName: functionName,
      Runtime: 'nodejs20.x',
      Role: 'arn:aws:iam::123456789012:role/lambda-execution-role',
      Handler: 'index.handler',
      Code: {
        ZipFile: base64Code
      }
    }
  });

  return response;
};

// Paket fungsi
// zip -r function.zip index.js node_modules/
await createFunctionWithZip('my-function', './function.zip');

Memperbarui Kode Fungsi

Terapkan versi kode baru:

const updateFunctionCode = async (functionName, updateConfig) => {
  const response = await lambdaRequest(`/functions/${functionName}/code`, {
    method: 'PUT',
    body: {
      S3Bucket: updateConfig.s3Bucket,
      S3Key: updateConfig.s3Key,
      Publish: updateConfig.publish || false
    }
  });

  return response;
};

// Penggunaan
const updated = await updateFunctionCode('order-processor', {
  s3Bucket: 'my-deployments-bucket',
  s3Key: 'order-processor/v1.1.0.zip',
  publish: true // Buat versi baru
});

console.log(`Diperbarui ke versi: ${updated.Version}`);

Memperbarui Konfigurasi Fungsi

Modifikasi batas waktu, memori, lingkungan:

const updateFunctionConfig = async (functionName, config) => {
  const response = await lambdaRequest(`/functions/${functionName}/configuration`, {
    method: 'PUT',
    body: {
      Runtime: config.runtime,
      Handler: config.handler,
      Description: config.description,
      Timeout: config.timeout,
      MemorySize: config.memorySize,
      Environment: {
        Variables: config.environment
      }
    }
  });

  return response;
};

// Penggunaan
const updated = await updateFunctionConfig('order-processor', {
  timeout: 60,
  memorySize: 1024,
  environment: {
    DB_HOST: 'new-db.example.com',
    LOG_LEVEL: 'debug'
  }
});

Menghapus Fungsi

Hapus fungsi:

const deleteFunction = async (functionName, qualifier = null) => {
  const path = qualifier
    ? `/functions/${functionName}?Qualifier=${qualifier}`
    : `/functions/${functionName}`;

  await lambdaRequest(path, { method: 'DELETE' });
  console.log(`Fungsi ${functionName} dihapus`);
};

Pemanggilan Fungsi

Pemanggilan Sinkron (Permintaan-Respons)

Panggil fungsi dan tunggu respons:

const invokeFunction = async (functionName, payload, qualifier = null) => {
  const path = qualifier
    ? `/functions/${functionName}/invocations?Qualifier=${qualifier}`
    : `/functions/${functionName}/invocations`;

  const response = await lambdaRequest(path, {
    method: 'POST',
    headers: {
      'X-Amz-Invocation-Type': 'RequestResponse', // Sinkron
      'X-Amz-Log-Type': 'Tail' // Sertakan log
    },
    body: payload
  });

  // Urai respons
  const result = JSON.parse(Buffer.from(response.Payload).toString());
  const logs = Buffer.from(response.LogResult, 'base64').toString();

  return { result, logs };
};

// Penggunaan
const { result, logs } = await invokeFunction('order-processor', {
  orderId: 'ORD-12345',
  customerId: 'CUST-67890',
  items: [
    { sku: 'PROD-001', quantity: 2 },
    { sku: 'PROD-002', quantity: 1 }
  ]
});

console.log(`Hasil: ${JSON.stringify(result)}`);
console.log(`Log:\n${logs}`);

Pemanggilan Asinkron (Fire-and-Forget)

Panggil fungsi tanpa menunggu:

const invokeAsync = async (functionName, payload) => {
  const response = await lambdaRequest(`/functions/${functionName}/invocations`, {
    method: 'POST',
    headers: {
      'X-Amz-Invocation-Type': 'Event', // Asinkron
      'X-Amz-Log-Type': 'None'
    },
    body: payload
  });

  return {
    statusCode: response.StatusCode,
    executionId: response['X-Amz-Execution-Id']
  };
};

// Penggunaan - picu pemrosesan asinkron
const result = await invokeAsync('email-sender', {
  to: 'customer@example.com',
  template: 'order-confirmation',
  data: { orderId: 'ORD-12345' }
});

console.log(`ID pemanggilan asinkron: ${result.executionId}`);

Pemanggilan Dry Run

Uji izin tanpa mengeksekusi:

const dryRunInvocation = async (functionName) => {
  const response = await lambdaRequest(`/functions/${functionName}/invocations`, {
    method: 'POST',
    headers: {
      'X-Amz-Invocation-Type': 'DryRun'
    }
  });

  return response;
};

// Penggunaan - verifikasi izin IAM
try {
  await dryRunInvocation('order-processor');
  console.log('Izin pemanggilan OK');
} catch (error) {
  console.error('Izin ditolak:', error.message);
}

Jenis Respons Pemanggilan

Jenis Pemanggilan Perilaku Kasus Penggunaan
RequestResponse Sinkron, tunggu hasil Panggilan API, perintah CLI
Event Asinkron, fire-and-forget Pemrosesan peristiwa, notifikasi
DryRun Hanya uji izin Validasi, debugging

Pengelolaan Versi dan Alias

Menerbitkan Versi

Buat versi fungsi yang tidak dapat diubah (immutable):

const publishVersion = async (functionName, description = null) => {
  const response = await lambdaRequest(`/functions/${functionName}/versions`, {
    method: 'POST',
    body: description ? { Description: description } : {}
  });

  return response;
};

// Penggunaan
const version = await publishVersion('order-processor', 'v1.2.0 - Tambah perhitungan pajak');
console.log(`Versi yang diterbitkan: ${version.Version}`);

Membuat Alias

Buat penunjuk bernama ke versi:

const createAlias = async (functionName, aliasName, version, description = null) => {
  const response = await lambdaRequest(`/functions/${functionName}/aliases`, {
    method: 'POST',
    body: {
      Name: aliasName,
      FunctionVersion: version,
      Description: description
    }
  });

  return response;
};

// Penggunaan - Buat alias produksi
const prodAlias = await createAlias('order-processor', 'prod', '5', 'Versi produksi');
console.log(`ARN Alias: ${prodAlias.AliasArn}`);

Pergeseran Lalu Lintas dengan Konfigurasi Perutean

Secara bertahap alihkan lalu lintas ke versi baru:

const updateAliasWithRouting = async (functionName, aliasName, routingConfig) => {
  const response = await lambdaRequest(`/functions/${functionName}/aliases/${aliasName}`, {
    method: 'PUT',
    body: {
      RoutingConfig: {
        AdditionalVersionWeights: routingConfig
      }
    }
  });

  return response;
};

// Penggunaan - 10% lalu lintas ke versi 6, 90% ke versi 5
await updateAliasWithRouting('order-processor', 'prod', {
  '6': 0.1
});

// Setelah validasi, geser ke 100%
await updateAliasWithRouting('order-processor', 'prod', {});

Kasus Penggunaan Alias

Alias Versi Tujuan
dev $LATEST Pengujian pengembangan
staging Versi teruji terbaru Validasi QA
prod Versi stabil Lalu lintas produksi
blue Produksi saat ini Deployment blue-green
green Versi baru Deployment blue-green

Pemetaan Sumber Peristiwa

Membuat Pemicu SQS

Hubungkan antrean SQS ke Lambda:

const createSQSEventSource = async (functionName, queueArn, batchSize = 10) => {
  const response = await lambdaRequest('/event-source-mappings', {
    method: 'POST',
    body: {
      EventSourceArn: queueArn,
      FunctionName: functionName,
      BatchSize: batchSize,
      Enabled: true
    }
  });

  return response;
};

// Penggunaan
const mapping = await createSQSEventSource(
  'order-processor',
  'arn:aws:sqs:us-east-1:123456789012:orders-queue',
  10
);

console.log(`Sumber peristiwa dibuat: ${mapping.UUID}`);

Membuat Pemicu DynamoDB Stream

Hubungkan stream DynamoDB ke Lambda:

const createDynamoDBEventSource = async (functionName, streamArn, startingPosition = 'LATEST') => {
  const response = await lambdaRequest('/event-source-mappings', {
    method: 'POST',
    body: {
      EventSourceArn: streamArn,
      FunctionName: functionName,
      StartingPosition: startingPosition,
      BatchSize: 100,
      BisectBatchOnFunctionError: true,
      MaximumRetryAttempts: 3
    }
  });

  return response;
};

// Penggunaan
await createDynamoDBEventSource(
  'user-analytics',
  'arn:aws:dynamodb:us-east-1:123456789012:table/Users/stream/2026-03-25T00:00:00.000'
);

Jenis Sumber Peristiwa

Sumber Kasus Penggunaan Dukungan Batch
SQS Antrean pesan Ya (1-10)
Kinesis Stream waktu nyata Ya (1-10,000)
DynamoDB Streams Perubahan database Ya (1-1,000)
S3 Peristiwa objek Tidak (1 per peristiwa)
EventBridge Perutean peristiwa Ya
API Gateway API HTTP Tidak
Jadwal Cron job Tidak

Pengelolaan Layer

Membuat Layer

Kemasan kode/dependensi bersama:

const createLayer = async (layerName, layerConfig) => {
  const response = await lambdaRequest('/layers', {
    method: 'POST',
    body: {
      LayerName: layerName,
      Description: layerConfig.description,
      CompatibleRuntimes: layerConfig.runtimes,
      Content: {
        S3Bucket: layerConfig.s3Bucket,
        S3Key: layerConfig.s3Key
      }
    }
  });

  return response;
};

// Penggunaan
const layer = await createLayer('shared-utils', {
  description: 'Utilitas dan dependensi bersama',
  runtimes: ['nodejs20.x', 'nodejs18.x'],
  s3Bucket: 'my-layers-bucket',
  s3Key: 'shared-utils/v1.zip'
});

console.log(`ARN Layer: ${layer.LayerArn}`);

Menggunakan Layer dalam Fungsi

Lampirkan layer ke fungsi:

const createFunctionWithLayers = async (functionConfig) => {
  const response = await lambdaRequest('/functions', {
    method: 'POST',
    body: {
      FunctionName: functionConfig.name,
      Runtime: functionConfig.runtime,
      Role: functionConfig.roleArn,
      Handler: functionConfig.handler,
      Code: {
        S3Bucket: functionConfig.s3Bucket,
        S3Key: functionConfig.s3Key
      },
      Layers: functionConfig.layers // Array ARN layer
    }
  });

  return response;
};

// Penggunaan
await createFunctionWithLayers({
  name: 'api-handler',
  roleArn: 'arn:aws:iam::123456789012:role/lambda-execution-role',
  handler: 'index.handler',
  runtime: 'nodejs20.x',
  s3Bucket: 'my-deployments-bucket',
  s3Key: 'api-handler/v1.0.0.zip',
  layers: [
    'arn:aws:lambda:us-east-1:123456789012:layer:shared-utils:1',
    'arn:aws:lambda:us-east-1:123456789012:layer:aws-sdk:3'
  ]
});

Konkurensi dan Penskalaan

Menyetel Konkurensi Cadangan

Cadangkan kapasitas untuk fungsi penting:

const putFunctionConcurrency = async (functionName, reservedConcurrentExecutions) => {
  const response = await lambdaRequest(`/functions/${functionName}/concurrency`, {
    method: 'PUT',
    body: {
      ReservedConcurrentExecutions: reservedConcurrentExecutions
    }
  });

  return response;
};

// Penggunaan - Cadangkan 100 eksekusi bersamaan
await putFunctionConcurrency('order-processor', 100);

Batas Konkurensi Akun

Jenis Akun Batas Default Peningkatan Tersedia
Tingkat Gratis 1.000 Ya
Bayar-Sesuai-Pakai 1.000 Ya
Enterprise 1.000+ Batas kustom

Daftar Periksa Deployment Produksi

Sebelum deployment ke produksi:

Kasus Penggunaan Dunia Nyata

Backend API

Sebuah perusahaan SaaS membangun API REST tanpa server:

Implementasi kunci:

Pipeline Pemrosesan Peristiwa

Sebuah platform e-commerce memproses pesanan:

Implementasi kunci:

Kesimpulan

API AWS Lambda menyediakan kemampuan komputasi tanpa server yang komprehensif. Poin-poin penting:

tombol

Bagian FAQ

Bagaimana cara saya melakukan autentikasi dengan API Lambda?

Gunakan kredensial AWS IAM dengan penandatanganan Signature Versi 4. AWS SDK menangani penandatanganan secara otomatis.

Apa perbedaan antara pemanggilan sinkron dan asinkron?

Pemanggilan sinkron (RequestResponse) menunggu fungsi selesai dan mengembalikan hasilnya. Pemanggilan asinkron (Event) mengantrekan permintaan dan segera kembali.

Bagaimana cara kerja versi Lambda?

Setiap versi yang diterbitkan adalah snapshot fungsi Anda yang tidak dapat diubah (immutable). Gunakan alias untuk menunjuk ke versi tertentu dan memungkinkan pergeseran lalu lintas.

Apa itu Lambda Layers?

Layer mengemas kode dan dependensi secara terpisah dari kode fungsi, memungkinkan library bersama di beberapa fungsi.

Bagaimana cara mengurangi cold start?

Gunakan konkurensi terprovisi, paket deployment yang lebih kecil, dan bahasa terkompilasi (Go, Rust) untuk fungsi yang sensitif terhadap latensi.

Apa itu konkurensi cadangan?

Konkurensi cadangan menjamin slot eksekusi untuk fungsi tertentu, mencegah masalah 'noisy neighbor' (gangguan dari fungsi lain).

Bisakah saya memicu Lambda dari S3?

Ya, konfigurasi notifikasi peristiwa S3 untuk memanggil Lambda saat objek dibuat/dihapus.

Mengembangkan API dengan Apidog

Apidog adalah alat pengembangan API yang membantu Anda mengembangkan API dengan lebih mudah dan efisien.