> ## 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.

# Generate Google Ads image assets

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

Generates ad pictures for the app and returns them as previews.

Nothing reaches Google Ads here. Each picture comes back with a `session_asset_id` you pass to [Accept a generated Google Ads asset](/api-reference/accept-a-generated-google-ads-asset) to put it on a live campaign.

Send exactly one of `final_url` and `freeform_prompt`. Sending both is rejected, and so is sending neither, which is the one place this endpoint differs from [Generate Google Ads assets](/api-reference/generate-google-ads-assets), where omitting both is allowed and grounds the pictures in the app's home page.

Pictures are slower than copy, so the response returns once the first one is ready. `assets` holds what finished in time and `background_pending` with `background_count` say that more are coming. Poll [List Google Ads generated assets](/api-reference/list-google-ads-generated-assets) with the returned `session_id` for the rest. `assets` can be empty while `background_pending` is `true`, which means the pictures are being generated but none landed in time.

<Note>Only one generation of each kind runs per app at a time. Calling this while one is running returns a 200 carrying `in_flight` set to `true`, that run's `session_id`, and an empty `assets`. Poll the `session_id` you were given rather than retrying.</Note>

Each shape in `asset_field_types` costs one of 10 picture requests a minute per app, and the retry below costs the whole shape count again. So four shapes cost 4 normally and 8 on a retry, which is one call a minute in the worst case rather than two, and a single shape costs 1 or 2.

<Note>When Google refuses the page you pointed at, Base44 retries once on the app's own published URL, and that retry costs the same again. Pace requests against the doubled figure, not the single one, or a refusal-heavy app hits a 429 part-way through its own recovery.</Note>

<Note>Generating creative does not spend credits and is not billed. It is capped by rate limits instead, so a burst gets a 429 rather than a bill.</Note>

<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. Send only the fields documented here. Other request fields are not supported and their behavior can change.</Warning>



## OpenAPI

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


        Generates ad pictures for the app and returns them as previews.


        Nothing reaches Google Ads here. Each picture comes back with a
        `session_asset_id` you pass to [Accept a generated Google Ads
        asset](/api-reference/accept-a-generated-google-ads-asset) to put it on
        a live campaign.


        Send exactly one of `final_url` and `freeform_prompt`. Sending both is
        rejected, and so is sending neither, which is the one place this
        endpoint differs from [Generate Google Ads
        assets](/api-reference/generate-google-ads-assets), where omitting both
        is allowed and grounds the pictures in the app's home page.


        Pictures are slower than copy, so the response returns once the first
        one is ready. `assets` holds what finished in time and
        `background_pending` with `background_count` say that more are coming.
        Poll [List Google Ads generated
        assets](/api-reference/list-google-ads-generated-assets) with the
        returned `session_id` for the rest. `assets` can be empty while
        `background_pending` is `true`, which means the pictures are being
        generated but none landed in time.


        <Note>Only one generation of each kind runs per app at a time. Calling
        this while one is running returns a 200 carrying `in_flight` set to
        `true`, that run's `session_id`, and an empty `assets`. Poll the
        `session_id` you were given rather than retrying.</Note>


        Each shape in `asset_field_types` costs one of 10 picture requests a
        minute per app, and the retry below costs the whole shape count again.
        So four shapes cost 4 normally and 8 on a retry, which is one call a
        minute in the worst case rather than two, and a single shape costs 1 or
        2.


        <Note>When Google refuses the page you pointed at, Base44 retries once
        on the app's own published URL, and that retry costs the same again.
        Pace requests against the doubled figure, not the single one, or a
        refusal-heavy app hits a 429 part-way through its own recovery.</Note>


        <Note>Generating creative does not spend credits and is not billed. It
        is capped by rate limits instead, so a burst gets a 429 rather than a
        bill.</Note>


        <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. Send only the fields documented here. Other request fields are not
        supported and their behavior can change.</Warning>
      operationId: >-
        generate_image_assets_api_apps__app_id__google_ads_assets_generate_images_post
      parameters:
        - name: app_id
          in: path
          required: true
          schema:
            type: string
            description: >-
              ID of the app whose Google Ads creative you want to generate or
              read.
            title: App Id
          description: >-
            ID of the app whose Google Ads creative you want to generate or
            read.
          example: 6820f3a4e7b91d003c45a1f2
      requestBody:
        required: true
        content:
          application/json:
            schema:
              title: GenerateImageAssets
              type: object
              properties:
                channel_type:
                  type: string
                  description: >-
                    Campaign type the pictures are for, one of
                    `PERFORMANCE_MAX`, `DEMAND_GEN`, `SEARCH` or `DISPLAY`. It
                    does not restrict the shapes you may ask for.
                  default: PERFORMANCE_MAX
                  example: PERFORMANCE_MAX
                asset_field_types:
                  type: array
                  description: >-
                    Which picture shapes to generate, from `MARKETING_IMAGE`,
                    `SQUARE_MARKETING_IMAGE`, `PORTRAIT_MARKETING_IMAGE` or
                    `TALL_PORTRAIT_MARKETING_IMAGE`. Send between one and four
                    entries. Each shape costs one request against the picture
                    rate limit, so asking for fewer gets you more calls a
                    minute. A text field type here is rejected with a 422.
                  items:
                    type: string
                    description: >-
                      One of `MARKETING_IMAGE`, `SQUARE_MARKETING_IMAGE`,
                      `PORTRAIT_MARKETING_IMAGE` or
                      `TALL_PORTRAIT_MARKETING_IMAGE`.
                    example: SQUARE_MARKETING_IMAGE
                  default:
                    - MARKETING_IMAGE
                    - SQUARE_MARKETING_IMAGE
                    - PORTRAIT_MARKETING_IMAGE
                    - TALL_PORTRAIT_MARKETING_IMAGE
                  example:
                    - MARKETING_IMAGE
                    - SQUARE_MARKETING_IMAGE
                final_url:
                  type: string
                  description: >-
                    Page to base the pictures on. Send exactly one of this and
                    `freeform_prompt`.
                  example: https://example.com/spring
                freeform_prompt:
                  type: string
                  description: >-
                    What the pictures should show, in your own words, up to 1500
                    characters. Send exactly one of this and `final_url`.
                  example: Warm studio shots of handmade oak dining tables
            example:
              asset_field_types:
                - MARKETING_IMAGE
                - SQUARE_MARKETING_IMAGE
              final_url: https://example.com/spring
      responses:
        '200':
          description: The pictures that were generated.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GenerateImageAssetsResult'
        '400':
          description: >-
            Google Ads rejected the generation request, for example a landing
            page it could not read. The response message carries Google's
            reason.
        '401':
          description: Missing or invalid credentials.
        '403':
          description: >-
            You don't have access to this app, the app does not exist, or you
            used a workspace API key. A missing app and an app you cannot reach
            are deliberately the same answer.
        '409':
          description: >-
            The request to Google Ads timed out after being sent. Nothing was
            attached to a campaign, so retrying is safe.
        '422':
          description: >-
            You sent both `final_url` and `freeform_prompt` or neither, or
            `asset_field_types` contains a value that is not an image field
            type, is empty, or has more than four entries, or `freeform_prompt`
            is longer than 1500 characters.
        '429':
          description: >-
            The app has used up one of the creative rate limits, either 20 copy
            requests a minute or 10 picture requests a minute. Retry later.
components:
  schemas:
    GenerateImageAssetsResult:
      properties:
        session_id:
          type: string
          title: Session Id
          description: >-
            ID of this generation. Pass it as `session_id` to [List Google Ads
            generated assets](/api-reference/list-google-ads-generated-assets)
            to collect the pictures that are still coming.
          example: 9c1d2e3f-4a5b-6c7d-8e9f-0a1b2c3d4e5f
        assets:
          items:
            $ref: '#/components/schemas/GeneratedAssetSummary'
          type: array
          title: Assets
          description: >-
            The pictures that finished in time to be returned inline. Empty when
            nothing landed in time, when the engine produced nothing, and when a
            generation for this app was already running, which `in_flight` tells
            apart.
          example: []
        background_pending:
          anyOf:
            - type: boolean
            - type: 'null'
          title: Background Pending
          description: >-
            Present and `true` when more pictures are still being generated
            under this `session_id`, including when `assets` came back empty
            because the first one took too long. Absent on a lock-miss response.
          example: true
        background_count:
          anyOf:
            - type: integer
            - type: 'null'
          title: Background Count
          description: >-
            How many more pictures are still being generated. Absent on a
            lock-miss response.
          example: 3
        in_flight:
          anyOf:
            - type: boolean
            - type: 'null'
          title: In Flight
          description: >-
            Present and `true` only when an image generation for this app was
            already running, in which case `session_id` is that run's and
            `assets` is empty. Poll the returned `session_id` rather than
            retrying. The field is absent on every other response.
          example: true
      type: object
      required:
        - session_id
        - assets
      title: GenerateImageAssetsResult
      description: The pictures one image generation produced.
    GeneratedAssetSummary:
      properties:
        session_asset_id:
          type: string
          title: Session Asset Id
          description: >-
            ID of this asset within the session. Pass it as `session_asset_id`
            to [Accept a generated Google Ads
            asset](/api-reference/accept-a-generated-google-ads-asset).
          example: b7f3a1c8-52d4-4a0e-9b31-2c6f0d8e4a19
        asset_field_type:
          type: string
          title: Asset Field Type
          description: >-
            Which slot on the ad this asset fills. Text assets are `HEADLINE`,
            `LONG_HEADLINE` or `DESCRIPTION`. Image assets are
            `MARKETING_IMAGE`, `SQUARE_MARKETING_IMAGE`,
            `PORTRAIT_MARKETING_IMAGE` or `TALL_PORTRAIT_MARKETING_IMAGE`.
          example: HEADLINE
        kind:
          type: string
          title: Kind
          description: Whether the asset is copy (`text`) or a picture (`image`).
          example: text
        text:
          anyOf:
            - type: string
            - type: 'null'
          title: Text
          description: The generated copy, or `null` on an image asset.
          example: Handmade oak furniture, built to last
        image_url:
          anyOf:
            - type: string
            - type: 'null'
          title: Image Url
          description: >-
            URL of the generated picture, or `null` on a text asset. It is a
            Base44 preview URL, not a Google one, and it stops resolving once
            the asset is cleaned up.
          example: https://storage.base44.com/gads-assets/b7f3a1c8-square.png
        source:
          type: string
          title: Source
          description: >-
            Which engine wrote it. The value is `google` for Google's own asset
            generation and `inhouse` for the Base44 model that covers languages
            Google does not generate for, and that stands in when Google's call
            fails.
          example: google
        language:
          anyOf:
            - type: string
            - type: 'null'
          title: Language
          description: >-
            Language of a text asset as a lowercase two-letter code, or `null`
            on an image, because image assets carry no copy.
          example: de
        channel_type:
          type: string
          title: Channel Type
          description: >-
            Campaign type the asset was generated for, one of `SEARCH`,
            `PERFORMANCE_MAX`, `DISPLAY` or `DEMAND_GEN`.
          example: PERFORMANCE_MAX
        created_at:
          type: string
          format: date-time
          title: Created At
          description: When the asset was generated.
          example: '2026-08-25T14:05:00Z'
      type: object
      required:
        - session_asset_id
        - asset_field_type
        - kind
        - text
        - image_url
        - source
        - language
        - channel_type
        - created_at
      title: GeneratedAssetSummary
      description: One generated asset in a live generation session.
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: api_key
      description: Personal API key.

````