Marketing Cloud REST API: OAuth 2.0 authentication and writing to a Data Extension

Create the Installed Package, get a server-to-server OAuth 2.0 token, reuse the token and write rows to a Data Extension through the REST API.

Brown Tutorial Marketing Cloud Engagement 3 min Published

Integrating an external system with Marketing Cloud Engagement always starts with the same step: getting an access token. This tutorial covers server-to-server authentication (OAuth 2.0, client credentials) and a first real use case: writing rows to a Data Extension.

1. Installed Package

In Setup → Apps → Installed Packages:

  1. Click New and give it a name (e.g. "ERP integration").
  2. Add Component → API Integration → Server-to-Server.
  3. Select only the permissions the integration needs. To write to Data Extensions: Data → Data Extensions: Read and Write.
  4. Save and note down the Client Id, Client Secret, Authentication Base URI and REST Base URI.

2. Requesting the token

Terminal
curl -X POST "https://YOUR_SUBDOMAIN.auth.marketingcloudapis.com/v2/token" \
  -H "Content-Type: application/json" \
  -d '{
    "grant_type": "client_credentials",
    "client_id": "YOUR_CLIENT_ID",
    "client_secret": "YOUR_CLIENT_SECRET",
    "account_id": "BUSINESS_UNIT_MID"
  }'
  • account_id is the MID of the Business Unit you want to act in. Without it, the token applies to the package's Business Unit.
  • The subdomain is the same one that appears in the package's Authentication Base URI.

The response:

JSON
{
  "access_token": "eyJhbGciOi...",
  "token_type": "Bearer",
  "expires_in": 1079,
  "scope": "data_extensions_read data_extensions_write",
  "rest_instance_url": "https://YOUR_SUBDOMAIN.rest.marketingcloudapis.com/",
  "soap_instance_url": "https://YOUR_SUBDOMAIN.soap.marketingcloudapis.com/"
}

3. Reuse the token

The token is valid for about 18 minutes (expires_in, in seconds). Requesting a new token on every call is the most common mistake: it slows the integration down and can run into request limits.

The right pattern:

  1. store the access_token and the time it expires;
  2. reuse it while more than a minute or two is left before it expires;
  3. request a new one only when it is close to expiring, or when a call returns 401.

Always use the rest_instance_url from the response for the following calls.

4. Writing to a Data Extension

The row upsert endpoint uses the Data Extension's external key:

Terminal
curl -X POST "https://YOUR_SUBDOMAIN.rest.marketingcloudapis.com/hub/v1/dataevents/key:ORDERS_API/rowset" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '[
    {
      "keys":   { "Number": "10021" },
      "values": { "Email": "ana@example.com", "Amount": "189.90", "Status": "Shipped" }
    }
  ]'
  • keys carries the primary key columns; values, the rest.
  • If a row with that key already exists, it is updated; if not, it is created.
  • Send several rows in the same array instead of one call per row.

Common errors

Response Likely cause
401 on the token Wrong Client Id or Secret, or a subdomain from another account
401 on a call Expired token: request a new one
403 The package lacks the permission for that operation, or account_id points to a Business Unit without access
404 on the rowset Wrong Data Extension external key (it is not the name)

Summary

A server-to-server Installed Package, a token reused until it is close to expiring, and the rest_instance_url from the response: with that, any Marketing Cloud integration is stable. The /hub/v1/dataevents upsert is the most direct way to keep a Data Extension in sync with another system.

Related

Related
Title Type Platform Belt Reading
Transactional Messaging API: real-time transactional email in Marketing Cloud Tutorial Marketing Cloud Engagement Brown 3 min
AttributeValue and empty fields: AMPscript personalization that never breaks a send Tutorial Marketing Cloud Engagement White 3 min
How to use LookupRows in AMPscript (and when to switch to Lookup or LookupOrderedRows) Tutorial Marketing Cloud Engagement Yellow 3 min
Data Views in SQL: who opened or clicked in the last 30 days Tutorial Marketing Cloud Engagement Green 3 min