# Listing Guide

Here's a step-by-step guide to help you publish your item for sale using the API.

Technical-focus
This guide provides a *technical* overview of the steps required to publish an item for sale on the Wallapop platform using the API, along with sample API requests. For a *conceptual* understanding of the process at a high level, please refer to our [Publish Item Flow](/pages/api-essentials/publishing-items).

The following sequence diagram demonstrates the actions performed by the API client during the item listing process:

```mermaid
sequenceDiagram
    participant Seller
    participant API

    Seller->>API: GET /items/categories
    API-->>Seller: 200 OK + Categories List

    Seller->>Seller: Choose category with assignable_to_item = true

    Seller->>API: GET /items/categories/{id}/attributes
    API-->>Seller: 200 OK + Category Attributes

    Seller->>API: POST /items (category_leaf_id + required attributes)
    API-->>Seller: 201 Created + Item ID

    Seller->>API: POST /items/{id}/images (image URL, order)
    API-->>Seller: 201 Created + Image ID

    Seller->>API: GET /items/{id} (Optional: Check item status)
    API-->>Seller: 200 OK + Item Details
```

## 1) Identify Item Categories

First things first—let's find the right category for your item! Start by sending a **GET** request to `/items/categories` to access Wallapop’s category hierarchy. Don’t forget to replace `<YOUR_TOKEN_HERE>` with your access token.

Example
Response Body Schema
```json
{
  "$ref": "#/components/schemas/CategoriesResponse",
  "components": {
    "schemas": {
      "Category": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "description": "The ID of the category.",
            "example": 24200
          },
          "parent_id": {
            "type": "integer",
            "description": "If the category is a subcategory, the `parent_id` indicates the category it is logically nested under. It returns `null` if the category is a root-level category, meaning it is not nested under another category.\n",
            "example": 24200
          },
          "name": {
            "type": "string",
            "description": "The category name will be translated according to the `Accept-Language` header. If Wallapop does not support the language, it will default to English.\n",
            "example": "Tecnología y electrónica"
          },
          "assignable_to_item": {
            "type": "boolean",
            "description": "When set to `true`, a category can be assigned to an item. If set to `false`, it acts as a parent category and cannot be selected directly, containing more specific subcategories. Wallapop encourages users to choose the most specific subcategory, so top-level and intermediate categories in certain trees cannot be assigned to items.\n",
            "example": false
          },
          "subcategories": {
            "type": "array",
            "description": "A list of subcategories that are logically nested under this category. An empty list in the response indicates that the category can be assigned to an item and that there are no specific subcategories available for selection.",
            "example": [
              {
                "id": 10414,
                "parent_id": 24200,
                "name": "TV",
                "assignable_to_item": true
              }
            ],
            "items": {
              "$ref": "#/components/schemas/Category"
            }
          }
        }
      },
      "CategoriesResponse": {
        "type": "object",
        "properties": {
          "categories": {
            "type": "array",
            "description": "Wallapop's category hierarchy used to classify items. Some categories serve as grouping mechanisms, while others can be assigned to items.",
            "items": {
              "$ref": "#/components/schemas/Category"
            }
          }
        }
      }
    }
  }
}
```

A successful request returns a `200 OK` status with Wallapop's categories.

## 2) Choose a Category

The next step is to a choose a category from the list. Choose wisely! An item can only be assigned to a category if its `assignable_to_item` property is set to `true`. For example, if you’re selling a pair of women’s activewear shorts, you’ll want to select `Shorts` under the `Activewear` category.

## 3) Retrieve Category Attributes

Next up, find out what info Wallapop needs for your category. Send a **GET** request to `/items/categories/{id}/attributes`, swapping `{id}` with the relevant category ID.

Example
```shell cURL
curl -i -X GET \
  https://connect.wallapop.com/items/categories/12467/attributes \
  -H 'Authorization: Bearer <YOUR_TOKEN_HERE>'
```

Response Body Schema
```json
{
  "$ref": "#/components/schemas/CategoryAttributesResponse",
  "components": {
    "schemas": {
      "MandatoryByDate": {
        "type": "string",
        "format": "date",
        "description": "The expected date after which the attribute will be mandatory.",
        "example": "2024-12-30"
      },
      "CategoryAttributeDiscreteValuesResponse": {
        "description": "An attribute that allows selection from a predefined set of options, similar to choosing a value from an enumerated list.",
        "required": [
          "id",
          "type",
          "is_mandatory",
          "options"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "The ID of the attribute."
          },
          "type": {
            "type": "string",
            "enum": [
              "discrete_values"
            ]
          },
          "is_mandatory": {
            "type": "boolean",
            "description": "Indicates whether the attribute is mandatory.",
            "example": true
          },
          "mandatory_by_date": {
            "$ref": "#/components/schemas/MandatoryByDate"
          },
          "options": {
            "type": "object",
            "description": "The options for attributes of type 'discrete_values'.",
            "required": [
              "max_choices",
              "values"
            ],
            "properties": {
              "max_choices": {
                "type": "integer",
                "description": "The maximum number of selectable options."
              },
              "values": {
                "type": "array",
                "items": {
                  "type": "object",
                  "required": [
                    "id"
                  ],
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "The ID of the attribute value, expected when adding or updating a specific item attribute."
                    },
                    "title": {
                      "type": "string",
                      "description": "The title of the option in the requested language, if available."
                    }
                  }
                }
              }
            }
          }
        }
      },
      "RegexValidation": {
        "type": "object",
        "description": "The regex validation applied to the value.",
        "required": [
          "type",
          "value"
        ],
        "properties": {
          "type": {
            "type": "string",
            "description": "Indicates how the regex pattern is applied. The possible values include: `not_match` or `not_contain`.\n",
            "example": "not_contain"
          },
          "value": {
            "type": "string",
            "description": "The regex pattern.",
            "example": "^(\\s+$)"
          }
        }
      },
      "CategoryAttributeTextValueResponse": {
        "type": "object",
        "description": "An attribute that accepts text input (i.e., a string of characters).",
        "required": [
          "id",
          "type",
          "is_mandatory",
          "max_length"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "The ID of the attribute."
          },
          "type": {
            "type": "string",
            "enum": [
              "text"
            ]
          },
          "is_mandatory": {
            "type": "boolean",
            "description": "Indicates whether the attribute is mandatory.",
            "example": true
          },
          "mandatory_by_date": {
            "$ref": "#/components/schemas/MandatoryByDate"
          },
          "max_length": {
            "type": "integer",
            "description": "The maximum allowable length for the provided text value.",
            "example": 640
          },
          "regex": {
            "type": "array",
            "description": "A regex pattern that the provided text value is validated against.",
            "items": {
              "$ref": "#/components/schemas/RegexValidation"
            }
          }
        }
      },
      "CategoryAttributeNumericValueResponse": {
        "description": "An attribute that accepts numerical values.",
        "required": [
          "id",
          "type",
          "is_mandatory",
          "data_type"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "The ID of the attribute."
          },
          "type": {
            "type": "string",
            "enum": [
              "numeric"
            ]
          },
          "is_mandatory": {
            "type": "boolean",
            "description": "Indicates whether the attribute is mandatory.",
            "example": true
          },
          "mandatory_by_date": {
            "$ref": "#/components/schemas/MandatoryByDate"
          },
          "data_type": {
            "type": "object",
            "description": "Information about the numeric data type. See the [OpenAPI Specification](https://spec.openapis.org/oas/latest.html#data-types) for more details.",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "integer",
                  "number"
                ],
                "description": "The numeric data type."
              },
              "format": {
                "type": "string",
                "enum": [
                  "int32",
                  "int64",
                  "float",
                  "double"
                ],
                "description": "The format of the numeric data type."
              }
            }
          },
          "range": {
            "type": "object",
            "description": "The allowed range for the numeric value.",
            "properties": {
              "greater_than_or_equal": {
                "type": "integer",
                "description": "The minimum allowed value (inclusive)."
              },
              "less_than_or_equal": {
                "type": "integer",
                "description": "The maximum allowed value (inclusive)."
              }
            }
          }
        }
      },
      "CategoryAttributesResponse": {
        "type": "object",
        "properties": {
          "attributes": {
            "type": "array",
            "items": {
              "type": "object",
              "oneOf": [
                {
                  "$ref": "#/components/schemas/CategoryAttributeDiscreteValuesResponse"
                },
                {
                  "$ref": "#/components/schemas/CategoryAttributeTextValueResponse"
                },
                {
                  "$ref": "#/components/schemas/CategoryAttributeNumericValueResponse"
                }
              ]
            },
            "example": {
              "example": {
                "attributes": [
                  {
                    "id": "condition",
                    "type": "discrete_values",
                    "is_mandatory": true,
                    "options": {
                      "max_choices": 1
                    },
                    "values": [
                      {
                        "id": "new",
                        "title": "Nuevo"
                      },
                      {
                        "id": "as_good_as_new",
                        "title": "Como nuevo"
                      },
                      {
                        "id": "good",
                        "title": "En buen estado"
                      },
                      {
                        "id": "fair",
                        "title": "En condiciones aceptables"
                      },
                      {
                        "id": "has_given_it_all",
                        "title": "Lo ha dado todo"
                      }
                    ]
                  },
                  {
                    "id": "brand",
                    "type": "text",
                    "is_mandatory": true,
                    "max_length": 75
                  },
                  {
                    "id": "height_cm",
                    "type": "numeric",
                    "is_mandatory": false,
                    "data_type": {
                      "type": "integer"
                    },
                    "range": {
                      "greater_than_or_equal": 0,
                      "less_than_or_equal": 999
                    }
                  }
                ]
              }
            }
          }
        }
      }
    }
  }
}
```

A successful request will return a `200 OK` status, along with a list of attributes. Some attributes are mandatory while others are optional. If you’re selling a car, for instance, you'll need attributes like `brand` and `model`:

```json
{
  "attributes": [
    { "type": "text", "id": "brand", "is_mandatory": true, "max_length": 75 },
    { "type": "text", "id": "model", "is_mandatory": true, "max_length": 75 },
    // other attributes...
  ]
}
```

Pro Tip: Mapping your Inventory
To simplify synchronization between your system and Wallapop, you can use specific attributes to store your own identifiers directly on the item:

**`external_id`**: Available for **all categories**. Use this field to store your internal reference code (SKU, ID, etc.).

```json
{ "type": "text", "id": "external_id", "is_mandatory": false, "max_length": 75 }
```

**`license_plate`**: Specific to the **Cars** category. Useful for identifying unique vehicles in your fleet.

```json
{ "type": "text", "id": "license_plate", "is_mandatory": false, "max_length": 10 }
```

By providing these values during creation (`POST`) or modification (`PUT`), and retrieving them via `GET`, you can easily maintain the relationship between your internal identifiers and Wallapop listings.

Make sure you stick with any character limits and guidelines—it's all in the details!

## 4) Publish Your Items

You’re ready to go! Send a **POST** request to the `/items` endpoint with all the necessary info in the request body. Don't forget the `category_leaf_id`, which links to your chosen category.

Example
```shell cURL
curl -i -X POST \
  https://connect.wallapop.com/items \
  -H 'Authorization: Bearer <YOUR_TOKEN_HERE>' \
  -H 'Content-Type: application/json' \
  -d '{
    "item": {
      "category_leaf_id": "9931",
      "title": "Title example",
      "description": "A renowned line of performance and lifestyle sneakers that offer superior comfort, support, and style both on and off the court.",
      "price": {
        "cash_amount": 75.5,
        "currency": "EUR"
      },
      "attributes": {
        "external_id": "407947058",
        "brand": "Abc Design",
        "size": 34,
        "condition": "new",
        "color": "yellow"
      },
      "hashtags": [
        "awesome",
        "original"
      ],
      "delivery": {
        "allowed_by_user": true,
        "max_weight_kg": 10,
        "free_shipping": false
      }
    },
    "main_image": {
      "url": "http://cdn.portal.com/image129.jpg"
    },
    "stock": {
      "units": 0
    }
  }'
```

Request Body Schema
```json
{
  "$ref": "#/components/schemas/CreateItemRequest",
  "components": {
    "schemas": {
      "ItemPrice": {
        "required": [
          "cash_amount",
          "currency"
        ],
        "properties": {
          "cash_amount": {
            "type": "number",
            "description": "The price of the item.",
            "example": 75.5
          },
          "currency": {
            "type": "string",
            "description": "The currency code. Only supports `EUR`.",
            "example": "EUR"
          }
        }
      },
      "Attributes": {
        "type": "object",
        "additionalProperties": true,
        "description": "Attributes that only apply for some categories. You can retrieve the expected attributes/values by category using [this operation](#category/getCategoryAttributes)\n",
        "example": {
          "external_id": "407947058",
          "brand": "Abc Design",
          "size": 34,
          "condition": "new",
          "color": "yellow"
        }
      },
      "ItemHashTags": {
        "type": "array",
        "deprecated": true,
        "description": "List of hashtags.",
        "example": [
          "awesome",
          "original"
        ],
        "items": {
          "type": "string"
        }
      },
      "DeliveryAttributes": {
        "type": "object",
        "required": [
          "allowed_by_user"
        ],
        "properties": {
          "allowed_by_user": {
            "type": "boolean",
            "description": "Boolean indicating if the seller allows shipping for the item.",
            "example": true
          },
          "max_weight_kg": {
            "type": "integer",
            "description": "The maximum item weight in kilograms for shipping. Acceptable values are `1`, `2`, `5`, `10`, `20`, or `30`?",
            "example": 10
          },
          "free_shipping": {
            "type": "boolean",
            "format": "uuid",
            "description": "Whether to offer free shipping. Requires a Wallapop Pro subscription. For more details, refer to [Offer free shipping](https://ayuda.wallapop.com/hc/es-es/articles/9971072329361-Ofrece-env%C3%ADo-gratis).\n",
            "example": false
          }
        }
      },
      "Item": {
        "type": "object",
        "required": [
          "category_leaf_id",
          "title",
          "description",
          "price"
        ],
        "properties": {
          "category_leaf_id": {
            "type": "string",
            "description": "The category used to classify the item. The category must be an assignable category.",
            "example": "9931"
          },
          "title": {
            "type": "string",
            "description": "The item's title.",
            "example": "Title example"
          },
          "description": {
            "type": "string",
            "description": "The item description.",
            "example": "A renowned line of performance and lifestyle sneakers that offer superior comfort, support, and style both on and off the court."
          },
          "price": {
            "$ref": "#/components/schemas/ItemPrice"
          },
          "attributes": {
            "$ref": "#/components/schemas/Attributes"
          },
          "hashtags": {
            "$ref": "#/components/schemas/ItemHashTags"
          },
          "delivery": {
            "$ref": "#/components/schemas/DeliveryAttributes"
          }
        }
      },
      "ExternalImageURL": {
        "type": "string",
        "description": "Provide a direct link to the image without redirections. The HTTP response code should be 2xx (e.g., 200). Only JPG or JPEG files up to 10 MB are allowed.\n",
        "example": "http://cdn.portal.com/image129.jpg"
      },
      "MainImage": {
        "required": [
          "url"
        ],
        "properties": {
          "url": {
            "$ref": "#/components/schemas/ExternalImageURL"
          }
        }
      },
      "Stock": {
        "type": "object",
        "description": "The quantity of the item in the seller's inventory. This feature is only available to Wallapop Pro users. See [Add stock to your items](https://ayuda.wallapop.com/hc/es-es/articles/24311666443025-A%C3%B1ade-stock-a-tus-art%C3%ADculos).",
        "required": [
          "units"
        ],
        "properties": {
          "units": {
            "type": "integer",
            "description": "The number of units you have available to sell of this item.\n"
          }
        }
      },
      "CreateItemRequest": {
        "type": "object",
        "required": [
          "item",
          "main_image"
        ],
        "properties": {
          "item": {
            "$ref": "#/components/schemas/Item"
          },
          "main_image": {
            "$ref": "#/components/schemas/MainImage"
          },
          "stock": {
            "$ref": "#/components/schemas/Stock"
          }
        }
      }
    }
  }
}
```

A successful request will net you a `201 Created` status, plus the `id` of your brand-new listing.

Want to check on your item later?
Just send a GET request to `/items/{id}`, using the item's specific `id`!

Deactivating published items
To stop showing an item (like a virtual hiding act!), send a **PUT** request to `/items/{id}/inactivate`. You’ll need a [Wallapop Pro subscription](https://ayuda.wallapop.com/hc/es-es/articles/23521878501137-Activaci%C3%B3n-y-desactivaci%C3%B3n-de-productos) for this magic. Want to bring it back? Just send a request to `/items/{id}/activate`.

## 5) Adding Images

Last but definitely not least, let's make your listing pop! In the previous example, while creating an item, we specified a `main_image` to feature at the top. Want to add more flair? Send a **POST** request to `/items/{id}/images`, including the image `url` and display `order`—starting with `0` for your first additional image!

Example
```shell cURL
curl -i -X POST \
  https://connect.wallapop.com/items/xpzpvny244z3/images \
  -H 'Authorization: Bearer <YOUR_TOKEN_HERE>' \
  -H 'Content-Type: application/json' \
  -d '{
    "url": "http://cdn.portal.com/image129.jpg",
    "order": 0
  }'
```

Request Body Schema
```json
{
  "$ref": "#/components/schemas/AddItemImageRequest",
  "components": {
    "schemas": {
      "ExternalImageURL": {
        "type": "string",
        "description": "Provide a direct link to the image without redirections. The HTTP response code should be 2xx (e.g., 200). Only JPG or JPEG files up to 10 MB are allowed.\n",
        "example": "http://cdn.portal.com/image129.jpg"
      },
      "AddItemImageRequest": {
        "required": [
          "url",
          "order"
        ],
        "properties": {
          "url": {
            "$ref": "#/components/schemas/ExternalImageURL"
          },
          "order": {
            "type": "integer",
            "minimum": 0,
            "description": "The order the image will display in the Wallapop interface."
          }
        }
      }
    }
  }
}
```

When all goes well, you'll get a `201 Created` status on your image upload, plus its `id`.

No longer like an image you uploaded?
Just send a DELETE request to `/items/{itemId}/images/{imageId}`, using the image's specific `id`!

## 6) Managing Item Availability

As your inventory grows, managing which items are visible to buyers becomes crucial. This is especially important for **Wallapop PRO** subscribers,
who have specific limits on the number of active listings allowed in their plan.

### Check Item Status (Active vs Inactive)

To retrieve your full inventory, send a **GET** request to `/items`. Be aware that this list returns **both** active (published) and inactive (hidden) items.

You must check the `inactive` field in the response to determine the status of each item:

* **Active Item:** The `inactive` field is **omitted** (not present) in the JSON object. These items are visible to buyers and count towards your quota.
* **Inactive Item:** The response includes an `inactive` object with `"flag": true`. These items are hidden.


Example Request
```shell cURL
curl -i -X GET \
  https://connect.wallapop.com/items \
  -H 'Authorization: Bearer <YOUR_TOKEN_HERE>'
```

JSON: Active Item
```json
{
  "id": "xpzpvny244z3",
  "title": "Air Jordan shoes",
  "price": { "cash_amount": 75.50, "currency": "EUR" }
  // 'inactive' field is MISSING here
}
```

JSON: Inactive Item
```json
{
  "id": "abc123456789",
  "title": "Winter Coat",
  "price": { "cash_amount": 120.00, "currency": "EUR" },
  "inactive": {
    "flag": true
  }
}
```

To specifically view items that are hidden or have exceeded your quota, use the dedicated endpoint **`GET /items/inactive`**. This is the most efficient way to identify items waiting to be published.

Pagination
Both endpoints support pagination for large inventories. The response includes a `meta.pagination.next` token. To retrieve the next page of results, simply make the same request again adding the `since` query parameter with that token.

### Real-time Monitoring via Webhooks

Alternatively, instead of constantly polling the API to check for status changes, you can integrate [**Webhooks**](/pages/guides/webhooks) to receive real-time updates.

For instance, by subscribing to the `ITEM_INACTIVATED` event, your system will be notified immediately when an item is deactivated (e.g., due to subscription limits or manual actions).

When the event occurs, Wallapop will send a `POST` request to your configured webhook URL with the following JSON structure:

```json
{
  "id": "5b7263ce-69cd-4344-ae4a-61d226370eb5",
  "type": "ITEM_INACTIVATED",
  "occurred_on": 1752820579294,
  "data": {
    "item_id": "9nz0m00eejon"
  }
}
```

### Choose the Right Action

Before you simply deactivate an item to free up space, check its real-world status. Using the correct endpoint is vital for keeping your sales history accurate.

| Item Status | Recommended Action | Endpoint |
|  --- | --- | --- |
| **Sold outside Wallapop** | Mark it as sold. This removes it from the marketplace but keeps it in your sales history. | `PUT /items/{id}/sold` |
| **No longer available** | If the item was lost, broken, or you simply want to delete it permanently. | `DELETE /items/{id}` |
| **Seasonal / Rotational** | If you want to hide it temporarily to free up space (e.g., hiding winter coats in summer). | `PUT /items/{id}/inactivate` |


### Swapping Items (Rotation)

If you have confirmed the item wasn't sold or deleted, and you simply need to rotate stock because you reached your subscription limit, follow these steps:

1. **Deactivate an Item:** Identify a published item you want to hide and call `PUT /items/{id}/inactivate`.
2. **Activate an Item:** Once a slot is open, choose an item from your inactive list and call `PUT /items/{id}/activate`.


Deactivate (Hide)
```shell cURL
curl -i -X PUT \
  https://connect.wallapop.com/items/xpzpvny244z3/inactivate \
  -H 'Authorization: Bearer <YOUR_TOKEN_HERE>'
```

Activate (Publish)
```shell cURL
curl -i -X PUT \
  https://connect.wallapop.com/items/xpzpvny244z3/activate \
  -H 'Authorization: Bearer <YOUR_TOKEN_HERE>'
```

Subscription Limits
The `/activate` endpoint requires an available slot in your Wallapop PRO subscription. If you are already at your maximum limit, you must deactivate (or mark as sold/delete) an item before activating another.

You can check your current usage per category group with **`GET /items/limits`**,  the response includes `total`, `used`, `available`, and the `category_ids` sharing each limit.

## Next steps

Your listing is live! Before you get ready for a buyer to swoop in, we recommend reviewing our [Items API](/apis/items/items) to learn how to manage your inventory. This will help you keep your listings up-to-date.

Once you are comfortable with managing your listings, you can head on over to our [Transactions Guide](/pages/guides/transactions)!

Need to view all of your items for sale?
Send a GET request to `/items`! If you have many items for sale, you can paginate the results instead of receiving a large list all at once.