> ## Documentation Index
> Fetch the complete documentation index at: https://docs.base44.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Sync Google Ads campaigns

> <Info>This API is in beta. Endpoints, fields, and behavior may still change, so avoid depending on it in production.</Info>

Reads the account's campaigns from Google Ads now, saves them to Base44, and returns what Google reported.

For each campaign it reads, Base44 replaces its own record of the name, status, type, daily budget, and serving and policy status with Google's. A campaign on the account that Base44 has no record of, such as one created outside Base44, is added. Deleted campaigns are skipped.

Base44 already refreshes campaign statuses and metrics from Google in the background about once an hour, and that refresh never adds a campaign Base44 doesn't know about. Call this when you need Google's current state right away, or to bring in campaigns created outside Base44.

The rows carry `google_campaign_id` but not Base44's `id`. To act on a campaign afterwards, find its `id` in [List campaigns](/api-reference/list-google-ads-campaigns). The metrics are not limited to a date range. Use [Get campaign metrics](/api-reference/get-google-ads-campaign-metrics) for figures over a window.

<Warning>A sync reads at most 50 campaigns, the ones with the most impressions, and there is no pagination. On an account with more campaigns than that, the rest are neither refreshed nor returned, and nothing in the response says so.</Warning>

This keeps working while the workspace is on a billing hold, so the campaigns it owes for can still be refreshed.

This is limited to 6 requests a minute per app. Some workspaces have a different limit.

<Note>This endpoint accepts a personal API key. Workspace API keys are not authorized for it and are rejected with a 403.</Note>

<Warning>The response includes fields beyond the ones documented here. Don't rely on undocumented response fields, as they can change at any time.</Warning>



## OpenAPI

````yaml /developers/references/app-management/app-management-openapi.json post /api/apps/{app_id}/google-ads/campaigns/sync
openapi: 3.1.0
info:
  title: Base44 App Management API
  version: 1.0.0
servers:
  - url: https://app.base44.com
security:
  - PersonalAccessTokenAuth: []
paths:
  /api/apps/{app_id}/google-ads/campaigns/sync:
    post:
      summary: Sync Google Ads campaigns
      description: >-
        <Info>This API is in beta. Endpoints, fields, and behavior may still
        change, so avoid depending on it in production.</Info>


        Reads the account's campaigns from Google Ads now, saves them to Base44,
        and returns what Google reported.


        For each campaign it reads, Base44 replaces its own record of the name,
        status, type, daily budget, and serving and policy status with Google's.
        A campaign on the account that Base44 has no record of, such as one
        created outside Base44, is added. Deleted campaigns are skipped.


        Base44 already refreshes campaign statuses and metrics from Google in
        the background about once an hour, and that refresh never adds a
        campaign Base44 doesn't know about. Call this when you need Google's
        current state right away, or to bring in campaigns created outside
        Base44.


        The rows carry `google_campaign_id` but not Base44's `id`. To act on a
        campaign afterwards, find its `id` in [List
        campaigns](/api-reference/list-google-ads-campaigns). The metrics are
        not limited to a date range. Use [Get campaign
        metrics](/api-reference/get-google-ads-campaign-metrics) for figures
        over a window.


        <Warning>A sync reads at most 50 campaigns, the ones with the most
        impressions, and there is no pagination. On an account with more
        campaigns than that, the rest are neither refreshed nor returned, and
        nothing in the response says so.</Warning>


        This keeps working while the workspace is on a billing hold, so the
        campaigns it owes for can still be refreshed.


        This is limited to 6 requests a minute per app. Some workspaces have a
        different limit.


        <Note>This endpoint accepts a personal API key. Workspace API keys are
        not authorized for it and are rejected with a 403.</Note>


        <Warning>The response includes fields beyond the ones documented here.
        Don't rely on undocumented response fields, as they can change at any
        time.</Warning>
      operationId: sync_campaigns_api_apps__app_id__google_ads_campaigns_sync_post
      parameters:
        - name: app_id
          in: path
          required: true
          schema:
            type: string
            description: ID of the app whose Google Ads campaigns to manage.
            title: App Id
          description: ID of the app whose Google Ads campaigns to manage.
          example: 6820f3a4e7b91d003c45a1f2
      responses:
        '200':
          description: The campaigns Google reported, as Base44 saved them.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/SyncedCampaign'
                title: >-
                  Response 200 Sync Campaigns Api Apps  App Id  Google Ads
                  Campaigns Sync Post
        '400':
          description: Google Ads rejected the read.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: >-
            You don't have access to this app, the app does not exist, you used
            a read-only or workspace API key, or Google Ads refused access to
            the account. A missing app and an app you cannot reach are
            deliberately the same answer.
        '404':
          description: The app has no connected Google Ads account.
        '429':
          description: >-
            The app has used up its sync quota for the current minute, or Google
            Ads is rate limiting the account. Retry later.
components:
  schemas:
    SyncedCampaign:
      properties:
        google_campaign_id:
          type: string
          title: Google Campaign Id
          description: >-
            The campaign's ID in Google Ads. Match it against
            `google_campaign_id` from [List
            campaigns](/api-reference/list-google-ads-campaigns) to find
            Base44's `id` for the campaign.
          example: '21098765432'
        name:
          type: string
          title: Name
          description: Name shown for the campaign.
          example: Spring sale in Berlin
        status:
          type: string
          title: Status
          description: Serving state Google reports, `ENABLED` or `PAUSED`.
          example: ENABLED
        campaign_type:
          type: string
          title: Campaign Type
          description: >-
            Campaign type, passed through as Google reports it. Base44 creates
            `SMART` and `PERFORMANCE_MAX`. The other values appear only on
            campaigns created outside Base44.
          example: SMART
        impressions:
          type: integer
          title: Impressions
          description: Times the campaign's ads were shown.
          example: 15420
        clicks:
          type: integer
          title: Clicks
          description: Clicks the campaign received.
          example: 612
        cost_micros:
          type: integer
          title: Cost Micros
          description: >-
            Spend in micros of the account currency, where 1,000,000 micros is
            one unit, so `248000000` is 248.00.
          example: 248000000
        conversions:
          type: number
          title: Conversions
          description: Conversions Google attributed to the campaign.
          example: 31
        review_status:
          type: string
          title: Review Status
          description: >-
            Google's policy review status as Base44 last recorded it
            (`REVIEWED`, `UNDER_REVIEW`, …). A sync doesn't refresh it, and it's
            empty on a campaign the sync just added.
          example: REVIEWED
        serving_status:
          type: string
          title: Serving Status
          description: Google's serving status, passed through as Google reports it.
          example: SERVING
        primary_status:
          type: string
          title: Primary Status
          description: >-
            Google's summary of whether the campaign is serving well, passed
            through as Google reports it (`ELIGIBLE`, `LIMITED`, `NOT_SERVING`,
            …).
          example: ELIGIBLE
        primary_status_reasons:
          items:
            type: string
          type: array
          title: Primary Status Reasons
          description: >-
            Google's reasons behind `primary_status`, for example why a campaign
            is limited. Empty when there is nothing to explain.
          example:
            - CAMPAIGN_BUDGET_LIMITED
      type: object
      required:
        - google_campaign_id
        - name
        - status
        - campaign_type
        - impressions
        - clicks
        - cost_micros
        - conversions
        - review_status
        - serving_status
        - primary_status
        - primary_status_reasons
      title: SyncedCampaign
      description: One campaign as Google reported it during a sync.
  securitySchemes:
    PersonalAccessTokenAuth:
      type: http
      scheme: bearer
      description: 'Personal access token, sent as `Authorization: Bearer <token>`.'

````