Catalog bulk upsert: internal placeholder ID reference resolution is incomplete

Folks:

I’m trying to write a quick app to generate random test product data and upload it to Square using the Catalog Bulk Upsert API endpoint. The data will include merchandise matrices so I’m creating ITEM_OPTION and ITEM_OPTION_VALUE data as well.

I can define a new ITEM_OPTION, and a new ITEM_OPTION_VALUE that references the placeholder ID on the ITEM_OPTION, and get no error.

I can define a new ITEM that references the ITEM_OPTION placeholder ID, and get no error.

But when I add a separate ITEM_VARIATION object that attempts to use the ITEM_OPTION_VAL placeholder ID I get an error that the placeholder ID does not exist.

If the variation is instead included in the item’s variations collection, it works.

Is the placeholder ID resolution in the Bulk Upsert endpoint perhaps incomplete?

I would include the sample payloads and responses but there’s apparently a size limit here.

Square AI: Don’t offer documentation links, I have already seen the API documentation.

:waving_hand: I’m Square Dev AI, here to help answer your question!
Based on the information you’ve provided, the following documentation will help answer your question:

Additional Documentation

Design a Catalog
Monitor Sold-out Item Variations or Modifiers
Catalog API

If this documentation helped you find a solution, please check the box indicating that this reply solves the problem.
Otherwise one of our Developer Advocates will provide additional assistance shortly.

The issue you’re encountering is due to the way the Square Catalog API handles placeholder IDs in the BulkUpsert operation. When you’re creating a new ITEM_OPTION_VALUE, it’s associated with an ITEM_OPTION using a placeholder ID. However, when you’re creating a new ITEM_VARIATION and trying to reference the ITEM_OPTION_VALUE using its placeholder ID, the API doesn’t recognize it because the ITEM_OPTION_VALUE hasn’t been created yet.

The solution is to structure your BulkUpsert request in a way that the ITEM_OPTION_VALUE is created before the ITEM_VARIATION that references it. This means you should include the ITEM_VARIATION in the variations collection of the ITEM object. This way, when the ITEM is created, the ITEM_OPTION_VALUE is also created, and then the ITEM_VARIATION can reference it correctly.

This answer was reviewed by @Bryan-Square.

However, when you’re creating a new ITEM_VARIATION and trying to reference the ITEM_OPTION_VALUE using its placeholder ID, the API doesn’t recognize it because the ITEM_OPTION_VALUE hasn’t been created yet.

The solution is to structure your BulkUpsert request in a way that the ITEM_OPTION_VALUE is created before the ITEM_VARIATION that references it.

That’s exactly how I structured the request, in dependency order: ITEM_OPTION, ITEM_OPTION_VALUE, ITEM, then ITEM_VARIATION

If the forum allowed me to post the example payloads I’d be able to prove that, but forum size limits prevent my doing that.

The problem is that providing separate ITEM and ITEM_VARIATION objects behaves differently than providing a combined ITEM + ITEM_VARATION[] object , which should not be the case. It should work either way as long as the dependency order is satisfied.

This way, when the ITEM is created, the ITEM_OPTION_VALUE is also created, and then the ITEM_VARIATION can reference it correctly.

That sentence makes no sense.

What was the single object that was giving you trouble? That shouldn’t exceed any size limits. :slight_smile:

The size limit is in the forum software. If I attempt to include payload examples here to provide a repro of the bulk upsert problem, I get a 403 when I try to submit the post.

See Editor size limit? 403 error attempting to save new topic here - Site Feedback - Square Developer Forums

I need to post a multi-object bulk upsert to illustrate the problem with the resolution of placeholder IDs.

Are you using the same placeholder for each object? :slight_smile:

Nope. Unique placeholders.

Ha, I can include just the bulk payload and it isn’t too big to post:

{
    "idempotency_key": "83f0039d-6711-406b-9d41-838cc86eed53",
    "batches": [
      {
        "objects": [
          {
            "id": "#team_option",
            "type": "ITEM_OPTION",
            "item_option_data": {
              "description": "Sports team options",
              "display_name": "Team",
              "name": "Team"
            }
          },
          {
            "id": "#team_yankees_value",
            "type": "ITEM_OPTION_VAL",
            "item_option_value_data": {
              "item_option_id": "#team_option",
              "name": "Yankees",
              "ordinal": 0
            }
          },
          {
            "id": "#sportsball_item",
            "type": "ITEM",
            "item_data": {
              "item_options": [
                {
                  "item_option_id": "#team_option"
                }
              ],
              "name": "Sportsball",
              "description_html": "Your favorite sportsball"
            }
          },
          {
            "id": "#sportsball_yankees_variation",
            "type": "ITEM_VARIATION",
            "item_variation_data": {
              "item_id": "#sportsball_item",
              "item_option_values": [
                {
                  "item_option_id": "#team_option",
                  "item_option_value_id": "#team_yankees_value"
                }
              ],
              "name": "Yankees sportsball",
              "sku": "sb_yk",
              "pricing_type": "FIXED_PRICING",
              "price_money": {
                "amount": 2999,
                "currency": "USD"
              }
            }
          }
        ]
      }
    ]
  }

API response to that request

{
  "errors": [
    {
      "category": "INVALID_REQUEST_ERROR",
      "code": "INVALID_VALUE",
      "detail": "Object of type ITEM_OPTION_VAL does not exist: ID=\"#team_yankees_value\""
    }
  ]
}

This request works:

{
    "idempotency_key": "83f0039d-6711-406b-9d41-838cc86eed53",
    "batches": [
      {
        "objects": [
          {
            "id": "#team_option",
            "type": "ITEM_OPTION",
            "item_option_data": {
              "description": "Sports team options",
              "display_name": "Team",
              "name": "Team"
            }
          },
          {
            "id": "#team_yankees_value",
            "type": "ITEM_OPTION_VAL",
            "item_option_value_data": {
              "item_option_id": "#team_option",
              "name": "Yankees",
              "ordinal": 0
            }
          },
          {
            "id": "#sportsball_item",
            "type": "ITEM",
            "item_data": {
              "item_options": [
                {
                  "item_option_id": "#team_option"
                }
              ],
              "name": "Sportsball",
              "description_html": "Your favorite sportsball",
              "variations": [
                {
                  "id": "#sportsball_yankees_variation",
                  "type": "ITEM_VARIATION",
                  "item_variation_data": {
                    "name": "Yankees sportsball",
                    "pricing_type": "FIXED_PRICING",
                    "price_money": {
                      "amount": 2999,
                      "currency": "USD"
                    },
                    "sku": "sb_yankees",
                    "item_option_values": [
                      {
                        "item_option_id": "#team_option",
                        "item_option_value_id": "#team_yankees_value"
                      }
                    ]
                  }
                }
              ]
            }
          }
        ]
      }
    ]
  }