@@ -10,6 +10,11 @@ BemiDB is an open-source Snowflake and Fivetran alternative bundled together. It
1010- [ Use cases] ( #use-cases )
1111- [ Quickstart] ( #quickstart )
1212- [ Usage] ( #usage )
13+ - [ Syncing from Amplitude] ( #syncing-from-amplitude )
14+ - [ Syncing from Attio] ( #syncing-from-attio )
15+ - [ Syncing from Dialpad] ( #syncing-from-dialpad )
16+ - [ Syncing from Postgres] ( #syncing-from-postgres )
17+ - [ Customizing S3 endpoint] ( #customizing-s3-endpoint )
1318- [ Configuration] ( #configuration )
1419- [ Architecture] ( #architecture )
1520- [ Benchmark] ( #benchmark )
@@ -118,50 +123,124 @@ psql postgres://localhost:54321/bemidb -c "SELECT COUNT(*) FROM postgres.[table_
118123
119124## Usage
120125
121- #### Syncing from Postgres
126+ #### Syncing from Amplitude
122127
123- By default, BemiDB syncs all tables from the Postgres database. To include and sync only specific tables from your Postgres database:
128+ 1 . Create an [ Amplitude API key] ( https://docs.gettelio.com/integrations/amplitude )
129+ 2 . Run the syncer:
124130
125131``` sh
126132docker run \
127- -e SOURCE_POSTGRES_DATABASE_URL=postgres://user:password@host.docker.internal:5432/source \
128- -e SOURCE_POSTGRES_INCLUDE_TABLES=public.table1,public.table2 \ # A comma-separated list of tables to include
129- -e DESTINATION_SCHEMA_NAME=postgres \
133+ -e SOURCE_AMPLITUDE_API_KEY=[...] \
134+ -e SOURCE_AMPLITUDE_SECRET_KEY=[...] \
135+ -e SOURCE_AMPLITUDE_START_DATE=2025-01-01 \
136+ -e DESTINATION_SCHEMA_NAME=amplitude \
130137 -e AWS_REGION -e AWS_S3_BUCKET -e AWS_ACCESS_KEY_ID -e AWS_SECRET_ACCESS_KEY -e CATALOG_DATABASE_URL \
131- ghcr.io/bemihq/bemidb:latest syncer-postgres
138+ ghcr.io/bemihq/bemidb:latest syncer-amplitude
132139```
133140
134- To exclude specific tables during the sync:
141+ #### Syncing from Attio
142+
143+ 1 . Create an [ Attio API access token] ( https://docs.gettelio.com/integrations/attio )
144+ 2 . Run the syncer:
135145
136146``` sh
137147docker run \
138- -e SOURCE_POSTGRES_DATABASE_URL=postgres://user:password@host.docker.internal:5432/source \
139- -e SOURCE_POSTGRES_EXCLUDE_TABLES=public.audit_log,public.cache \ # A comma-separated list of tables to exclude
140- -e DESTINATION_SCHEMA_NAME=postgres \
148+ -e SOURCE_ATTIO_API_ACCESS_TOKEN=[...] \
149+ -e DESTINATION_SCHEMA_NAME=attio \
141150 -e AWS_REGION -e AWS_S3_BUCKET -e AWS_ACCESS_KEY_ID -e AWS_SECRET_ACCESS_KEY -e CATALOG_DATABASE_URL \
142- ghcr.io/bemihq/bemidb:latest syncer-postgres
151+ ghcr.io/bemihq/bemidb:latest syncer-attio
143152```
144153
145- #### Syncing from Amplitude
154+ #### Syncing from Dialpad
155+
156+ 1 . Create a [ Dialpad API key] ( https://docs.gettelio.com/integrations/dialpad )
157+ 2 . Create a webhook endpoint:
158+
159+ ``` sh
160+ curl -X POST " https://dialpad.com/api/v2/webhooks" \
161+ -H " Content-Type: application/json" \
162+ -H " Authorization: Bearer [DIALPAD_API_KEY]" \
163+ -d ' {
164+ "hook_url": "https://[YOUR_DOMAIN]/[YOUR_WEBHOOK_ENDPOINT]",
165+ "secret": "[YOUR_WEBHOOK_SECRET]"
166+ }'
167+ ```
168+
169+ 3 . Subscribe to SMS events for the created webhook:
170+
171+ ``` sh
172+ curl -X POST " https://dialpad.com/api/v2/subscriptions/sms" \
173+ -H " Content-Type: application/json" \
174+ -H " Authorization: Bearer [DIALPAD_API_KEY]" \
175+ -d ' {
176+ "direction": "all",
177+ "enabled": true,
178+ "endpoint_id": "[WEBHOOK_ID]",
179+ "include_internal": false,
180+ "status": false
181+ }'
182+ ```
183+
184+ 4 . Write a small service to receive Dialpad webhook events and publish them to NATS JetStream.
185+
186+ <details >
187+ <summary >See example code in Node.js</summary >
188+
189+ ``` ts
190+ import express from ' express' ;
191+ import bodyParser from ' body-parser' ;
192+ import { jwtVerify } from ' jose' ;
193+ import { connect , JSONCodec } from ' nats' ;
194+
195+ const app = express ();
196+ app .use (bodyParser .json ());
197+ app .post (' /dialpad-webhook' , async (req , res ) => {
198+ const { payload } = await jwtVerify (request .body , new TextEncoder ().encode (' [YOUR_WEBHOOK_SECRET]' ), { algorithms: [' HS256' ] });
199+ const jsonCodec = JSONCodec ();
200+ const natsConnection = await connect ({ servers: " nats://host.docker.internal:4222" });
201+ const jetstreamManager = await natsConnection .jetstreamManager ();
202+ await jetstreamManager .streams .add ({ name: ' bemidb' , subjects: [' bemidb.dialpad' ] });
203+ await jetstreamManager .jetstream ().publish (' bemidb.dialpad' , jsonCodec .encode (payload ));
204+ });
205+ app .listen (3000 , () => console .log (' Server is running on port 3000' ));
206+ ```
207+ </details >
208+
209+ 5 . Run the syncer:
146210
147211``` sh
148212docker run \
149- -e SOURCE_AMPLITUDE_API_KEY=[...] \
150- -e SOURCE_AMPLITUDE_SECRET_KEY=[...] \
151- -e SOURCE_AMPLITUDE_START_DATE=2025-01-01 \
152- -e DESTINATION_SCHEMA_NAME=amplitude \
213+ -e NATS_URL=nats://host.docker.internal:4222 \
214+ -e NATS_JETSTREAM_STREAM=bemidb \
215+ -e NATS_JETSTREAM_SUBJECT=bemidb.dialpad \
216+ -e NATS_JETSTREAM_CONSUMER_NAME=bemidb-dialpad \
217+ -e DESTINATION_SCHEMA_NAME=dialpad \
153218 -e AWS_REGION -e AWS_S3_BUCKET -e AWS_ACCESS_KEY_ID -e AWS_SECRET_ACCESS_KEY -e CATALOG_DATABASE_URL \
154- ghcr.io/bemihq/bemidb:latest syncer-amplitude
219+ ghcr.io/bemihq/bemidb:latest syncer-dialpad
155220```
156221
157- #### Syncing from Attio
222+ #### Syncing from Postgres
223+
224+ By default, BemiDB syncs all tables from the Postgres database. To include and sync only specific tables from your Postgres database:
158225
159226``` sh
160227docker run \
161- -e SOURCE_ATTIO_API_ACCESS_TOKEN=[...] \
162- -e DESTINATION_SCHEMA_NAME=attio \
228+ -e SOURCE_POSTGRES_DATABASE_URL=postgres://user:password@host.docker.internal:5432/source \
229+ -e SOURCE_POSTGRES_INCLUDE_TABLES=public.table1,public.table2 \ # A comma-separated list of tables to include
230+ -e DESTINATION_SCHEMA_NAME=postgres \
163231 -e AWS_REGION -e AWS_S3_BUCKET -e AWS_ACCESS_KEY_ID -e AWS_SECRET_ACCESS_KEY -e CATALOG_DATABASE_URL \
164- ghcr.io/bemihq/bemidb:latest syncer-attio
232+ ghcr.io/bemihq/bemidb:latest syncer-postgres
233+ ```
234+
235+ To exclude specific tables during the sync:
236+
237+ ``` sh
238+ docker run \
239+ -e SOURCE_POSTGRES_DATABASE_URL=postgres://user:password@host.docker.internal:5432/source \
240+ -e SOURCE_POSTGRES_EXCLUDE_TABLES=public.audit_log,public.cache \ # A comma-separated list of tables to exclude
241+ -e DESTINATION_SCHEMA_NAME=postgres \
242+ -e AWS_REGION -e AWS_S3_BUCKET -e AWS_ACCESS_KEY_ID -e AWS_SECRET_ACCESS_KEY -e CATALOG_DATABASE_URL \
243+ ghcr.io/bemihq/bemidb:latest syncer-postgres
165244```
166245
167246#### Customizing S3 endpoint
@@ -195,15 +274,6 @@ export AWS_S3_ENDPOINT=http://localhost:9000
195274
196275## Configuration
197276
198- #### ` syncer-postgres ` command options
199-
200- | Environment variable | Default value | Description |
201- | -------------------------------------| ---------------| ----------------------------------------------------------------------|
202- | ` DESTINATION_SCHEMA_NAME ` | Required | Schema name in BemiDB to sync data to. |
203- | ` SOURCE_POSTGRES_DATABASE_URL ` | Required | Postgres database URL to sync data from. |
204- | ` SOURCE_POSTGRES_INCLUDE_TABLES ` | | List of tables to include in sync. Comma-separated ` schema.table ` . |
205- | ` SOURCE_POSTGRES_EXCLUDE_TABLES ` | | List of tables to exclude from sync. Comma-separated ` schema.table ` . |
206-
207277#### ` syncer-amplitude ` command options
208278
209279| Environment variable | Default value | Description |
@@ -220,6 +290,26 @@ export AWS_S3_ENDPOINT=http://localhost:9000
220290| ` DESTINATION_SCHEMA_NAME ` | Required | Schema name in BemiDB to sync data to. |
221291| ` SOURCE_ATTIO_API_ACCESS_TOKEN ` | Required | Attio API access token for authentication. |
222292
293+ #### ` syncer-dialpad ` command options
294+
295+ | Environment variable | Default value | Description |
296+ | --------------------------------| ---------------| ----------------------------------------------------------------|
297+ | ` DESTINATION_SCHEMA_NAME ` | Required | Schema name in BemiDB to sync data to. |
298+ | ` NATS_URL ` | Required | NATS server URL for connecting to receive Dialpad SMS records. |
299+ | ` NATS_JETSTREAM_STREAM ` | Required | NATS JetStream stream name. |
300+ | ` NATS_JETSTREAM_SUBJECT ` | Required | NATS JetStream subject name. |
301+ | ` NATS_JETSTREAM_CONSUMER_NAME ` | Required | NATS JetStream consumer name. |
302+ | ` NATS_FETCH_TIMEOUT_SECONDS ` | ` 30 ` | Timeout in seconds for fetching messages from NATS. |
303+
304+ #### ` syncer-postgres ` command options
305+
306+ | Environment variable | Default value | Description |
307+ | -------------------------------------| ---------------| ----------------------------------------------------------------------|
308+ | ` DESTINATION_SCHEMA_NAME ` | Required | Schema name in BemiDB to sync data to. |
309+ | ` SOURCE_POSTGRES_DATABASE_URL ` | Required | Postgres database URL to sync data from. |
310+ | ` SOURCE_POSTGRES_INCLUDE_TABLES ` | | List of tables to include in sync. Comma-separated ` schema.table ` . |
311+ | ` SOURCE_POSTGRES_EXCLUDE_TABLES ` | | List of tables to exclude from sync. Comma-separated ` schema.table ` . |
312+
223313#### ` server ` command options
224314
225315| Environment variable | Default value | Description |
@@ -323,6 +413,7 @@ SELECT * FROM [TABLE] WHERE [JSON_COLUMN]->>'[JSON_KEY]' = '[JSON_VALUE]';
323413 - [x] Amplitude (incremental)
324414 - [x] Attio CRM (full-refresh)
325415 - [x] Postgres (full-refresh)
416+ - [x] Dialpad (real-time)
326417 - [ ] HubSpot
327418 - [ ] Stripe
328419 - [ ] Google Sheets
0 commit comments