Skip to main content
Skip table of contents

Microsoft Advertising

Overview

Configuring an integration between Redpoint Data Management (DM) and Microsoft Advertising (Bing Ads) APIs allows you to create and populate customer match lists. This document contains instructions for generating and refreshing authentication tokens, getting a file upload location from Bing, and creating/populating a customer match list by posting to that file upload location. Bing provides a combination of SOAP and REST endpoints to enable this functionality.

File Modified

File add to customer list.csv

Apr 08, 2024

File new customer list empty.csv

Apr 08, 2024

File new customer list.csv

Apr 08, 2024

Basic Requirements

Each task contained in this document has the following requirements:

Basic Authentication Flow

All requests to the Bing APIs must include an authentication token and a developer token. The developer token is granted by Microsoft. Per Microsoft, “The universal developer token can be used to authenticate with any Microsoft Advertising user credentials. You can use the same universal developer token whether your application will be used by one or multiple Microsoft Advertising users.” Follow these steps (https://learn.microsoft.com/en-us/advertising/guides/get-started?view=bingads-13#get-developer-token ) to request a developer token:

  1. Sign in with Super Admin credentials at the Microsoft Advertising Developer Portal account tab.

  2. Choose the user that you want associated with the developer token. Typically an application only needs one universal token, regardless how many users will be supported.

  3. Click on the Request Token button.

The required authentication token is a short-lived token that must accompany every request to the Bing APIs. Bing APIs employ the OAuth 2.0 flow to generate tokens. Each user must be prompted and provide consent through a web browser control at least once for your application to manage their Microsoft Advertising accounts. The PowerShell script below will…

  1. Make a request for user access.

  2. Redeem the returned code for authentication and refresh tokens.

  3. Use the refresh token to to generate new authentication and refresh tokens.

You can get your client id when you register the application or from your list of applications https://portal.azure.com/#view/Microsoft_AAD_RegisteredApps/ApplicationsListBlade.

POWERSHELL
# Replace the Tutorial Sample App ID with your registered application ID. 
$clientId = "f3fa9b54-9035-46a6-95f5-87410a74c3fc"

Start-Process "https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=$clientId&scope=openid%20profile%20https://ads.microsoft.com/msads.manage%20offline_access&response_type=code&redirect_uri=https://login.microsoftonline.com/common/oauth2/nativeclient&state=ClientStateGoesHere&prompt=login"

$code = Read-Host "Grant consent in the browser, and then enter the response URI here:"
$code = $code -match 'code=(.*)\&'
$code = $Matches[1]

# Get the initial access and refresh tokens. 

$response = Invoke-WebRequest https://login.microsoftonline.com/common/oauth2/v2.0/token -ContentType application/x-www-form-urlencoded -Method POST -Body "client_id=$clientId&scope=https://ads.microsoft.com/msads.manage%20offline_access&code=$code&grant_type=authorization_code&redirect_uri=https%3A%2F%2Flogin.microsoftonline.com%2Fcommon%2Foauth2%2Fnativeclient"

$oauthTokens = ($response.Content | ConvertFrom-Json)  
Write-Output "Access token: " $oauthTokens.access_token  
Write-Output "Access token expires in: " $oauthTokens.expires_in  
Write-Output "Refresh token: " $oauthTokens.refresh_token 

# The access token will expire e.g., after one hour. 
# Use the refresh token to get new access and refresh tokens. 

$response = Invoke-WebRequest https://login.microsoftonline.com/common/oauth2/v2.0/token -ContentType application/x-www-form-urlencoded -Method POST -Body "client_id=$clientId&scope=https://ads.microsoft.com/msads.manage%20offline_access&code=$code&grant_type=refresh_token&refresh_token=$($oauthTokens.refresh_token)"

$oauthTokens = ($response.Content | ConvertFrom-Json)  
Write-Output "Access token: " $oauthTokens.access_token  
Write-Output "Access token expires in: " $oauthTokens.expires_in  
Write-Output "Refresh token: " $oauthTokens.refresh_token

The authentication and refresh tokens can be stored in DM and refreshed when needed.

Refresh Token

Each call to refresh the authentication token will return both a new authentication token as well as a new refresh token to be used in future refresh requests.

Endpoint: https://login.microsoftonline.com/common/oauth2/v2.0/token

Method: POST

Header:

Field

Data Type

Description

Content-Type

string

(Required)

"application/x-www-form-urlencoded".

Parameters:

Field

Data Type

Description

client_id

string

(Required)

The application (client) ID that the Azure portal - App registrations portal assigned your app.

client_secret

string

(Required for web apps)

The application secret that you created in the app registration portal for your app. It should not be used in a native app, because client_secrets cannot be reliably stored on devices. It is required for web apps and web APIs, which have the ability to store the client_secret securely on the server side.

grant_type

string

(Required)

refresh_token

refresh_token

string

(Required)

The refresh_token that you acquired when you requested an access token.

scope

string

(Required)

https://api.ads.microsoft.com/msads.manage%20offline_access

A space-separated list of scopes. The scopes requested in this leg must be equivalent to or a subset of the scopes included when you requested user consent. If the scopes specified in this request span multiple resource servers, then the Microsoft identity platform endpoint will return a token for the resource specified in the first scope. For a more detailed explanation of scopes, refer to permissions, consent, and scopes.

DM Caveat:

The requirement for application/x-www-form-urlencoded means that the field is not created as a JSON object, but as a simple string. The request must be created manually using a Calculate function. See below:

Example DM Field:

JSON
"client_id=" + global.appIDSandbox + " &scope=https://api.ads.microsoft.com/msads.manage%20offline_access&grant_type=refresh_token&refresh_token=" + global.refreshTokenSandbox

Request:

JSON
// Line breaks for legibility only

POST /common/oauth2/v2.0/token HTTP/1.1
Host: https://login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded

client_id=6731de76-14a6-49ae-97bc-6eba6914391e
&scope=https%3A%2F%2Fads.microsoft.com%2Fmsads.manage
&refresh_token=OAAABAAAAiL9Kn2Z27UubvWFPbm0gLWQJVzCTE9UkP3pSx1aXxUjq...
&grant_type=refresh_token
&client_secret=JqQX2PNo9bpM0uEihUPzyrh      // NOTE: Only applicable for web apps

Response:

JSON
{
    "token_type": "Bearer",
    "scope": "https://api.ads.microsoft.com/msads.manage",
    "expires_in": 4104,
    "ext_expires_in": 4104,
    "access_token": "eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkExMjhDQkMtSFMyNTYiLCJ4NXQiOiJlWDZfN25KcHNWTEh0LTAxSkRFaWFWNHpBamMiLCJ6aXAiOiJERUYifQ.OtEpr6G0vy_ToDDUpAvhSz2yeyUKoFyaYhjK_Y8p_HGa5dYnm6BR8bp72sVM_NendS-xb_IkNxuVb0WhQWrNFML_4GllP9fL6bla5K8HLi4R5ZCrxrQ7ud26hyFZvevKpJpL9R4WGsjta14rbREcxuUewyoGEYXa_9JVOv68u9EP7VMVrQAAxeCVZGtkAkySYahZzAsteYhN-GwwSWpJjGAtbo77eiUQpk50LusUlrgsnUDrClzfrI42nY1YtmNn3TlaWVEtuWppbQA7gijl6Qjuxix5nftO2DLIZvzvQmS-fo69Ou9z1BgO2SqI6ExU-GPVTygPHb0xRuGSAc44Xg.UWCKVhQoLYYBdJR3mou9pg.Iyi0DRaw7Z4rs3fw9cdQA0NAFVFfsYi5ej6v5qBA78U9Lh76VfrcAufzjibnLi19KSbKdawAMZh4CytEZqY68RJsVe6siKJm_FiIcG6cuIEBEqGIrf0jt2KlEvOUn3H6Bnz9MmN5hTb24wi-w7QewCpCped4ktTcvjL4A_c9JW-IHL5qblXIHOv6HpNCI24GBwteRD3OzlTxj4IOcSo7dAv8b0PgT9OcpQqz9adkNO9X3hrayTGSPSQjQSr21WI0S5N26jxAiIBtM7VGL_nNqXTSnsDCQMl4M5G1BtieHzpHpOfunArlaEIQcgUVHObSnYZkxMAli2x5MQb369wiZEUzXeABbx-jnAeItsnwQlWSHIJHA99ogZdf1QFYN3wLDSF2XgI1Qs4GKxUw6cvOSgW_tHOXntg6jNoi7224bSuIsJT-WkhxaCrVAcMKEzr8y6E-21gKKWOsoaTFRHmFYZG_VNaUHYRdWs2PC9uovU5nKR29eB2oil0rPU5rp1YA8xiK5g6GWrkI85zhl9zV9hUMpILCSjhlgyKMlAk-cN4hKjhWXU65xu7lsvjtqkBOLHvzudy2FViByLf1dJo0i8W-qZWj1G1Z6DVDozdfI4Yjjiqb_1lony_wxftbKz41UPXJFXMxTWay-7Hc5Jb8jzLQuzltXtT8Xx20u6EngWM92G0K0Uba1LdHxawkprsRzk67xs_75-O-gJ0plrQnJgSaV7RXF8p7YA2I3xbkMEeou3tc6DodfZ8yRmbHS-Rg7eXcJm0X4BVtKn4CrlGpMDqljBsNp6JV5xqQkI6AvpO6jk3-NFKTlrcFxVdmRL8TFCqwLZjCA_qhyYYP7INfYBbE1VPcfMyYP-1leTz23DMZgyWvfUX5ObP7z984tHF0h3kGqJPJR_tVaExFa7k24mHOhc2-zOp9qR0NiWelLkq32xgOU8i60ETlTBT8Tw8QNGcSLGTtSj4IvWm4OWSWuJwBpO7d_1LHYOmRiGWMFczb-Z-3GwQpGwRajJ-tcxK6zoE62KvUly3iXIxkPNTbROXofwOdZKqAeFThfAbDbUddCfyuvYF4rzancCsNMmdOFllYA6CjRUflAmoF8GiKgulnl263ODm1edDmjAajbaWnBGAte1dEzA_WixbB3JwSOieIVn6kLIMYzg7GsxAgwUqwHjWCJ-IzohBE7pm7Qz9Po0XHUcMcIhPHt8LsovQi3wszrdORtkpotdckm2EramRMZiYlfzBbZSUiceNND4NkZb__fUGJKrIMeFizcIAHpt6Lldox5o_EA0zdaqrZkb-W5sjgu_mqMKQaOrU7JLxgz_dpSSudPRlP2Iki89QY.GTyut6DXV2fLKnNeoyVWsg",
    "refresh_token": "M.C100_SN1.-AoQq82eMerUJGGt7fqfJQiO0HzkYe7PkmeDpqZtoX0tgtK3e7Mp0XcGbbSNd1ke3TOQ0wMp6m5vLeJrtKw6yVZ3qY961LMecKx7tzA6LUr3AxizgcGrmRjul!ubmQGJkwbcQOoenbpud633CLzSK1oy1*ZJ6h0XR3dS7ufW8T0klPfp1aJ*Vvd5wxEiUNbzDkzQCMOCFly7TVQJin8u*SMAjdyxJpA*Oh8dNJqujUn3ULvkjD25kMhPMMVTt2Og09NGsFpPXGuAgSfroWcH6qoXt2SEwVNW!D3hG7GIQyYRb0BrqLGsU9qHxxMu09dS*Lzg3j7Wrw8rnvTRXDELmR2vvvBBqi9N8tS4fYGIPU26OEWfhHSaP1blZITKheOhogzCpZ3eQE8Bzx6iMWDVDsRShYAubgCbYv1IdpnutQy*E"
}

Create a Customer Match List

To create a Customer Match List:

  1. First call the Bing API to retrieve a file upload location.

  2. Once you have that, you must then post the CSV file to the file upload location.

  3. Bing will then return a RequestId that can be used to query the status of the file upload until completion.

Get File Upload URL

In order to get the file upload URL, you must make use of Bing’s Bulk Service API Webservice. This webservice utilizes the SOAP protocol, which requires you to manually create the SOAP envelope within DM. The order of the parameters in the SOAP Header and Body must match those below.

Endpoint: https://bulk.api.bingads.microsoft.com/Api/Advertiser/CampaignManagement/v13/BulkService.svc

Method: POST

Header:

Field

Data Type

Description

Content-Type

string

(Required)

"text/xml"

SOAPAction

string

(Required)

"GetBulkUploadUrl"

SOAP Parameters Header:

Field

Data Type

Description

Action

string

(Required)

"GetBulkUploadUrl"

AuthenticationToken

string

(Required)

The access_token that you acquired when you requested an access token.

CustomerAccountId

string

(Required)

The identifier of the ad account that owns or is associated with the entities in the request. This header element must have the same value as the AccountId body.

CustomerId

string

(Required)

The identifier of the manager account (customer) the user is accessing or operating from. A user can have access to multiple manager accounts..

DeveloperToken

string

(Required)

The developer token used to access the Bing Ads API.

SOAP Parameters Body:

Field

Data Type

Description

AccountId

string

(Required)

The identifier of the ad account that owns or is associated with the entities in the request. This body element must have the same value as the CustomerAccountId header.

ResponseMode

string

(Required)

"ErrorsOnly"

Specify whether to return errors and their corresponding data, or only the errors in the results file. The default is ErrorsOnly.

DM Caveat:

The requirement for a SOAP envelope means that the field is not created as a JSON object, but as a simple string containing XML. The request must be created manually using a Calculate function. See below:

Example DM Field:

XML
"<s:Envelope xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">
  <s:Header xmlns=\"https://bingads.microsoft.com/CampaignManagement/v13\">
    <Action mustUnderstand=\"1\">GetBulkUploadUrl</Action>
    <AuthenticationToken i:nil=\"false\">"+global.authToken+"</AuthenticationToken>
    <CustomerAccountId i:nil=\"false\">"+global.accountID+"</CustomerAccountId>
    <CustomerId i:nil=\"false\">"+global.custID+"</CustomerId>
    <DeveloperToken i:nil=\"false\">"+global.devToken+"</DeveloperToken>
  </s:Header>
  <s:Body>
    <GetBulkUploadUrlRequest xmlns=\"https://bingads.microsoft.com/CampaignManagement/v13\">
      <ResponseMode>ErrorsOnly</ResponseMode>
      <AccountId>"+global.accountID+"</AccountId>
    </GetBulkUploadUrlRequest>
  </s:Body>
</s:Envelope>"

Request:

XML
POST /Api/Advertiser/CampaignManagement/v13/BulkService.svc HTTP/1.1
Host: bulk.api.sandbox.bingads.microsoft.com:443
Content-Type: text/xml
SOAPAction: GetBulkUploadUrl
Content-Length: 2614

<s:Envelope xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header xmlns="https://bingads.microsoft.com/CampaignManagement/v13">
    <Action mustUnderstand="1">GetBulkUploadUrl</Action>
    <AuthenticationToken i:nil="false">eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkExMjhDQkMtSFMyNTYiLCJ4NXQiOiJlWDZfN25KcHNWTEh0LTAxSkRFaWFWNHpBamMiLCJ6aXAiOiJERUYifQ.If6F1UbXA1UU9r3KEzXpz919mYx959h_K0CT14srSUAabvLfYhZvUDpJWExQOyU4O8PFW8XfcJmOkc_vVxdUc0RGqbbwplxDYh1sWFUyvzsMX5eKiaBStnC-guEiqVKt90v6LxeKchPraZq7ViM6ho51FEt44FbocZzdW4McsJvNhMSbgSqhHvEH_INaDqkyxyV-R0J1M_QLzWA3na462owNq382GCoGIPrPFqSm4HkK6fTGylvGXy_A8eQIFxMsh2uBCBVPAqtxRBGnGQPLGNkLGKmrzhlL8fGv1dZaVJx-nt67b2Qk81boM1kb1NE-0MoPeF9Fip_VB0I90XTWFw.efog0xI714NkE2JDiTLTjA.RDZCfEmwvg40PtN3epjxC1ptmGNrytZWHPxZ89-gnsBgRGzVf8fJb2fyK6rgh6zE0CLDOMmZarn7xgVKg_wHbgSg3h4jK0_Ad5pLgrEvqXVund1-YkYvjYQ7kEJYNXQEnsYsQc4-ssnG3MNcVy_6KllgVOEeAPh-mvTErF4xe9o8p6qY11qHHG-e3WnwI3ZbDJ_WEKN9Nyyq5HoM6i8UOtXeF4uwrQqIyA5v3jDhwUIXvywjJAdclPaMONxRNNYzbIh_Oc80ZMghHBwEtkuWuLKXR4_-u_0uDvf6VlZ8MoUALzGiAfvEpJEo1qlhkv_A9J8rOWNqbtvyycB-rCrUZo0RnZVx-2WP5MmRQ9p4EJ9rX1je2bK3NNQvEv0x3nLkFNc3lCXaIF_4k3JQOEwqF7i17vtEYTsTO07S7CuXMehsx8a_hzLZNqfPtSpJcLGCffDiA_OmAHTcAUobK6urWATZjcIdWocKPyV2asJ-iFqejVn6FBxaoG4HSwCx3eZr_yE-cprLbz9VFXsMy3AehVjMviOzuNN9EY9jBox3bocSiy8uw6FsYD3sejGPMPRArnN9LNjXquvWzcSiY0UbY__mQOHbKrpApux_hluaRzLDtjWb-2sJfzFatUieHImZpBIA8e9jcQxFcSg9ZqzEr_c5lX1PtYVEuIrTc9DTi9d_xxSr0mws0MElO2-6xutTHPnCQZOZGkMwuj9hWd4D4iUzifDUVz6G0gKGwl5oD0LJnlD5YCklv9HeD05nuphLz7stWZqmNWPWkLZ267eThFiuxI6SqRuQe_7stNz9P2HVfB9d5C0LBL9UAVAUco9eSF7K5wwFgXlAFGl2_qufjUG_iy2xkukQ2oJKsj2ueazvEkkACnefgyUcDfPAtJiXNPW2uYbmgLXcLfLZ1m5YM5ytOfduSYYgsGijtazU_l9YSa3xRfBlwF7r9ICC4s3EFoy7Z_0iOWHa0QxNMyfu-LRvmTv1N08YCXaAD7FA3XN3vbrvhrLCp5EBt1GX-F7R6Cz5x2WcVPdynkSlg9dEH8EQ2cYU9OfhoVBMcW84zaoxMWiqykAF8c0--1hK0_0EK9PDRwojvLD5OKAUnqDFhBSRfFSlcNadmbyyEwurbNZxsD9fidfxgggLnlhM-w389tNaWum-K3x1Oi3oOpB0HaSELigKfNUKUbXSbCK31H_ehyVjgXjaceZNqph9WU-HdyxsP05zuD3GPSwYXL3GzyBZG0Jr3AWXozavJKT-KJ42Nug2HSe8zt5tiVLdnWaL8bGmHzagBFx5LV5CWURgOQxvcfp3bL5Nl7HgMyGTMH1w8Uu8YhJwnkoZwosuk4uE.2k1fGeI4Q8YUzFXe-rVCPw</AuthenticationToken>
    <CustomerAccountId i:nil="false">279426368</CustomerAccountId>
    <CustomerId i:nil="false">330031209</CustomerId>
    <DeveloperToken i:nil="false">BBD37VB98</DeveloperToken>
  </s:Header>
  <s:Body>
    <GetBulkUploadUrlRequest xmlns="https://bingads.microsoft.com/CampaignManagement/v13">
      <ResponseMode>ErrorsOnly</ResponseMode>
      <AccountId>279426368</AccountId>
    </GetBulkUploadUrlRequest>
  </s:Body>
</s:Envelope>

Response:

XML
<Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
	<Header>
		<TrackingId xmlns:h="https://bingads.microsoft.com/CampaignManagement/v13">
			4e66a06c-a95d-478d-b86c-4bdd2e734f24
		</TrackingId>
	</Header>
	<Body>
		<GetBulkUploadUrlResponse xmlns="https://bingads.microsoft.com/CampaignManagement/v13">
			<RequestId>
				e19e4ef3-20f3-4f2e-944c-a20e8b399a3f
			</RequestId>
			<UploadUrl>
				https://fileupload.api.sandbox.bingads.microsoft.com/Api/Advertiser/CampaignManagement/FileUpload/File/UploadBulkFile/e19e4ef3-20f3-4f2e-944c-a20e8b399a3f?Ver=13
			</UploadUrl>
		</GetBulkUploadUrlResponse>
	</Body>
</Envelope>

Upload Customer Match List File

Once obtained, you can post a customer match list file to the UploadUrl. Note that the UploadUrl is not a SOAP endpoint, but it does contain multipart/form-data that must be manually created.

Endpoint: UploadUrl

Method: POST

Header:

Field

Data Type

Description

AuthenticationToken

string

(Required)

The access_token that you acquired when you requested an access token.

AccountId

string

(Required)

The identifier of the ad account that owns or is associated with the entities in the request.

CustomerId

string

(Required)

The identifier of the manager account (customer) the user is accessing or operating from. A user can have access to multiple manager accounts..

DeveloperToken

string

(Required)

The developer token used to access the Bing Ads API.

Content-Type

string

"multipart/form-data"

Parameters:

The following parameters must be included in the request body in the form-data format.

Field

Data Type

Description

AuthenticationToken

string

(Required)

The access_token that you acquired when you requested an access token.

DM Caveat:

The requirement for multipart/form-data and a file upload presents a difficulty for DM. The request must be created manually using a Calculate function after consuming the customer file. We must define a form-data boundary, the request content type, including the boundary, and the request itself. See below:

Field: boundary

Expression:

CODE
"0ebd3"

Field: contentType

Expression:

CODE
"multipart/form-data; boundary=" + boundary

Field: request

Expression:

CODE
"--" + boundary + "
Content-Disposition: form-data; name=\"file\"; filename=\"file:///C:/Dev/bing ads/new to customer list.csv\"
Content-Type: text/plain

"+ DecodeTextBytes(contents,"UTF8") +"
--" + boundary + "--"

When run through a DM web service with the request field assigned to the Body field, this will produce a payload that contains contents of the file located at filename.

Request:

CODE
POST /Api/Advertiser/CampaignManagement/FileUpload/File/UploadBulkFile/e19e4ef3-20f3-4f2e-944c-a20e8b399a3f?Ver=13 HTTP/1.1
Host: fileupload.api.sandbox.bingads.microsoft.com:443
AuthenticationToken: eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkExMjhDQkMtSFMyNTYiLCJ4NXQiOiJlWDZfN25KcHNWTEh0LTAxSkRFaWFWNHpBamMiLCJ6aXAiOiJERUYifQ.If6F1UbXA1UU9r3KEzXpz919mYx959h_K0CT14srSUAabvLfYhZvUDpJWExQOyU4O8PFW8XfcJmOkc_vVxdUc0RGqbbwplxDYh1sWFUyvzsMX5eKiaBStnC-guEiqVKt90v6LxeKchPraZq7ViM6ho51FEt44FbocZzdW4McsJvNhMSbgSqhHvEH_INaDqkyxyV-R0J1M_QLzWA3na462owNq382GCoGIPrPFqSm4HkK6fTGylvGXy_A8eQIFxMsh2uBCBVPAqtxRBGnGQPLGNkLGKmrzhlL8fGv1dZaVJx-nt67b2Qk81boM1kb1NE-0MoPeF9Fip_VB0I90XTWFw.efog0xI714NkE2JDiTLTjA.RDZCfEmwvg40PtN3epjxC1ptmGNrytZWHPxZ89-gnsBgRGzVf8fJb2fyK6rgh6zE0CLDOMmZarn7xgVKg_wHbgSg3h4jK0_Ad5pLgrEvqXVund1-YkYvjYQ7kEJYNXQEnsYsQc4-ssnG3MNcVy_6KllgVOEeAPh-mvTErF4xe9o8p6qY11qHHG-e3WnwI3ZbDJ_WEKN9Nyyq5HoM6i8UOtXeF4uwrQqIyA5v3jDhwUIXvywjJAdclPaMONxRNNYzbIh_Oc80ZMghHBwEtkuWuLKXR4_-u_0uDvf6VlZ8MoUALzGiAfvEpJEo1qlhkv_A9J8rOWNqbtvyycB-rCrUZo0RnZVx-2WP5MmRQ9p4EJ9rX1je2bK3NNQvEv0x3nLkFNc3lCXaIF_4k3JQOEwqF7i17vtEYTsTO07S7CuXMehsx8a_hzLZNqfPtSpJcLGCffDiA_OmAHTcAUobK6urWATZjcIdWocKPyV2asJ-iFqejVn6FBxaoG4HSwCx3eZr_yE-cprLbz9VFXsMy3AehVjMviOzuNN9EY9jBox3bocSiy8uw6FsYD3sejGPMPRArnN9LNjXquvWzcSiY0UbY__mQOHbKrpApux_hluaRzLDtjWb-2sJfzFatUieHImZpBIA8e9jcQxFcSg9ZqzEr_c5lX1PtYVEuIrTc9DTi9d_xxSr0mws0MElO2-6xutTHPnCQZOZGkMwuj9hWd4D4iUzifDUVz6G0gKGwl5oD0LJnlD5YCklv9HeD05nuphLz7stWZqmNWPWkLZ267eThFiuxI6SqRuQe_7stNz9P2HVfB9d5C0LBL9UAVAUco9eSF7K5wwFgXlAFGl2_qufjUG_iy2xkukQ2oJKsj2ueazvEkkACnefgyUcDfPAtJiXNPW2uYbmgLXcLfLZ1m5YM5ytOfduSYYgsGijtazU_l9YSa3xRfBlwF7r9ICC4s3EFoy7Z_0iOWHa0QxNMyfu-LRvmTv1N08YCXaAD7FA3XN3vbrvhrLCp5EBt1GX-F7R6Cz5x2WcVPdynkSlg9dEH8EQ2cYU9OfhoVBMcW84zaoxMWiqykAF8c0--1hK0_0EK9PDRwojvLD5OKAUnqDFhBSRfFSlcNadmbyyEwurbNZxsD9fidfxgggLnlhM-w389tNaWum-K3x1Oi3oOpB0HaSELigKfNUKUbXSbCK31H_ehyVjgXjaceZNqph9WU-HdyxsP05zuD3GPSwYXL3GzyBZG0Jr3AWXozavJKT-KJ42Nug2HSe8zt5tiVLdnWaL8bGmHzagBFx5LV5CWURgOQxvcfp3bL5Nl7HgMyGTMH1w8Uu8YhJwnkoZwosuk4uE.2k1fGeI4Q8YUzFXe-rVCPw
DeveloperToken: BBD37VB98
CustomerId: 330031209
AccountId: 279426368
Content-Type: multipart/form-data; boundary=0ebd3
Content-Length: 56207

--0ebd3
Content-Disposition: form-data; name="file"; filename="file:///C:/Dev/bing ads/new to customer list.csv"
Content-Type: text/plain

Type,Status,Id,Parent Id,Client Id,Modified Time,Name,Description,Scope,Audience,Action Type,Sub Type,Text
Format Version,,,,,,6,,,,,,
Customer List,Active,-10,,ClientIdGoesHere,,,An audience created with a demo with Dan,Customer,Demo with Dan,Add,,
Customer List Item,,,-10,ClientIdGoesHere,,,,,,,Email,2A9A9F735262755E1A3B6DADD35F8D6ED7FE971D9F38D788D52802AD2BA3645A
Customer List Item,,,-10,ClientIdGoesHere,,,,,,,Email,1AAC4498AC887EA12E1A5E8090206726138D7C0648D503002BC04DB50D23C099
Customer List Item,,,-10,ClientIdGoesHere,,,,,,,Email,5EC35D133C6149707AA5EC6940CCC2623783AC8479F0098070A11502EABB8C2A
Customer List Item,,,-10,ClientIdGoesHere,,,,,,,Email,2BDC4DC9F113FD9D1CB1E4FD7E45E602279F2E0EA5FF7F613978471DEB98DB03

--0ebd3--

A successful response will include a body containing a RequestId. This RequestId can be used in subsequent queries to check on the status of the file upload.

Response:

CODE
{
  "TrackingId":"3debbca9-3175-408d-8ec8-592fb05eb23a",
  "RequestId":"e19e4ef3-20f3-4f2e-944c-a20e8b399a3f"
}

Get Upload Status

If you want to monitor the progress of a customer match list file upload, you can use the RequestId to query the Bing API for the upload status. Once again, this is a SOAP endpoint, so the SOAP envelope must be generated manually.

Endpoint: https://bulk.api.bingads.microsoft.com/Api/Advertiser/CampaignManagement/v13/BulkService.svc

Method: POST

Header:

Field

Data Type

Description

Content-Type

string

(Required)

"text/xml".

SOAPAction

string

(Required)

"GetBulkUploadStatus"

SOAP Parameters Header:

Field

Data Type

Description

Action

string

(Required)

"GetBulkUploadStatus"

AuthenticationToken

string

(Required)

The access_token that you acquired when you requested an access token.

CustomerAccountId

string

(Required)

The identifier of the ad account that owns or is associated with the entities in the request. This header element must have the same value as the AccountId body.

CustomerId

string

(Required)

The identifier of the manager account (customer) the user is accessing or operating from. A user can have access to multiple manager accounts..

DeveloperToken

string

The developer token used to access the Bing Ads API.

SOAP Parameters Body:

Field

Data Type

Description

RequestId

string

(Required)

The identifier returned from the POST to upload the file.

Example DM Field:

XML
"<s:Envelope xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">
  <s:Header xmlns=\"https://bingads.microsoft.com/CampaignManagement/v13\">
    <Action mustUnderstand=\"1\">GetBulkUploadStatus</Action>
    <AuthenticationToken i:nil=\"false\">"+global.authToken+"</AuthenticationToken>
    <CustomerAccountId i:nil=\"false\">"+global.accountIDSandbox+"</CustomerAccountId>
    <CustomerId i:nil=\"false\">"+global.custID+"</CustomerId>
    <DeveloperToken i:nil=\"false\">"+global.devToken+"</DeveloperToken>
  </s:Header>
  <s:Body>
    <GetBulkUploadStatusRequest xmlns=\"https://bingads.microsoft.com/CampaignManagement/v13\">
      <RequestId i:nil=\"false\">"+global.uploadStatusRequestID+"</RequestId>
    </GetBulkUploadStatusRequest>
  </s:Body>
</s:Envelope>"

Request:

XML
POST /Api/Advertiser/CampaignManagement/v13/BulkService.svc HTTP/1.1
Host: bulk.api.sandbox.bingads.microsoft.com:443
Content-Type: text/xml
SOAPAction: GetBulkUploadStatus
Content-Length: 2617

<s:Envelope xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header xmlns="https://bingads.microsoft.com/CampaignManagement/v13">
    <Action mustUnderstand="1">GetBulkUploadStatus</Action>
    <AuthenticationToken i:nil="false">eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkExMjhDQkMtSFMyNTYiLCJ4NXQiOiJlWDZfN25KcHNWTEh0LTAxSkRFaWFWNHpBamMiLCJ6aXAiOiJERUYifQ.If6F1UbXA1UU9r3KEzXpz919mYx959h_K0CT14srSUAabvLfYhZvUDpJWExQOyU4O8PFW8XfcJmOkc_vVxdUc0RGqbbwplxDYh1sWFUyvzsMX5eKiaBStnC-guEiqVKt90v6LxeKchPraZq7ViM6ho51FEt44FbocZzdW4McsJvNhMSbgSqhHvEH_INaDqkyxyV-R0J1M_QLzWA3na462owNq382GCoGIPrPFqSm4HkK6fTGylvGXy_A8eQIFxMsh2uBCBVPAqtxRBGnGQPLGNkLGKmrzhlL8fGv1dZaVJx-nt67b2Qk81boM1kb1NE-0MoPeF9Fip_VB0I90XTWFw.efog0xI714NkE2JDiTLTjA.RDZCfEmwvg40PtN3epjxC1ptmGNrytZWHPxZ89-gnsBgRGzVf8fJb2fyK6rgh6zE0CLDOMmZarn7xgVKg_wHbgSg3h4jK0_Ad5pLgrEvqXVund1-YkYvjYQ7kEJYNXQEnsYsQc4-ssnG3MNcVy_6KllgVOEeAPh-mvTErF4xe9o8p6qY11qHHG-e3WnwI3ZbDJ_WEKN9Nyyq5HoM6i8UOtXeF4uwrQqIyA5v3jDhwUIXvywjJAdclPaMONxRNNYzbIh_Oc80ZMghHBwEtkuWuLKXR4_-u_0uDvf6VlZ8MoUALzGiAfvEpJEo1qlhkv_A9J8rOWNqbtvyycB-rCrUZo0RnZVx-2WP5MmRQ9p4EJ9rX1je2bK3NNQvEv0x3nLkFNc3lCXaIF_4k3JQOEwqF7i17vtEYTsTO07S7CuXMehsx8a_hzLZNqfPtSpJcLGCffDiA_OmAHTcAUobK6urWATZjcIdWocKPyV2asJ-iFqejVn6FBxaoG4HSwCx3eZr_yE-cprLbz9VFXsMy3AehVjMviOzuNN9EY9jBox3bocSiy8uw6FsYD3sejGPMPRArnN9LNjXquvWzcSiY0UbY__mQOHbKrpApux_hluaRzLDtjWb-2sJfzFatUieHImZpBIA8e9jcQxFcSg9ZqzEr_c5lX1PtYVEuIrTc9DTi9d_xxSr0mws0MElO2-6xutTHPnCQZOZGkMwuj9hWd4D4iUzifDUVz6G0gKGwl5oD0LJnlD5YCklv9HeD05nuphLz7stWZqmNWPWkLZ267eThFiuxI6SqRuQe_7stNz9P2HVfB9d5C0LBL9UAVAUco9eSF7K5wwFgXlAFGl2_qufjUG_iy2xkukQ2oJKsj2ueazvEkkACnefgyUcDfPAtJiXNPW2uYbmgLXcLfLZ1m5YM5ytOfduSYYgsGijtazU_l9YSa3xRfBlwF7r9ICC4s3EFoy7Z_0iOWHa0QxNMyfu-LRvmTv1N08YCXaAD7FA3XN3vbrvhrLCp5EBt1GX-F7R6Cz5x2WcVPdynkSlg9dEH8EQ2cYU9OfhoVBMcW84zaoxMWiqykAF8c0--1hK0_0EK9PDRwojvLD5OKAUnqDFhBSRfFSlcNadmbyyEwurbNZxsD9fidfxgggLnlhM-w389tNaWum-K3x1Oi3oOpB0HaSELigKfNUKUbXSbCK31H_ehyVjgXjaceZNqph9WU-HdyxsP05zuD3GPSwYXL3GzyBZG0Jr3AWXozavJKT-KJ42Nug2HSe8zt5tiVLdnWaL8bGmHzagBFx5LV5CWURgOQxvcfp3bL5Nl7HgMyGTMH1w8Uu8YhJwnkoZwosuk4uE.2k1fGeI4Q8YUzFXe-rVCPw</AuthenticationToken>
    <CustomerAccountId i:nil="false">279426368</CustomerAccountId>
    <CustomerId i:nil="false">330031209</CustomerId>
    <DeveloperToken i:nil="false">BBD37VB98</DeveloperToken>
  </s:Header>
  <s:Body>
    <GetBulkUploadStatusRequest xmlns="https://bingads.microsoft.com/CampaignManagement/v13">
      <RequestId i:nil="false">e19e4ef3-20f3-4f2e-944c-a20e8b399a3f</RequestId>
    </GetBulkUploadStatusRequest>
  </s:Body>
</s:Envelope>

Response:

XML
<Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
	<Header>
		<TrackingId xmlns:h="https://bingads.microsoft.com/CampaignManagement/v13">
			9ce078d4-52fe-4b9e-b559-440bb5e860f6
		</TrackingId>
	</Header>
	<Body>
		<GetBulkUploadStatusResponse xmlns="https://bingads.microsoft.com/CampaignManagement/v13">
			<Errors i:nil="true" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" />
			<ForwardCompatibilityMap xmlns:a="http://schemas.datacontract.org/2004/07/System.Collections.Generic" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" />
			<PercentComplete>
				100
			</PercentComplete>
			<RequestStatus>
				Completed
			</RequestStatus>
			<ResultFileUrl>
				https://bingadsappsstoragesi.blob.core.windows.net:443/bulkuploadresultfiles/d1c80c9c-0e75-440d-a58e-33f97eb8af6e.zip?sv=2018-03-28&amp;sr=b&amp;sig=Bsj9UC8zb5%2BUZyS%2B8wj3mLYmt7pDWQ3pkIrUVKd3wdE%3D&amp;st=2023-11-13T19%3A57%3A16Z&amp;se=2023-11-13T20%3A22%3A16Z&amp;sp=rl
			</ResultFileUrl>
		</GetBulkUploadStatusResponse>
	</Body>
</Envelope>

Customer Match List File

Bing relies on the use of customer match list files to both create new Customer Match Lists and to add emails to the lists (which Bing refers to as Customer Match List items). A single file can both create a new list as well as add emails to it. The list is sent to the same File Upload URL endpoint referenced earlier. Due to this, the format of the file is confusing.

  • The first row of the file contains the column headers. Subsequent rows populate a subset of these columns.

  • The second row declares the Format Version of the file. This tells Bing which API version to parse the file with. At this point, the only valid value is 6.0.

  • The third row defines the Customer List to be acted upon. The ID column must either match an existing Customer Match List, or contain a negative number (which indicates the API should create a new Customer Match List).

  • All subsequent rows contain hashed emails and indicate which Customer List they should be added to by setting the Parent Id column.

See below for an example CSV with headers and first three defining rows:

CODE
Type,Status,Id,Parent Id,Client Id,Modified Time,Name,Description,Scope,Audience,Action Type,Sub Type,Text
Format Version,,,,,,6.0,,,,,,
Customer List,Active,-10,,ClientIdGoesHere,,,New customer list description,Customer,New Customer List,Add,,
Customer List Item,,,-10,ClientIdGoesHere,,,,,,,Email,HashedValue

See below for example CSV files that…

  • Define a new customer list and add emails to it

  • Define a new empty customer list

  • Add emails to an existing customer list

File Modified

File add to customer list.csv

Apr 08, 2024

File new customer list empty.csv

Apr 08, 2024

File new customer list.csv

Apr 08, 2024

new customer list.csv new customer list empty.csv add to customer list.csv

File Column Headers

Type

Determines what object the given row is defining. For our purposes, this will be one of the following:

  • Format Version

  • Customer List

  • Customer List Item

Add: Required.
Update: Required.
Delete: Required.

Status

The customer list status. Possible values are Active or Deleted.

Add: Optional. The default value is Active.
Update: Read-only.
Delete: Required. The Status must be set to Deleted.

Id

The system-generated identifier of the customer list.

Add: Optional. You must either leave this field empty, or specify a negative identifier. A negative identifier set for the customer list can then be referenced in the Parent Id field of dependent record types such as customer list item. This is required if you are adding a new customer list and new customer list items in the same Bulk file. For more information, see Bulk File Schema Reference Keys.
Update: Read-only and Required.
Delete: Read-only and Required.

Parent Id

The identifier of the parent customer list audience. You must specify either the Parent Id or Audience field.

Add: Read-only and Required. You must either specify an existing customer list identifier, or specify a negative identifier that is equal to the Id field of the parent Customer List record. This is required if you are adding new customer list items to a new customer list in the same Bulk file. For more information, see Bulk File Schema Reference Keys.
Delete: Required.

Client Id

Used to associate records in the bulk upload file with records in the results file. The value of this field is not used or stored by the server; it is simply copied from the uploaded record to the corresponding result record. It may be any valid string to up 100 in length.

Add: Optional.
Update: Optional.
Delete: Read-only.

Modified Time

The date and time that the entity was last updated. The value is in Coordinated Universal Time (UTC).

The date and time value reflects the date and time at the server, not the client. For information about the format of the date and time, see the dateTime entry in Primitive XML Data Types.

Add: Read-only.
Update: Read-only.
Delete: Read-only.

Name

Used to define the Format Version. Only supports 6.0.

Add: Required.
Update: Required.
Delete: Required.

Description

The description of the customer list. Use a description to help you remember what audience you are targeting with this customer list. The description can contain a maximum of 1,024 characters.

Add: Optional.
Update: Optional. If no value is set for the update, this setting is not changed. If you set this field to the delete_value string, the prior setting is removed.
Delete: Read-only.

Scope

Scope defines what accounts can use this customer list. For a customer list the only supported scope is Customer, and the customer list can be associated with any campaigns and ad groups across all of the customer's accounts.

Add: Required.
Update: Read-only. You cannot change the scope.
Delete: Read-only.

Audience

The name of the customer list. The name can contain a maximum of 128 characters.

Add: Required.
Update: Optional. If no value is set for the update, this setting is not changed.
Delete: Read-only.

Action Type

Determines whether to add, remove, or replace the Customer List Item records that you include in the same Bulk upload file.

  • If the action type is Add, the service will attempt to add the Customer List Item records that you include in the same Bulk upload file.

  • If the action type is set to Remove, the service will attempt to remove the Customer List Item records that you include in the same Bulk upload file.

  • If the action type is set to Replace, all previous customer match data for this list will be removed, and the service will attempt to add the Customer List Item records that you include in the same Bulk upload file.

Add: Optional. By default the Add action type is used for new customer lists. Whether or not you set a value, this field is ignored for new customer lists.
Update: Required if you are also including Customer List Item records for an existing audience in the same Bulk upload file; otherwise, this field is optional.
Delete: Read-only.

Sub Type

Determines whether the Text field represents a hashed Email value. Currently the only supported value is Email.

Add: Required.
Delete: Required.

Text

The hashed Email as text.

If the Sub Type is Email, this field cannot contain plain text. The string must be hashed using the SHA-256 algorithm. The hashed Email must be a hexadecimal string of length 64. For example, you must upload a hashed string such as f25ad364d33972379a7a4f4df33db142205f5c40eb19cfdb2fc5aaf117e10101 instead of test@contoso.com.

Add: Required.
Delete: Required.

Notes on Customer List File

Before you can upload customer list data via Bulk API, you must first create one customer list audience and accept the terms and conditions in the Microsoft Advertising UI. The initial customer list doesn't need to contain any customer data, but you must select I ACCEPT. By selecting I ACCEPT you (1) agree that you are able to lawfully disclose audience details, which is personal data, to Microsoft and (2) accept the Customer Match Terms, the Microsoft Advertising Agreement, and the Microsoft Advertising policies. Microsoft will use the data that you upload in accordance with the Customer Match Terms.

Upload Best Practices

  • Large files can degrade the upload performance. It is optional, but recommended that the file be compressed for upload. If compressed, it must be formatted as ZIP with the corresponding extension. The file size limit for upload in production is 100MB and up to 4 million rows. For Sandbox the limit is 20K rows. If you can limit concurrent uploads per customer below 5 or 6, then consider splitting the file rather than approaching the file size limit.

  • The list should have at least 300 active email users if being used for targeting across both the Microsoft Search Network and Microsoft Audience Network.

  • Limit concurrent uploads to 5 or 6 per customer to upload files in parallel. Wait on each thread until the previous file was processed, and then you can reuse the thread to upload another file. For example, one thread can upload a file and after the upload status is either Completed, CompletedWithErrors, or Failed that thread can upload another file.

  • Upload only the entities and fields that you are adding or updating. If supplied, read-only fields such as bid suggestions and quality score data will be ignored.

  • Upload one entity type per file to maximize performance. There are some exceptions; for example, when creating new campaigns, ads, and keywords, it can be more efficient to upload them together with reference keys. As another example, if you are only updating 10 campaigns, 500 ads, and 800 keywords, then you can include them in one upload rather than splitting uploads per type.

  • Consider whether you need to request errors and results (ResponseMode = ErrorsAndResults) in the upload results file, or whether errors only (ResponseMode = ErrorsOnly) will suffice. Consider whether or not you should synchronize the results with your local data. For example, if you are updating entities, you might only need to know whether any errors occurred, and in that case you can specify ResponseMode = ErrorsOnly in the GetBulkUploadUrl request. If you are adding new entities, then you can specify ResponseMode = ErrorsAndResults in the GetBulkUploadUrl request to receive the resulting entity identifiers.

  • For partial retry attempts, do not upload the entire file if only a subset of the records resulted in errors. Only upload the records that you want to retry.

  • Do not retry until the upload status is either Completed, CompletedWithErrors, or Failed. If by chance performance does not meet expectations, please wait for the result anyway.

  • Poll for upload results at reasonable intervals. Initially you should wait one minute for every 10K rows uploaded. After the initial wait time, consider polling in one minute intervals.

For further reading:

JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.