<div id='api_jvgfgdahvgoc' class='api_div' data-search-keywords='retrieve banners for a user external_user_id app_id app_version placements banners home_hero id placement_id is_control is_test_send expires_at properties headline type value cta_label sidebar_promo'>
<h1 id="retrieve-banners-for-a-user">Retrieve Banners for a user</h1>
<div class="api_type"><div class="method post ">post</div>
<p>/v1/device-messaging/banners/sync</p>
</div>

<p><strong>Important:</strong></p>

<p>This page is in beta. Features and documentation for the Device Messaging API are subject to change.</p>

<blockquote>
  <p>Use this endpoint to retrieve the eligible Banner for each requested placement for a user.</p>
</blockquote>

<p>The response contains structured Banner properties that you can use to build a custom interface. It doesn’t contain rendered HTML.</p>

<h2 id="prerequisites">Prerequisites</h2>

<p>To use this endpoint, you need the following:</p>

<ul>
  <li>A workspace with Banners enabled</li>
  <li>A <a href="/docs/api/device_messaging_api/authentication">client-side REST API key</a> with the <code class="language-plaintext highlighter-rouge">banners.sync</code> permission</li>
  <li>The <a href="/docs/api/basics#endpoints">REST endpoint</a> for your Braze instance</li>
</ul>

<p>Include the client-side REST API key in the <code class="language-plaintext highlighter-rouge">Authorization</code> header as a bearer token.</p>

<h2 id="rate-limit">Rate limit</h2>

<p>Rate limits apply per workspace. If you exceed the rate limit, Braze returns a <code class="language-plaintext highlighter-rouge">429</code> status code. When available, use the <code class="language-plaintext highlighter-rouge">X-RateLimit-Limit</code>, <code class="language-plaintext highlighter-rouge">X-RateLimit-Remaining</code>, and <code class="language-plaintext highlighter-rouge">X-RateLimit-Reset</code> response headers to monitor your usage.</p>

<p>For more information, see <a href="/docs/api/device_messaging_api/rate_limits">Device Messaging API rate limits</a>.</p>

<h2 id="request-body">Request body</h2>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
</pre></td><td class="rouge-code"><pre><span class="p">{</span><span class="w">
  </span><span class="nl">"external_user_id"</span><span class="p">:</span><span class="w"> </span><span class="s2">"{EXTERNAL_USER_ID}"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"app_id"</span><span class="p">:</span><span class="w"> </span><span class="s2">"{APP_API_IDENTIFIER}"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"app_version"</span><span class="p">:</span><span class="w"> </span><span class="s2">"1.0.0"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"placements"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
    </span><span class="s2">"home_hero"</span><span class="p">,</span><span class="w">
    </span><span class="s2">"sidebar_promo"</span><span class="w">
  </span><span class="p">]</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></pre></td></tr></tbody></table></code></pre></div></div>

<h2 id="request-parameters">Request parameters</h2>

<table class="reset-td-br-1 reset-td-br-2 reset-td-br-3 reset-td-br-4 reset-td-br-5" aria-label="Request parameters">
  <thead>
    <tr>
      <th>Parameter</th>
      <th>Required</th>
      <th>Data type</th>
      <th>Description</th>
      <th>Example</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">external_user_id</code></td>
      <td>Required</td>
      <td>String</td>
      <td>The external ID of the user.</td>
      <td><code class="language-plaintext highlighter-rouge">user_abc123</code></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">app_id</code></td>
      <td>Required</td>
      <td>String</td>
      <td>The <a href="/docs/api/identifier_types#app-identifier">app API identifier</a>. It must identify an app in the authenticated workspace.</td>
      <td><code class="language-plaintext highlighter-rouge">26a39c72-e647-4766-b62e-4521fa2dae59</code></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">app_version</code></td>
      <td>Required</td>
      <td>String</td>
      <td>The version of the host app. It must not exceed 255 characters.</td>
      <td><code class="language-plaintext highlighter-rouge">1.0.0</code></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">placements</code></td>
      <td>Required</td>
      <td>Array of strings</td>
      <td>One or more placement IDs to retrieve Banners for. Include at least one placement ID.</td>
      <td><code class="language-plaintext highlighter-rouge">["home_hero", "sidebar_promo"]</code></td>
    </tr>
  </tbody>
</table>

<h2 id="example-request">Example request</h2>

<p>Replace <em><code class="language-plaintext highlighter-rouge">YOUR_REST_API_URL</code></em> with the <a href="/docs/api/basics#endpoints">REST endpoint</a> for your Braze instance.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="rouge-code"><pre>curl <span class="nt">--location</span> <span class="nt">--request</span> POST <span class="s1">'{YOUR_REST_API_URL}/v1/device-messaging/banners/sync'</span> <span class="se">\</span>
<span class="nt">--header</span> <span class="s1">'Authorization: Bearer {YOUR_CLIENT_SIDE_REST_API_KEY}'</span> <span class="se">\</span>
<span class="nt">--header</span> <span class="s1">'Content-Type: application/json'</span> <span class="se">\</span>
<span class="nt">--data-raw</span> <span class="s1">'{
  "external_user_id": "user_abc123",
  "app_id": "26a39c72-e647-4766-b62e-4521fa2dae59",
  "app_version": "1.0.0",
  "placements": [
    "home_hero",
    "sidebar_promo"
  ]
}'</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<h2 id="response-parameters">Response parameters</h2>

<table class="reset-td-br-1 reset-td-br-2 reset-td-br-3" aria-label="Response parameters">
  <thead>
    <tr>
      <th>Parameter</th>
      <th>Data type</th>
      <th>Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">banners</code></td>
      <td>Object</td>
      <td>A map of each requested placement ID to its resolved Banner. The value is <code class="language-plaintext highlighter-rouge">null</code> when no Banner is eligible for a placement.</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">banners.{placement_id}.id</code></td>
      <td>String</td>
      <td>The unique Banner identifier. Use this value to report impression and click events.</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">banners.{placement_id}.placement_id</code></td>
      <td>String</td>
      <td>The placement ID matched to the Banner.</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">banners.{placement_id}.is_control</code></td>
      <td>Boolean</td>
      <td>Whether the Banner is a control-group variant.</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">banners.{placement_id}.is_test_send</code></td>
      <td>Boolean</td>
      <td>Whether the Banner is from a test send. Defaults to <code class="language-plaintext highlighter-rouge">false</code>.</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">banners.{placement_id}.expires_at</code></td>
      <td>Integer</td>
      <td>The Unix timestamp, in seconds, after which you shouldn’t display the Banner. A value of <code class="language-plaintext highlighter-rouge">-1</code> means the Banner doesn’t expire.</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">banners.{placement_id}.properties</code></td>
      <td>Object or null</td>
      <td>Marketer-defined properties for the Banner. Each property contains a <code class="language-plaintext highlighter-rouge">type</code> and <code class="language-plaintext highlighter-rouge">value</code>.</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">banners.{placement_id}.properties.{property}.type</code></td>
      <td>String</td>
      <td>The property’s type. Possible values are <code class="language-plaintext highlighter-rouge">number</code>, <code class="language-plaintext highlighter-rouge">string</code>, <code class="language-plaintext highlighter-rouge">boolean</code>, <code class="language-plaintext highlighter-rouge">image</code>, <code class="language-plaintext highlighter-rouge">jsonobject</code>, and <code class="language-plaintext highlighter-rouge">datetime</code>.</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">banners.{placement_id}.properties.{property}.value</code></td>
      <td>Number, string, Boolean, or object</td>
      <td>The property’s value. Its JSON type corresponds to <code class="language-plaintext highlighter-rouge">type</code>.</td>
    </tr>
  </tbody>
</table>

<h2 id="example-response">Example response</h2>

<p>A successful request returns a <code class="language-plaintext highlighter-rouge">200</code> status code and the resolved Banner for each requested placement.</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
</pre></td><td class="rouge-code"><pre><span class="p">{</span><span class="w">
  </span><span class="nl">"banners"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
    </span><span class="nl">"home_hero"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
      </span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="s2">"this_banner_is_a_stub_01"</span><span class="p">,</span><span class="w">
      </span><span class="nl">"placement_id"</span><span class="p">:</span><span class="w"> </span><span class="s2">"home_hero"</span><span class="p">,</span><span class="w">
      </span><span class="nl">"is_control"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w">
      </span><span class="nl">"is_test_send"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w">
      </span><span class="nl">"expires_at"</span><span class="p">:</span><span class="w"> </span><span class="mi">1735689600</span><span class="p">,</span><span class="w">
      </span><span class="nl">"properties"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
        </span><span class="nl">"headline"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
          </span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"string"</span><span class="p">,</span><span class="w">
          </span><span class="nl">"value"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Level Up Your Game"</span><span class="w">
        </span><span class="p">},</span><span class="w">
        </span><span class="nl">"cta_label"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
          </span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"string"</span><span class="p">,</span><span class="w">
          </span><span class="nl">"value"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Shop Now"</span><span class="w">
        </span><span class="p">}</span><span class="w">
      </span><span class="p">}</span><span class="w">
    </span><span class="p">},</span><span class="w">
    </span><span class="nl">"sidebar_promo"</span><span class="p">:</span><span class="w"> </span><span class="kc">null</span><span class="w">
  </span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></pre></td></tr></tbody></table></code></pre></div></div>

<h2 id="status-codes">Status codes</h2>

<table class="reset-td-br-1 reset-td-br-2" aria-label="Status codes">
  <thead>
    <tr>
      <th>Status code</th>
      <th>Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">200</code></td>
      <td>Braze resolved Banner data for each requested placement.</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">400</code></td>
      <td>The request contains missing or invalid parameters.</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">401</code></td>
      <td>The client-side REST API key is missing, invalid, or doesn’t have the <code class="language-plaintext highlighter-rouge">banners.sync</code> permission.</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">404</code></td>
      <td>The endpoint is unavailable. This response doesn’t distinguish a missing or invalid API key from a disabled Banners feature.</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">429</code></td>
      <td>The workspace exceeded its rate limit.</td>
    </tr>
  </tbody>
</table>

<p>For more information, see <a href="/docs/api/device_messaging_api/error_handling">Device Messaging API error handling and retries</a>.</p>

</div>
