Lompat ke konten

Pengembang

Webhook dan Zapier

Webhook mengirim permintaan HTTP ke server Anda saat sesuatu terjadi di ruang kerja Anda, seperti aplikasi yang dijeda atau smart link yang diklik. Gunakan webhook untuk memperbarui sistem Anda sendiri, mengirim pesan ke Slack, atau menghubungkan mapps.one ke Zapier, Make, atau n8n tanpa menulis server. Webhook tersedia di paket Studio, dengan hingga 10 endpoint per ruang kerja.

Tambahkan endpoint

  1. Di dashboard, buka Pengembang → Webhook dan pilih Tambah endpoint. Pemilik dan admin ruang kerja dapat melakukan ini.
  2. Masukkan URL https publik, pilih event yang akan dikirim (atau semua event), dan tambahkan deskripsi.
  3. Salin signing secret dan simpan bersama rahasia server Anda lainnya.
  4. Pilih Kirim event uji untuk memeriksa apakah endpoint Anda merespons.

Halaman endpoint menampilkan pengiriman terbaru beserta status respons, 2.000 karakter pertama dari body respons, dan durasi setiap percobaan. Anda juga dapat membuat dan menghapus endpoint dengan API.

Event

JenisDikirim saat
app.createdAplikasi ditambahkan ke ruang kerja.
app.updatedDetail aplikasi, link, atau pengaturan halaman berubah.
app.deletedAplikasi dihapus.
app.status_changedAplikasi menjadi aktif, dijeda, atau ditangguhkan.
app.metadata_fetchedMetadata store diimpor untuk aplikasi.
legal.publishedDokumen kebijakan privasi atau ketentuan layanan dipublikasikan.
domain.verifiedDomain kustom diverifikasi.
link.clickedSetiap klik smart link. Ini bisa menghasilkan banyak permintaan untuk aplikasi yang populer.
analytics.daily_summaryTotal klik hari sebelumnya untuk setiap aplikasi, dikirim sekali sehari.

Format permintaan

Setiap event dikirim sebagai permintaan POST dengan body JSON.

HeaderNilai
Content-Typeapplication/json
User-Agentmapps.one-Webhooks/1.0
X-Mapps-EventJenis event, seperti link.clicked
X-Mapps-DeliveryID event. Nilainya tetap sama pada setiap percobaan ulang.
X-Mapps-TimestampWaktu Unix dari percobaan pengiriman ini
X-Mapps-Signaturet={timestamp},v1={signature}

Body berupa amplop dengan struktur yang sama untuk setiap event:

{
  "id": "evt_01j8c3m9t5v2x7z4b6d8f0h2k4",
  "type": "app.status_changed",
  "created_at": "2026-09-14T09:41:07+00:00",
  "workspace": {
    "id": "01j8a0f4c7d2e9h6k3m5n8q1r4",
    "name": "Habitly Labs"
  },
  "data": {
    "app": {
      "id": "01j8b2k6r3xq9v7m4n5p0s1t2w",
      "slug": "habitly",
      "name": "Habitly"
    },
    "status": "paused"
  }
}

Isi data bergantung pada event. Event tentang aplikasi menyertakan objek app dengan id, slug, dan name-nya.

link.clicked

"data": {
  "app": { "id": "01j8b2k6r3xq9v7m4n5p0s1t2w", "slug": "habitly", "name": "Habitly" },
  "click": {
    "occurred_at": "2026-09-14 09:41:07",
    "os": "iOS",
    "device_type": "mobile",
    "country": "TR",
    "source": "instagram",
    "destination": "app_store",
    "utm_source": "instagram",
    "utm_medium": "social",
    "utm_campaign": "launch"
  }
}

occurred_at dalam UTC. device_type bernilai mobile, tablet, atau desktop. destination berupa kunci store, web, atau landing. Kolom yang tidak diketahui bernilai null. Kunjungan bot tidak pernah memicu event ini.

app.metadata_fetched

"data": {
  "app": { "id": "01j8b2k6r3xq9v7m4n5p0s1t2w", "slug": "habitly", "name": "Habitly" },
  "source": "app_store"
}

Verifikasi signature

Periksa signature pada setiap permintaan, agar Anda tahu bahwa permintaan berasal dari mapps.one dan tidak diubah di tengah jalan:

  1. Baca t dan v1 dari header X-Mapps-Signature.
  2. Hitung HMAC-SHA256 dari {t}.{raw request body} menggunakan signing secret endpoint Anda, dalam format hex huruf kecil.
  3. Bandingkan hasilnya dengan v1 menggunakan perbandingan constant-time.
  4. Tolak permintaan jika t berselisih lebih dari lima menit dari jam server Anda, untuk memblokir permintaan yang diputar ulang.
Gunakan body mentah. Tanda tangani byte persis yang Anda terima, sebelum parsing JSON apa pun. Meng-encode ulang JSON dapat mengubah garis miring atau karakter Unicode dan merusak signature.

PHP

<?php

$secret = getenv('MAPPS_WEBHOOK_SECRET');
$body = file_get_contents('php://input');

parse_str(str_replace(',', '&', $_SERVER['HTTP_X_MAPPS_SIGNATURE'] ?? ''), $parts);

$timestamp = (int) ($parts['t'] ?? 0);
$expected = hash_hmac('sha256', $timestamp.'.'.$body, $secret);

if (! hash_equals($expected, (string) ($parts['v1'] ?? '')) || abs(time() - $timestamp) > 300) {
    http_response_code(400);
    exit;
}

$event = json_decode($body, true);

if ($event['type'] === 'link.clicked') {
    // Store $event['data']['click'] ...
}

http_response_code(200);

Di Laravel, baca body dengan $request->getContent() dan header dengan $request->header('X-Mapps-Signature'), lalu kecualikan route tersebut dari perlindungan CSRF.

Node.js (Express)

import crypto from 'node:crypto';
import express from 'express';

const app = express();
const secret = process.env.MAPPS_WEBHOOK_SECRET;

app.post('/webhooks/mapps', express.raw({ type: 'application/json' }), (req, res) => {
  const header = req.get('X-Mapps-Signature') ?? '';
  const parts = Object.fromEntries(header.split(',').map((pair) => pair.split('=')));
  const timestamp = Number(parts.t);
  const body = req.body.toString('utf8');

  const expected = crypto.createHmac('sha256', secret).update(`${timestamp}.${body}`).digest();
  const received = Buffer.from(parts.v1 ?? '', 'hex');
  const valid = received.length === expected.length && crypto.timingSafeEqual(received, expected);

  if (!valid || Math.abs(Date.now() / 1000 - timestamp) > 300) {
    return res.sendStatus(400);
  }

  const event = JSON.parse(body);

  if (event.type === 'link.clicked') {
    // Store event.data.click ...
  }

  res.sendStatus(200);
});

app.listen(3000);

Respons dan percobaan ulang

  • Balas dengan status 2xx apa pun dalam 10 detik. Kerjakan proses yang lambat di background job setelah Anda merespons.
  • Pengalihan tidak diikuti, jadi gunakan URL akhir.
  • URL harus berupa https publik. Alamat jaringan privat dan lokal ditolak.
  • Jika endpoint Anda mengalami timeout atau mengembalikan apa pun selain 2xx, kami mencoba ulang hingga lima kali lagi: setelah sekitar 1 menit, 5 menit, 30 menit, 2 jam, dan 6 jam. Setiap percobaan memiliki timestamp dan signature baru.
  • Event yang sama dapat tiba lebih dari sekali, dan event dapat tiba tidak berurutan. Gunakan X-Mapps-Delivery, yaitu id event, untuk mengabaikan duplikat, dan created_at untuk mengurutkannya.
  • Setelah 20 percobaan gagal berturut-turut, endpoint dinonaktifkan dan tidak ada lagi yang dikirim ke sana. Perbaiki masalahnya, lalu aktifkan kembali di dashboard.

Zapier, Make, dan n8n

Anda dapat menghubungkan mapps.one ke ribuan aplikasi tanpa menjalankan server.

Zapier

  1. Buat Zap dengan Webhooks by Zapier sebagai trigger dan pilih Catch Hook.
  2. Salin URL webhook yang diberikan Zapier.
  3. Di mapps.one, tambahkan endpoint dengan URL tersebut dan pilih event yang Anda inginkan, misalnya app.status_changed atau analytics.daily_summary.
  4. Pilih Kirim event uji di mapps.one, lalu Test trigger di Zapier. Kolom dari payload, seperti data.app.name, kini dapat digunakan pada langkah berikutnya.

Contoh: kirim pesan Slack saat aplikasi dijeda, tambahkan klik setiap hari ke Google Sheet, atau kirim email ke klien saat domain mereka diverifikasi.

Make dan n8n

Di Make, gunakan trigger Webhooks → Custom webhook. Di n8n, gunakan node Webhook dengan metode POST. Lalu tambahkan URL tersebut sebagai endpoint di mapps.one seperti di atas.

Membangun integrasi

Jika Anda membangun integrasi mapps.one untuk orang lain, daftarkan langganan dengan API saat pengguna menghubungkan akunnya (POST /api/v1/webhooks), batalkan langganan saat mereka memutuskan koneksi (DELETE /api/v1/webhooks/{id}), gunakan GET /api/v1/events untuk pemilih event, dan gunakan GET /api/v1/workspace untuk menguji koneksi. Lihat referensi API.