# CRM Properties

CRM Properties are stored securely only on the Hackle server and cannot be directly queried through the SDK.

{% hint style="danger" %}
CRM Properties are managed separately and are not deleted or reset even if you call `resetUser()` or `clearAll` in `updateUserProperties`.

If a user withdraws their account, you must call the separately provided function to delete the information.
{% endhint %}

## Phone Number Collection

{% hint style="danger" %}
Phone number collection is not available in the Java/Kotlin SDK.

You can collect and delete phone numbers using the [HTTP API](/en/development-guide/http-api/api-properties.md).
{% endhint %}

## CRM Marketing Subscription Consent

{% hint style="info" %}
For more details about subscription consent states, refer to the [CRM Message Subscription Consent Management documentation](/en/development-guide/sdk/user-identifier/crm-subscription.md).
{% endhint %}

### Subscription Consent Properties

You can subscribe or unsubscribe by message purpose.

Use `HackleSubscriptionOperations.Builder` to configure the consent state for the desired properties, then finalize the update using methods like `updatePushSubscriptions()`.

You can update the consent state per message channel.

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
import io.hackle.sdk.common.subscription.HackleSubscriptionOperations
import io.hackle.sdk.common.subscription.HackleSubscriptionStatus

val user = User.builder(userId)
    .build();

val subscriptions = HackleSubscriptionOperations.builder()
    .marketing(HackleSubscriptionStatus.SUBSCRIBED)   // Promotional message subscription consent
    .information(HackleSubscriptionStatus.SUBSCRIBED) // Informational message subscription consent
    .build()

hackle.app.updatePushSubscriptions(subscriptions, user)
```

{% endtab %}

{% tab title="Java" %}

```java
import io.hackle.sdk.common.subscription.HackleSubscriptionOperations
import io.hackle.sdk.common.subscription.HackleSubscriptionStatus

User user = User.builder(userId)
    .build();

HackleSubscriptionOperations subscriptions = HackleSubscriptionOperations.builder()
    .marketing(HackleSubscriptionStatus.SUBSCRIBED)   // Promotional message subscription consent
    .information(HackleSubscriptionStatus.SUBSCRIBED) // Informational message subscription consent
    .build()

hackle.app.updatePushSubscriptions(subscriptions, user)
```

{% endtab %}
{% endtabs %}

<table><thead><tr><th width="224.09765625">HackleSubscriptionStatus</th><th>Description</th></tr></thead><tbody><tr><td><code>UNKNOWN</code></td><td>Subscription Consent has not been given or denied (<code>default</code>)</td></tr><tr><td><code>SUBSCRIPTION</code></td><td>Explicitly opted in to receive messages</td></tr><tr><td><code>UNSUBSCRIPTION</code></td><td>Explicitly opted out of receiving messages</td></tr></tbody></table>

### Update Subscription Consent Status

{% tabs %}
{% tab title="Kotlin" %}
**Update Push Subscription Consent Status**

Updates the user's push message subscription consent status.

```kotlin
import io.hackle.sdk.common.subscription.HackleSubscriptionOperations
import io.hackle.sdk.common.subscription.HackleSubscriptionStatus

val user = User.builder(userId)
    .build();

val subscriptions = HackleSubscriptionOperations.builder()
    .marketing(HackleSubscriptionStatus.SUBSCRIBED)
    .information(HackleSubscriptionStatus.SUBSCRIBED)
    .build()

hackle.app.updatePushSubscriptions(subscriptions, user)
```

**Update Kakao Message Subscription Consent Status**

Updates the user's Kakao message subscription consent status.

```kotlin
import io.hackle.sdk.common.subscription.HackleSubscriptionOperations
import io.hackle.sdk.common.subscription.HackleSubscriptionStatus

val user = User.builder(userId)
    .build();

val subscriptions = HackleSubscriptionOperations.builder()
    .marketing(HackleSubscriptionStatus.SUBSCRIBED)
    .information(HackleSubscriptionStatus.SUBSCRIBED)
    .build()

hackle.app.updateKakaoSubscriptions(subscriptions, user)
```

**Update Text Message Subscription Consent Status**

Updates the user's Text Message subscription consent status.

```kotlin
import io.hackle.sdk.common.subscription.HackleSubscriptionOperations
import io.hackle.sdk.common.subscription.HackleSubscriptionStatus

val user = User.builder(userId)
    .build();

val subscriptions = HackleSubscriptionOperations.builder()
    .marketing(HackleSubscriptionStatus.SUBSCRIBED)
    .information(HackleSubscriptionStatus.SUBSCRIBED)
    .build()

hackle.app.updateSmsSubscriptions(subscriptions, user)
```

{% endtab %}

{% tab title="Java" %}
**Update Push Subscription Consent Status**

Updates the user's push message subscription consent status.

```java
import io.hackle.sdk.common.subscription.HackleSubscriptionOperations
import io.hackle.sdk.common.subscription.HackleSubscriptionStatus

User user = User.builder(userId)
    .build();

HackleSubscriptionOperations subscriptions = HackleSubscriptionOperations.builder()
    .marketing(HackleSubscriptionStatus.SUBSCRIBED)
    .information(HackleSubscriptionStatus.SUBSCRIBED)
    .build()

hackle.app.updatePushSubscriptions(subscriptions, user)
```

**Update Kakao Message Subscription Consent Status**

Updates the user's Kakao message subscription consent status.

```java
import io.hackle.sdk.common.subscription.HackleSubscriptionOperations
import io.hackle.sdk.common.subscription.HackleSubscriptionStatus

User user = User.builder(userId)
    .build();

HackleSubscriptionOperations subscriptions = HackleSubscriptionOperations.builder()
    .marketing(HackleSubscriptionStatus.SUBSCRIBED)
    .information(HackleSubscriptionStatus.SUBSCRIBED)
    .build()

hackle.app.updateKakaoSubscriptions(subscriptions, user)
```

**Update Text Message Subscription Consent Status**

Updates the user's Text Message subscription consent status.

```java
import io.hackle.sdk.common.subscription.HackleSubscriptionOperations
import io.hackle.sdk.common.subscription.HackleSubscriptionStatus

User user = User.builder(userId)
    .build();

HackleSubscriptionOperations subscriptions = HackleSubscriptionOperations.builder()
    .marketing(HackleSubscriptionStatus.SUBSCRIBED)
    .information(HackleSubscriptionStatus.SUBSCRIBED)
    .build()

hackle.app.updateSmsSubscriptions(subscriptions, user)
```

{% endtab %}
{% endtabs %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.hackle.io/en/development-guide/java-kotlin/user-identifier/java-user-info-crm.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
