# Dynamics 365: create or update record

The **Dynamics 365: create or update record** Point template upserts one Dataverse row: it matches on an alternate key column, updates the row when the value is already there and creates it when it isn't.

Dataverse has no static API key, so this point authenticates through an Entra ID application registered once for the whole account — there's no token field on the point itself.

## Before you start

Register an application in Entra ID and connect it under **Settings > 3rd-party integrations > Microsoft Dynamics 365**:

1. In the [Microsoft Entra admin center](https://entra.microsoft.com), register an application and create a client secret for it.
2. In the **Power Platform admin center**, open your target environment, add the application as an **Application user**, and assign it a security role that can create and update rows on the table you plan to write to.
3. In Pushwoosh, in **Environment URL**, enter the environment's URL with `https://` and no trailing path, for example `https://acme.crm4.dynamics.com`.
4. In **Directory (tenant) ID** and **Application (client) ID**, enter the application's IDs from its Entra ID overview page.
5. In **Client secret**, paste the secret's value. It's stored write-only: Pushwoosh never shows it again, so paste a new one to replace it.
6. Click **Connect Dynamics 365**.

<Aside type="note">
The alternate key you plan to match on has to already exist on the table in Dataverse. Set it up in the Power Platform admin center (or in your solution) first — the point can't create one for you.
</Aside>

## Configure the point

1. Drag **Dynamics 365: create or update record** from the **Integrations** section of the left panel onto the canvas.
2. Double-click the point and enter a **Step Name**.
3. In **Environment host**, enter the same environment's host without `https://`, for example `acme.crm4.dynamics.com`.
4. In **Table**, enter the entity set name, plural — `contacts`, `leads`, or a custom table's set name.
5. In **Alternate key column**, enter the column covered by an alternate key on that table, for example `pw_hwid`.
6. In **Alternate key value**, enter the value to match on, usually a macro like `{{device:hwid}}`. Avoid values with quotes, since the value goes into the request URL.
7. In **Columns**, add the column name mapped to the value to write — see [key/value fields](/product/customer-journey/journey-elements/integrations/#configuring-list-and-keyvalue-fields).
8. Click **Save**.

Unlike Salesforce: create or update record, this point doesn't return the row's ID into a traveler attribute. If a later step needs it, look the row up again by the same alternate key value.

## Reading a failed request

Open [Calls log](/product/customer-journey/journey-elements/channels/webhook/#calls-log) in the point's drawer and check the response:

* **401** — the connection's client secret was rejected or has expired; reconnect under **Settings > 3rd-party integrations**.
* **403** — the application user's security role doesn't grant create or update access on that table.
* **404** — **Environment host** or **Table** doesn't match anything in that environment.
* **400** — **Alternate key column** isn't defined as an alternate key on that table, or a name in **Columns** isn't a real column.

A failed request drops the traveler from the journey — see [Errors and failed requests](/product/customer-journey/journey-elements/integrations/#errors-and-failed-requests).