---
title: 'Hello World' Sync
slug: v4-6/get-started/hello-world-sync
docTags: 
createdAt: 2024-03-05T22:34:58.537Z
---

Once you've set up your environment, try on Ditto and perform your first peer-to-peer sync.&#x20;

Intended to get you oriented, this article provides a streamlined process for integrating sync functionality within your app.&#x20;

:::hint{type="info"}
If you prefer building and exploring through a chat app, and so on, see [Example Projects Overview](docId\:HmL3NunwO5K313jKu_Wyz).&#x20;
:::

# Integrating Sync Functionality

Integrate the Ditto SDK in your codebase, set up authentication, and then start syncing offline:

:::::WorkflowBlock
::::WorkflowBlockItem
From the top-most scope of your app's codebase, add the following to set up authentication and start syncing offline.

:::CodeblockTabs
```swift
DittoLogger.minimumLogLevel = .debug
let ditto = Ditto(identity: .onlinePlayground(
    appID: "REPLACE_ME_WITH_YOUR_APP_ID",
    token: "REPLACE_ME_WITH_YOUR_PLAYGROUND_TOKEN"
))
do {
  try ditto.startSync()
} catch (let err) {
  print(err.localizedDescription)
}
```

```kotlin
try {
    val androidDependencies = DefaultAndroidDittoDependencies(context)
    val identity = DittoIdentity.OnlinePlayground(
        androidDependencies,
        appId = "REPLACE_ME_WITH_YOUR_APP_ID",
        token = "REPLACE_ME_WITH_YOUR_PLAYGROUND_TOKEN"
    )
    DittoLogger.minimumLogLevel = DittoLogLevel.DEBUG
    ditto = Ditto(androidDependencies, identity)
    ditto.startSync()
} catch (e: DittoError) {
    Log.e("Ditto error", e.message!!)
}
```

```javascript
import { init, Ditto, Logger } from "@dittolive/ditto"
Logger.minimumLogLevel = 'Debug'
const identity: Identity = { type: 'onlinePlayground', appID: 'REPLACE_ME_WITH_YOUR_APP_ID', token: 'REPLACE_ME_WITH_YOUR_PLAYGROUND_TOKEN' }
const path = './your-ditto-application-data-path'
const ditto = new Ditto(identity, path)
ditto.startSync()
```

```nodejs
import { init, Ditto, Logger } from "@dittolive/ditto"
Logger.minimumLogLevel = 'Debug'
const identity: Identity = { type: 'onlinePlayground', appID: 'REPLACE_ME_WITH_YOUR_APP_ID', token: 'REPLACE_ME_WITH_YOUR_PLAYGROUND_TOKEN' }
const path = './your-ditto-application-data-path'
const ditto = new Ditto(identity, path)
ditto.startSync()
```

```java
DittoDependencies androidDependencies = new DefaultAndroidDittoDependencies(this.context);
DittoLogger.setMinimumLogLevel(DittoLogLevel.DEBUG);
DittoIdentity identity = new DittoIdentity.OnlinePlayground(androidDependencies, "REPLACE_ME_WITH_YOUR_APP_ID", "YOUR_PLAYGROUND_TOKEN_HERE");
Ditto ditto = new Ditto(androidDependencies, identity);

try {
    ditto.startSync();
} catch(DittoError e) {
    //handle error
}
```

```csharp
try
{
    DittoLogger.SetMinimumLogLevel(DittoLogLevel.Debug);
    var ditto = new Ditto(DittoIdentity.OnlinePlayground("REPLACE_ME_WITH_YOUR_APP_ID", "REPLACE_ME_WITH_YOUR_PLAYGROUND_TOKEN", true), path);
    ditto.StartSync();
}
catch (DittoException ex)
{
    Console.WriteLine($"Ditto Error {ex.Message}");
}
```

```cpp
auto identity =
    Identity::OnlinePlayground("REPLACE_ME_WITH_YOUR_APP_ID",
                               "REPLACE_ME_WITH_YOUR_PLAYGROUND_TOKEN", true);
try {
  Ditto ditto = Ditto(identity, dir);
  ditto.set_minimum_log_level(LogLevel::debug);
  ditto.start_sync();
} catch (const DittoError &err) {
}
```

```rust
let ditto = Ditto::builder()
    // creates a `ditto_data` folder in the directory containing the executing process
    .with_root(Arc::new(PersistentRoot::from_current_exe()?))
    .with_identity(|ditto_root| {
        // Provided as an env var, may also be provided as hardcoded string
        let app_id = AppId::from_env("REPLACE_ME_WITH_YOUR_APP_ID")?;
        let shared_token = std::env::var("REPLACE_ME_WITH_A_SHARED_TOKEN").unwrap();
        let enable_cloud_sync = true;
        let custom_auth_url = None;
        OnlinePlayground::new(
            ditto_root,
            app_id,
            shared_token,
            enable_cloud_sync,
            custom_auth_url,
        )
    })?
    .with_minimum_log_level(LogLevel::Debug)
    .build()?;

ditto.start_sync()?;
```

```curl
# not supported by HTTP API
```
:::
::::

:::WorkflowBlockItem
Replace `YOUR_APP_ID` and `YOUR_PLAYGROUND_TOKEN` with your access credentials available from the portal.&#x20;
:::
:::::

***

# Creating Subscriptions

To register a new sync subscription in your app. For example, the following snippet demonstrates how to establish a subscription to sync updates to documents in the `cars` collection with a field of `color` set to the value `blue`:

:::CodeblockTabs
```swift
ditto.sync.registerSubscription("SELECT * FROM cars")
```

```kotlin
ditto.sync.registerSubscription("SELECT * FROM cars")
```

```javascript
ditto.sync.registerSubscription("SELECT * FROM cars")
```

```java
ditto.sync.registerSubscription("SELECT * FROM cars")
```

```csharp
ditto.Sync.RegisterSubscription("SELECT * FROM cars");
```

```cpp
auto subscription = 
  ditto.sync().register_subscription("SELECT * FROM cars");
```

```rust
let subscription = 
  ditto.sync().register_subscription("SELECT * FROM cars", None);
```
:::

Sync subscriptions also support argument injection using the `:argument` syntax in DQL:

:::CodeblockTabs
```swift
ditto.sync.registerSubscription("""
  SELECT *
  FROM cars
  WHERE color = :color
  """,
  [ "color": "blue" ])
```

```kotlin
ditto.sync.registerSubscription("""
  SELECT *
  FROM cars
  WHERE color = :color
  """,
  mapOf("color" to "blue"))
```

```javascript
ditto.sync.registerSubscription(`
  SELECT *
  FROM cars
  WHERE color = :color`,
  { color: 'blue' })
```

```java
ditto.sync.registerSubscription(
  "SELECT * FROM cars WHERE color = :color",
  Collections.singletonMap("color", "blue"))
```

```csharp
var queryArguments = new Dictionary<string, object>(){{"color", "blue" }};

ditto.Sync.RegisterSubscription(
  "SELECT * FROM cars WHERE color = 'blue'",
  queryArguments);
```

```cpp
ditto.sync().register_subscription(
  "SELECT * FROM cars WHERE color = :color",
  {{"color", "blue"}});
```

```rust
struct Args {
  color: String,
}

// ...

let args = Args {
  color: "blue".to_string(),
};
ditto.sync().register_subscription(
  "SELECT * FROM cars WHERE color = :color",
  args);
```
:::

***

# Retrieving Subscriptions

Retrieve active sync subscriptions by calling the `subscriptions` method on the `ditto.sync` namespace:

:::CodeblockTabs
```swift
let activeSubscriptions = ditto.sync.subscriptions;
```

```kotlin
val activeSubscriptions = ditto.sync.subscriptions
```

```javascript
const activeSubscriptions = ditto.sync.subscriptions
```

```java
DittoSyncSubscription[] activeSubscriptions = ditto.sync.subscriptions;
```

```csharp
var activeSubscriptions = ditto.Sync.Subscriptions;
```

```cpp
// Not Supported. Hold the reference to the SyncSubscription object.
```

```rust
// Not Supported. Hold the reference to the SyncSubscription object.
```
:::

***

# Canceling Subscriptions

To cancel a subscription, call `cancel` on the subscription object you set up to establish your subscription:

:::CodeblockTabs
```swift
subscription.cancel()
```

```kotlin
subscription.close()
```

```javascript
subscription.cancel()
```

```java
subscription.close()
```

```csharp
subscription.Cancel();
```

```cpp
// ...
```

```rust
// ...
```
:::

You can check if a sync subscription is canceled by using the `isCancelled` field on the subscription object:

:::CodeblockTabs
```swift
subscription.isCancelled
```

```kotlin
subscription.isClosed
```

```javascript
subscription.isCancelled
```

```java
subscription.isCancelled
```

```csharp
subscription.IsCancelled
```

```cpp
// ...
```

```rust
// ...
```
:::

