Products

Products are definitions of physical products in our webshop. These products are usually supplied and delivered by the organization itself.

Abilities

Every endpoint on this page requires a token with the matching ability. The products.* abilities are the current names; tokens with the legacy product.* abilities keep working on the same routes. A token missing the ability gets an HTTP 403.

  • Name
    products.get
    Type
    ability
    Description

    List and inspect products. Legacy: product.get.

  • Name
    products.store
    Type
    ability
    Description

    Create a single product and batch-upsert products. Legacy: product.store.

  • Name
    products.update
    Type
    ability
    Description

    Update a product. Legacy: product.update.

  • Name
    products.delete
    Type
    ability
    Description

    Archive and restore a product. Legacy: product.delete.

Everything is scoped to the organizations the token's user has access to. Products of other organizations are never returned or modified.

The products model

The products model contains information about the product itself and extra information regarding webshop availability. The model is defined as follows:

Properties

  • Name
    identifier
    Type
    string
    Description

    Unique identifier for the product.

  • Name
    price
    Type
    float
    Description

    The sale price of the product.

  • Name
    points
    Type
    integer
    Description

    The sale amount of points of the product.

  • Name
    show_title
    Type
    boolean
    Description

    whether or not to show the title in the webshop.

  • Name
    show_subtitle
    Type
    boolean
    Description

    whether or not to show the subtitle in the webshop.

  • Name
    organization
    Type
    object
    Description

    Contains in formation about the products organization. contains: ['identifier', 'name']

  • Name
    primary_color
    Type
    string
    Description

    A Hexadecimal color code for the primary color of the product (background color for the webshop).

  • Name
    text_color
    Type
    string
    Description

    A Hexadecimal color code for the text color of the product (text color for the webshop).

  • Name
    ribbon_color
    Type
    string
    Description

    A Hexadecimal color code for the ribbon color of the product (label color for the webshop).

  • Name
    title
    Type
    string
    Description

    The title of the product.

  • Name
    subtitle
    Type
    string
    Description

    The subtitle of the product.

  • Name
    thumbnail_url
    Type
    string|url
    Description

    The URL to the image of the product.

  • Name
    start_date
    Type
    timestamp
    Description

    Used to set the availablity of the product in the webshop.

  • Name
    end_date
    Type
    timestamp
    Description

    Used to set the availablity of the product in the webshop.

  • Name
    use_start_and_end
    Type
    boolean
    Description

    whether or not to use a start and end date in the webshop.

  • Name
    sale
    Type
    boolean
    Description

    whether or not the product is on sale.

  • Name
    sale_points
    Type
    integer
    Description

    The sale amount of points of the product.

  • Name
    sale_price
    Type
    float
    Description

    The sale price of the product.

  • Name
    sale_text
    Type
    string
    Description

    The text to show when the product is on sale.

  • Name
    stock
    Type
    integer
    Description

    The amount of stock of the product.

  • Name
    use_stock
    Type
    boolean
    Description

    whether or not to use a stock in the webshop.

  • Name
    type
    Type
    string
    Description

    pickup or delivery.

  • Name
    vat
    Type
    float
    Description

    The VAT percentage of the product (for example 21).

  • Name
    purchase_price
    Type
    float|null
    Description

    The purchase (cost) price of the product.

  • Name
    b2b_price_cents
    Type
    integer|null
    Description

    The B2B price of the product in cents. null when no B2B price is set.

  • Name
    external_id
    Type
    string|null
    Description

    Your own identifier of the product (for example a SKU). Set by POST /products/batch.

  • Name
    integration_id
    Type
    integer|null
    Description

    The integration the product was pushed by. Together with the organization and external_id this is the upsert key of the batch endpoint. null for products created in the dashboard, the marketplace or Shopify.

  • Name
    archived
    Type
    boolean
    Description

    Whether the product is archived. Archived products are not available in the webshop.

  • Name
    created_at
    Type
    timestamp
    Description

    A timestamp when the product was created.

  • Name
    updated_at
    Type
    timestamp
    Description

    A timestamp when the product was last updated.

Note

Because a user can have access to multiple organizations we require a organization_id to be provided for most requests. We will also return an organization reference in each response.


GET/products

List all products

This endpoint returns a list of all the products the currently authenticated user has access to, ordered by creation (oldest first). Archived products are included; check the archived flag. The description is not part of the list output; use Inspect a product for it.

Required headers

  • Name
    Authorization
    Type
    string
    Description

    The token itself as a bearer token.

Abilities

  • Name
    products.get
    Type
    string
    Description

    The scope required to access this endpoint (legacy product.get is also accepted).

Query parameters

  • Name
    organization_id
    Type
    string
    Description

    Optional. Only return products of this organization (organization identifier).

  • Name
    external_id
    Type
    string
    Description

    Optional. Only return products with this external_id.

  • Name
    integration_id
    Type
    integer
    Description

    Optional. Only return products pushed by this integration (for example 0, the default of the batch endpoint).

  • Name
    page
    Type
    integer
    Description

    Optional. Page number, starting at 1. Pagination is only applied when page or per_page is present.

  • Name
    per_page
    Type
    integer
    Description

    Optional. Products per page, default 100, maximum 500 (higher values are capped at 500).

Without page and per_page all matching products are returned in one response, without meta. With either of them the response contains a meta object (current_page, per_page, total, last_page). For large catalogues always paginate.

Request

GET
/products
curl -X GET https://api.walletapp.co/products 
-H "Content-Type: application/json"
-H "Accept: application/json"
-H "Authorization: Bearer <your_token>"

Response

{
    "message": "Request successful",
    "data": [
        {
            "created_at": "<timestamp>",
            "end_date": "<timestamp>",
            "identifier": "<product_id>",
            "organization": {
                "name": "<organization_name>",
                "identifier": "<organization_id>"
            },
            "points": 0,
            "price": 0,
            "primary_color": "<hex_color>",
            "sale": 0,
            "sale_points": 0,
            "sale_price": 0.00,
            "sale_text": "<sale_text>",
            "show_subtitle": 0,
            "show_title": 0,
            "start_date": "<timestamp>",
            "stock": 0,
            "subtitle": "<subtitle>",
            "text_color": "<hex_color>",
            "thumbnail_url": "<url>",
            "title": "<title>",
            "updated_at": "<timestamp>",
            "use_start_and_end": 0,
            "use_stock": 0
        }
    ],
    ...
}

Filtered + paginated

curl -X GET "https://api.walletapp.co/products?organization_id=<organization_id>&integration_id=0&page=1&per_page=500" \
-H "Accept: application/json" \
-H "Authorization: Bearer <your_token>"

Response (paginated)

{
    "message": "Request successful",
    "data": [
        {
            "archived": 0,
            "b2b_price_cents": 1000,
            "external_id": "SKU-1",
            "identifier": "<product_id>",
            "integration_id": 0,
            "organization": {
                "name": "<organization_name>",
                "identifier": "<organization_id>"
            },
            "price": 12.5,
            "purchase_price": "6.00",
            "title": "Wine",
            "type": "pickup",
            "vat": "21.00",
            ...
        }
    ],
    "meta": {
        "current_page": 1,
        "per_page": 500,
        "total": 1240,
        "last_page": 3
    }
}

POST/products

Create a product

This endpoint allows you to create a single product. To create or update many products from a backoffice, use POST /products/batch instead.

Required headers

  • Name
    Authorization
    Type
    string
    Description

    The token itself as a bearer token.

Abilities

  • Name
    products.store
    Type
    string
    Description

    The scope required to access this endpoint (legacy product.store is also accepted).

Request body

  • Name
    title
    Type
    string|Required
    Description

    The title of the product.

  • Name
    subtitle
    Type
    string|Required
    Description

    The subtitle of the product.

  • Name
    organization_id
    Type
    string|Required
    Description

    The identifier of the organization the product should be created for.

  • Name
    description
    Type
    string
    Description

    The description of the product.

  • Name
    thumbnail_url
    Type
    string|url
    Description

    A valid url to the thumbnail image of the product.

  • Name
    show_title
    Type
    boolean
    Description

    Whether or not to show the title of the product.

  • Name
    show_subtitle
    Type
    boolean
    Description

    Whether or not to show the subtitle of the product.

  • Name
    price
    Type
    float
    Description

    The webshop price of the product.

  • Name
    points
    Type
    integer
    Description

    The webshop amount of points the product should cost.

  • Name
    use_stock
    Type
    boolean
    Description

    Whether or not the product makes use of stock.

  • Name
    stock
    Type
    integer|Required
    Description

    The amount of stock the product has.

  • Name
    use_start_and_end
    Type
    boolean
    Description

    Whether or not the product makes use of start and end dates.

  • Name
    sale
    Type
    boolean
    Description

    Whether or not the product is on sale.

  • Name
    sale_price
    Type
    float
    Description

    The sale price of the product.

  • Name
    sale_points
    Type
    integer
    Description

    The sale amount of points the product should cost.

  • Name
    sale_text
    Type
    string
    Description

    The sale text of the product.

  • Name
    start_date
    Type
    timestamp
    Description

    The start date of the product.

  • Name
    end_date
    Type
    timestamp
    Description

    The end date of the product.

  • Name
    type
    Type
    string
    Description

    Optional. Can be pickup or delivery. Use delivery for physical products.

  • Name
    shopify_id
    Type
    string
    Description

    Optional. A unique identifier that links the product to a Shopify product.

Request

POST
/products
curl -X POST https://api.walletapp.co/products \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "Authorization: Bearer <your_token>" \
-d '{
    "title": "<title>",
    "subtitle": "<subtitle>",
    "organization_id": "<organization_id>",
    "description": "<description>",
    "thumbnail_url": "<image_url>",
    "show_title": true,
    "show_subtitle": true,
    "price": 12.50,
    "points": 123,
    "use_stock": true,
    "stock": 12,
    "use_start_and_end": true,
    "start_date": "2022-01-01",
    "end_date": "2023-01-01",
    "sale": true,
    "sale_price": 10.00,
    "sale_points": 100,
    "sale_text": "10% Off",
    "type": "delivery",
    "shopify_id": "123456789"
}'

Response

{
  "message": "Request successful",
  "data": {
    "identifier": "<product_id>",
    "title": "<title>",
    "subtitle": "<subtitle>",
    "organization": {
      "name": "<organization_name>",
      "identifier": "<organization_id>"
    },
    "thumbnail_url": "<url>",
    "description": "<description>",
    "price": 12.5,
    "points": 123,
    "stock": 12,
    "sale": true,
    "sale_price": 10.0,
    "sale_points": 100,
    "sale_text": "10% Off",
    "show_title": true,
    "show_subtitle": true,
    "start_date": "2022-01-01",
    "end_date": "2023-01-01",
    "use_stock": true,
    "use_start_and_end": true,
    "type": "delivery",
    "shopify_id": "gid://shopify/Product/123456789",
    "created_at": "<timestamp>",
    "updated_at": "<timestamp>"
  }
}

POST/products/batch

Batch upsert products

This endpoint creates or updates up to 500 products of one organization in a single call. It is meant for keeping the product catalogue in sync with your own backoffice or ERP.

Each product is matched on the upsert key: the organization, the integration_id (default 0) and your external_id. A product that does not exist for that key yet is created; an existing one is updated. Products created in the dashboard, the marketplace or Shopify (no integration_id) are never matched, so this endpoint cannot touch them.

Every row is validated and saved on its own: a bad row never fails the rest of the batch. The response always has HTTP 200 and contains a result per row.

Required headers

  • Name
    Authorization
    Type
    string
    Description

    The token itself as a bearer token.

Abilities

  • Name
    products.store
    Type
    string
    Description

    The scope required to access this endpoint (legacy product.store is also accepted).

Request body

  • Name
    organization_id
    Type
    string|Required
    Description

    The identifier of the organization the products belong to.

  • Name
    integration_id
    Type
    integer
    Description

    Optional, default 0. A non-negative integer that identifies your integration. Use a different value per source system if more than one system pushes products for the same organization; each integration has its own external_id namespace.

  • Name
    products
    Type
    array|Required
    Description

    1 to 500 product rows. Each row is an object with the fields below.

Product row

  • Name
    external_id
    Type
    string|Required
    Description

    Your own identifier of the product (for example a SKU), max 191 characters. Must be unique within the batch; a repeated external_id fails as a duplicate.

  • Name
    title
    Type
    string
    Description

    Required when the product is created. Max 191 characters.

  • Name
    price
    Type
    float
    Description

    Required when the product is created. The sale price (0 – 9999999).

  • Name
    vat
    Type
    float
    Description

    Required when the product is created. The VAT percentage (0 – 100).

  • Name
    subtitle
    Type
    string|null
    Description

    The subtitle, max 191 characters.

  • Name
    description
    Type
    string|null
    Description

    The description as plain text, max 20000 characters.

  • Name
    b2b_price_cents
    Type
    integer|null
    Description

    The B2B price in cents (0 – 4294967295). Send null to clear it.

  • Name
    purchase_price
    Type
    float|null
    Description

    The purchase (cost) price (0 – 9999999).

  • Name
    type
    Type
    string
    Description

    pickup or delivery, max 50 characters.

  • Name
    thumbnail_url
    Type
    string|url|null
    Description

    A URL to the product image, max 2048 characters. Stored as given (the image is not downloaded).

  • Name
    archived
    Type
    boolean
    Description

    Archive (true) or restore (false) the product.

On an update only the keys present in the row are written; keys you leave out keep their current value. There is no stock field: stock is not synchronised through this endpoint.

Row status

  • Name
    created
    Type
    status
    Description

    A new product was created. identifier is the new product identifier.

  • Name
    updated
    Type
    status
    Description

    An existing product was found and at least one field changed.

  • Name
    unchanged
    Type
    status
    Description

    An existing product was found and all sent fields already had these values. Nothing was written.

  • Name
    failed
    Type
    status
    Description

    The row was not saved. reason explains why (for example a validation message or a duplicate external_id).

Idempotent replay

Sending the same batch again gives the same end state: rows that were created or updated the first time are reported as unchanged. A batch that timed out on your side can therefore safely be retried.

Errors

  • Name
    401
    Type
    Unauthorized
    Description

    The organization_id is missing, unknown, or not accessible with this token. Unknown and foreign organizations return the same response.

  • Name
    403
    Type
    Forbidden
    Description

    The token does not have the products.store (or legacy product.store) ability.

  • Name
    422
    Type
    Unprocessable
    Description

    products is missing, empty, not a list, or has more than 500 rows; or integration_id is not a non-negative integer. Nothing is processed.

Row-level problems never produce a 4xx; they are reported as failed rows in a 200 response.

Request

POST
/products/batch
curl -X POST https://api.walletapp.co/products/batch \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "Authorization: Bearer <your_token>" \
-d '{
    "organization_id": "<organization_id>",
    "integration_id": 0,
    "products": [
        {
            "external_id": "SKU-1",
            "title": "Wine",
            "price": 12.50,
            "vat": 21,
            "b2b_price_cents": 1000,
            "purchase_price": 6,
            "subtitle": "<subtitle>",
            "description": "<description>",
            "type": "pickup",
            "thumbnail_url": "https://example.com/sku-1.png",
            "archived": false
        },
        {
            "external_id": "SKU-2",
            "price": 9.95
        }
    ]
}'

Response

{
    "message": "Request successful",
    "data": {
        "summary": {
            "total": 2,
            "created": 1,
            "updated": 0,
            "unchanged": 0,
            "failed": 1
        },
        "results": [
            {
                "index": 0,
                "external_id": "SKU-1",
                "status": "created",
                "identifier": "<product_id>"
            },
            {
                "index": 1,
                "external_id": "SKU-2",
                "status": "failed",
                "reason": "The title field is required."
            }
        ]
    }
}

Response (422, too many rows)

{
    "message": "The provided request was invalid (errors: 1)",
    "errors": {
        "products": "A batch can contain at most 500 products"
    }
}

GET/products/:identifier

Inspect a product

The endpoint allows you to fetch a product by its identifier. Archived products are not returned (HTTP 422); restore them first or find them through List all products.

Required headers

  • Name
    Authorization
    Type
    string
    Description

    The token itself as a bearer token.

Abilities

  • Name
    products.get
    Type
    string
    Description

    The scope required to access this endpoint (legacy product.get is also accepted).

Route parameters

  • Name
    identifier
    Type
    string
    Description

    The identifier of the product you want to fetch.

Request

GET
/products/:identifier
curl -X GET https://api.walletapp.co/products/:identifier
-H "Content-Type: application/json"
-H "Accept: application/json"
-H "Authorization: Bearer <your_token>"

Response

{
    "message": "Request successful",
    "data": {
        "created_at": "<timestamp>",
        "end_date": "<timestamp>",
        "identifier": "<product_id>",
        "organization": {
            "name": "<organization_name>",
            "identifier": "<organization_id>"
        },
        "points": 0,
        "price": 0,
        "primary_color": "<hex_color>",
        "sale": 0,
        "sale_points": 0,
        "sale_price": 0.00,
        "sale_text": "<sale_text>",
        "show_subtitle": 0,
        "show_title": 0,
        "start_date": "<timestamp>",
        "stock": 0,
        "subtitle": "<subtitle>",
        "text_color": "<hex_color>",
        "thumbnail_url": "<url>",
        "title": "<title>",
        "updated_at": "<timestamp>",
        "use_start_and_end": 0,
        "use_stock": 0
    }
}

PUT/products/:identifier

Update a product

This endpoint allows you to modify a product. Only the fields you send are changed.

Required headers

  • Name
    Authorization
    Type
    string
    Description

    The token itself as a bearer token.

Abilities

  • Name
    products.update
    Type
    string
    Description

    The scope required to access this endpoint (legacy product.update is also accepted).

Route parameters

  • Name
    identifier
    Type
    string
    Description

    The identifier of the product.

Request body

  • Name
    title
    Type
    string
    Description

    The title of the product.

  • Name
    subtitle
    Type
    string
    Description

    The subtitle of the product.

  • Name
    organization_id
    Type
    string
    Description

    The identifier of the organization the product should be created for.

  • Name
    description
    Type
    string
    Description

    The description of the product.

  • Name
    thumbnail_url
    Type
    string|url
    Description

    A valid url to the thumbnail image of the product.

  • Name
    show_title
    Type
    boolean
    Description

    whether or not to show the title of the product.

  • Name
    show_subtitle
    Type
    boolean
    Description

    whether or not to show the subtitle of the product.

  • Name
    price
    Type
    float
    Description

    The webshop price of the product.

  • Name
    points
    Type
    integer
    Description

    The webshop amount of points the product should cost.

  • Name
    use_stock
    Type
    boolean
    Description

    whether or not the product makes use of stock.

  • Name
    stock
    Type
    integer
    Description

    The amount of stock the product has.

  • Name
    use_start_and_end
    Type
    boolean
    Description

    whether or not the product makes use of start and end dates.

  • Name
    sale
    Type
    boolean
    Description

    whether or not the product is on sale.

  • Name
    sale_price
    Type
    float
    Description

    The sale price of the product.

  • Name
    sale_points
    Type
    integer
    Description

    The sale amount of points the product should cost.

  • Name
    sale_text
    Type
    string
    Description

    The sale text of the product.

  • Name
    start_date
    Type
    timestamp
    Description

    The start date of the product.

  • Name
    end_date
    Type
    timestamp
    Description

    The end date of the product.

  • Name
    type
    Type
    string
    Description

    pickup or delivery.

  • Name
    shopify_id
    Type
    string
    Description

    A unique identifier that links the product to a Shopify product.

  • Name
    b2b_price_cents
    Type
    integer|null
    Description

    The B2B price in cents (0 – 4294967295).

  • Name
    purchase_price
    Type
    float|null
    Description

    The purchase (cost) price of the product.

  • Name
    archived
    Type
    boolean
    Description

    Archive (true) or restore (false) the product. Only applied to products pushed by a backoffice; use DELETE / PATCH otherwise.

Request

PUT
/products/:identifier
curl -X PUT https://api.walletapp.co/products/:identifier
-H "Content-Type: application/json"
-H "Accept: application/json"
-H "Authorization: Bearer <your_token>"
-d '{
    "title":"<title>",
    "subtitle":"<subtitle>",
    "description":"<description>",
    "organization_id":"<organization_id>",
    "thumbnail_url":"<image_url>",
    "show_title": true,
    "price": 12.50,
    "primary_color":"#ff00ff",
    "text_color":"#0000ff",
    "show_subtitle":true,
    "points": 123,
    "use_stock":true,
    "use_start_and_end": true,
    "sale": true,
    "sale_text": "<sale_text>",
    "sale_price":12.50,
    "sale_points":12,
    "stock":12,
    "start_date":"2022-01-01",
    "end_date":"2023-01-01",
    "type": "delivery",
    "shopify_id": "123456789"
}'

Response

{
"message": "Request successful",
"data": {
    "created_at": "<timestamp>",
    "end_date": "<timestamp>",
    "identifier": "<product_id>",
    "organization": {
        "name": "<organization_name>",
        "identifier": "<organization_id>"
    },
    "points": 0,
    "price": 0,
    "primary_color": "<hex_color>",
    "sale": 0,
    "sale_points": 0,
    "sale_price": 0.00,
    "sale_text": "<sale_text>",
    "show_subtitle": 0,
    "show_title": 0,
    "start_date": "<timestamp>",
    "stock": 0,
    "subtitle": "<subtitle>",
    "text_color": "<hex_color>",
    "thumbnail_url": "<url>",
    "title": "<title>",
    "updated_at": "<timestamp>",
    "use_start_and_end": 0,
    "use_stock": 0
}
}

DELETE/products/:identifier

Archive a product

The endpoint archives a product. The product is not deleted: it disappears from the webshop and can be brought back with Restore a product. Archiving an already archived product returns HTTP 422. Marketplace products (an external_id without an integration_id) cannot be archived (HTTP 422).

Required headers

  • Name
    Authorization
    Type
    string
    Description

    The token itself as a bearer token.

Abilities

  • Name
    products.delete
    Type
    string
    Description

    The scope required to access this endpoint (legacy product.delete is also accepted).

Route parameters

  • Name
    identifier
    Type
    string
    Description

    The identifier of the product.

Request

DELETE
/products/:identifier
curl -X DELETE https://api.walletapp.co/products/:identifier
-H "Content-Type: application/json"
-H "Accept: application/json"
-H "Authorization: Bearer <your_token>"

Response

{
    "message": "Request successful",
    "data": "Product archived"
}

PATCH/products/:identifier

Restore a product

The endpoint restores an archived product. Restoring a product that is not archived returns HTTP 422. Marketplace products cannot be restored through the API (HTTP 422).

Required headers

  • Name
    Authorization
    Type
    string
    Description

    The token itself as a bearer token.

Abilities

  • Name
    products.delete
    Type
    string
    Description

    The scope required to access this endpoint (legacy product.delete is also accepted).

Route parameters

  • Name
    identifier
    Type
    string
    Description

    The identifier of the product.

Request

PATCH
/products/:identifier
curl -X PATCH https://api.walletapp.co/products/:identifier
-H "Content-Type: application/json"
-H "Accept: application/json"
-H "Authorization: Bearer <your_token>"

Response

{
    "message": "Request successful",
    "data": "Product restored"
}