If you have a catalog with a big amount of products and quickly-changing inventory, using product feeds might not be a viable option for you. Instead of using a product feed to update a catalog, it's possible to use Meta's Catalog Batch API to send real-time information about the products that have changed via HTTP requests.
In order for you to use our features such (Image Templates, Dynamic Slideshows, Product Insights, etc.) with Catalog Batch API, we provide an endpoint where you send HTTP requests, we enhance products and forward them to Meta.
NOTE: We don't support API integration combined with product feed source file (XML or CSV feed). Once the catalog is whitelisted for our API, it should not contain any other data source.
Catalog Batch API
ROI Hunter API is similar to Meta API, but there are a few differences and specifics. All implementation details are described in this article. We highly recommend studying it carefully.
The endpoint for ROI Hunter is:
POST
https://products-api.roihunter.com/api/v2/catalogs/{catalogMetaId}/batch
You need an access token to send HTTP requests. Contact us, and we will provide you with the token.
HTTP request body
Field | Description |
type: string | Required. |
type: boolean | Optional. Default value:
If |
type: array<object> | Required.
An array of batch request objects. Batch request object should contain the following fields:
|
Every HTTP request must contain non-empty requests field, containing requests of CREATE, UPDATE or DELETE method. Every request method has some specifics, documented below.
CREATE method
Use this method to add new products to the catalog. CREATE requests on products which already exist are accepted and converted to updates.
Required fields in data
Field | Description |
type: string | Product's name. Max size: 100. |
type: integer | The price multiplied by 100. |
type: string | Currency for the value specified. Use ISO 4217 for currency standards. |
type: string | Link to merchant's site where someone can buy the product. |
type: string | Link to product image used in the ad. |
type: string | Product's description. Max size: 5000. |
At least one of the following fields must be set in order to create valid product.
type: string | Product's brand. |
type: string | Global Trade Item Number can include |
type: string | Unique manufacturer ID for product. This field is usually called |
Optional fields in data
type: array<string> | URLs for up to 20 different images. |
type: object | An object containing |
type: string | Group of people who are the same age or a similar age. Accepted values are |
type: object | Links to mobile apps. An object containing mobile platforms |
type: string |
|
type: float | Radius specified in kilometers from the given |
type: string | Google product category (GPC) for the product. Use the category's taxonomy path or its ID number, listed here. |
type: string | Product color. Max size: 100. |
type: string | Product's condition: |
type: string | Additional information about product. Max size: 100. |
type: string | Additional information about product. Max size: 100. |
type: string | Additional information about product. Max size: 100. |
type: string | Additional information about product. Max size: 100. |
type: string | Additional information about product. Max size: 100. |
type: integer | Additional numeric information about product. A whole positive number is required. |
type: integer | Additional numeric information about product. A whole positive number is required. |
type: integer | Additional numeric information about product. A whole positive number is required. |
type: integer | Additional numeric information about product. A whole positive number is required. |
type: integer | Additional numeric information about product. A whole positive number is required. |
type: string | Gender for sizing. Values include |
type: object | Address of the product importer. |
type: string | Name of the product importer. |
type: array<string> | Use up to 5000 labels per product and 110 characters per label. |
type: string | The manufacturer information. |
type: string | Material of the product. |
type: string | 2-letter code of a country. |
type: string | Pattern or graphic print on the product. Max size: 100. |
type: float | Product priority. Decimal number between 0.7 and 1.3. |
type: float | Product priority. Decimal number between 0.7 and 1.3. |
type: float | Product priority. Decimal number between 0.7 and 1.3. |
type: float | Product priority. Decimal number between 0.7 and 1.3. |
type: float | Product priority. Decimal number between 0.7 and 1.3. |
type: string | Retailer-defined category for the product. Max size: 750. |
type: string | Advertisers can use it to group products together. This field is usually called |
type: integer | The sale price multiplied by 100. |
type: string | Start and end date and time for the sale, separated by a slash. Write the start and end dates as YYYY-MM-DD. Add a "T" after each date and then include the time. Write the time in a 24-hour format (0:00 to 23:59). Example: 2014-11-01T12:00-0300/2014-12-01T00:00-0300. |
type: array<object> | Shipping information. Array of objects containing |
type: string | Size of the product. Example: |
type: array<object> | URLs and tags for videos to be used in your ads. Tags are optional and, if used, should describe what is in the video.
Each product can have up to 20 videos, where every video can have up to 1 tag.
Video object should contain:
|
type: string |
|
type: string | The ID of the vendor/seller that sells the product. |
Example HTTP request
{
"access_token": "<ACCESS_TOKEN>",
"requests": [{
"method": "CREATE",
"retailer_id": "retailer_id_1",
"data": {
"applinks": {
"ios": [{
"url": "example-ios://example",
"app_store_id": 123,
"app_name": "app name"
}],
"android": [{
"app_name": "app name",
"package": "com.package.name",
"url": "example-android://example"
}]
},
"availability": "in stock",
"brand": "Some brand",
"category": "t-shirts",
"condition": "new",
"currency": "USD",
"description": "Product description",
"image_url": "http://www.images.example.com/t-shirts/1.png",
"name": "Product name",
"price": 1000,
"retailer_product_group_id": "product-group-1",
"shipping": [{
"shipping_country": "US",
"shipping_region": "CA",
"shipping_service": "service",
"shipping_price_value": "10",
"shipping_price_currency": "USD"
}],
"url": "http://www.images.example.com/t-shirts/1.png",
"video": [{
"url":"http://example.com/video_1.mp4",
"tag": ["Summer"]
}]
}
}]
}
Example response (OK)
Response contains a handle, which can be used to check the status of asynchronous processing of the batch of products. One handle is returned for the whole request.
Status code: 200
Response body:
{
"handles": [
"Aczq4HLYFA8flS0gWr5YzLuShNtJnxFh5K4kLJQeY..."
]
}
Example response (product errors/warnings)
If product in the HTTP request has an invalid product URL, then it cannot be stored. This problem is returned as error. If product data contain an unsupported extra field, then this extra field is ignored. This is returned as a warning.
Status code: 200
Response body:
{
"handles":[
"Aczq4HLYFA8flS0gWr5YzLuShNtJnxFh5K4kLJQeY..."
],
"validation_status": [
{
"retailer_id": "1",
"errors": [
{
"message": "Product has the attribute 'URL' in unsupported format. Please make sure every product has a valid attribute 'URL' starting with one of: 'http://', 'https://', 'ftp://', 'sftp://'."
}
],
"warnings": [
{
"message": "The request contains unsupported product fields, which will be ignored. Ignored fields: {'some_field'}"
}
]
}
]
}
Example response (no changes)
HTTP request, which was not forwarded to Meta at all, because there were no changes compared to the previous state
Status code: 200
Response body:
{
"message": "There are no applicable requests in provided payload. No API calls to Meta will be made."
}Example response (invalid request body)
HTTP request, which is missing method (CREATE/UPDATE/DELETE) in the data.
Status code: 400
Response body:
{
"error": {
"code": "request_invalid_data",
"message": "Errors: required key not provided @ data['requests'][0]['method']",
"severity": "critical"
}
}
Example response (exceeding rate limit)
HTTP request, which exceeded API rate limit (you can ask Meta to increase the API limits for you).
Status code: 400
Response body:
{
"error": {
"message": "Calls to this api have exceeded the rate limit. (613)"
}
}
Example response (server error)
HTTP request has failed unexpectedly
Status code: 500
Response body:
{
"error": {
"message": "An unexpected error has occurred. Please retry your request later."
}
}
UPDATE method
Use this method to update the values of existing products in catalog. This method doesn’t have any required fields, the only limitation is that at least one field to update must be sent.
Example HTTP request
{
"access_token": "<ACCESS_TOKEN>",
"requests": [
{
"method": "UPDATE",
"retailer_id": "retailer_id_1",
"data": {
"price": 800
}
}
]
}
Example response (OK)
Response contains a handle, which can be used to check the status of asynchronous processing of the batch of products. One handle is returned for the whole request.
Status code: 200
Response body:
{
"handles": [
"Aczq4HLYFA8flS0gWr5YzLuShNtJnxFh5K4kLJQeY..."
]
}
Example response (some products not changed)
When HTTP requests contains more products, but some of them did not change comparing to previous state, then they are not forwarded to Meta and retailer IDs of such products are returned in unchanged_products.
Status code: 200
Response body:
{
"handles": [
"Aczq4HLYFA8flS0gWr5YzLuShNtJnxFh5K4kLJQeY..."
],
"unchanged_products": {
"message": "Some of the products already contain given changes. Updates of those products will not be sent to FB again.",
"retailer_ids": [
"2"
]
}
}
DELETE method
Use this method to delete products in catalog.
Example HTTP request
{
"access_token": "<ACCESS_TOKEN>",
"requests": [
{
"method": "DELETE",
"retailer_id": "retailer_id_1"
}
]
}
Limitations
Meta limits the HTTP request to contain up to 5000 products.
ROI Hunter does not apply any rate limit on the API requests. But there is a limit applied by Meta. In case you are hitting the rate limit for your catalog, please contact our Support team. We can request Meta Support to increase your limit. The rate limit on catalog is driven by the number of Facebook and Instagram users that saw products from yout catalog. See more about the calculation here.
Meta also has a limitation on how big payload can be in terms of Bytes. In case of too big payload, Meta will return an error with status code 500 and a response
{"error":{"code":1,"message":"Please reduce the amount of data you're asking for, then retry your request"}}In such a case you need to make your payload smaller and try again. We suggest sending up 5MB of the payload for safety and stability.More information about limitations can be seen also here.
Check Batch Request Status API
A successful batch update return handle, which can be used to check the status of the update. To check the status use the endpoint:
GET
https://products-api.roihunter.com/api/v2/catalogs/{catalogMetaId}
/check_batch_request_status
HTTP parameters
Parameter | Description |
type: string | Required. |
type: string | Unique handle of a batch request. |
type: boolean | When true the returned status will contain a list of product ids (retailer ids) for which the requests failed |
Example HTTP request
GET https://products-api.roihunter.com/api/v2/catalogs/123456/check_batch_request_status?access_token=AAA&handle=BBB&load_ids_of_invalid_requests=true
Example response (OK)
Status is finished what means that batch request with the corresponding handle was already processed. There are no errors, so all products were processed successfully.
Status code: 200
Response body:
{
"data": [
{
"handle": "Aczq4HLYFA8flS0gWr5YzLuShNtJnxFh5K4kLJQeY...",
"status": "finished",
"errors_total_count": 0,
"errors": [],
"warnings": []
}
]
}
Maintaining catalog quality
There will always be the risk that some requests fail. As you're only communicating changes with Catalog Batch API (instead of always providing the whole state of your catalog as with feed files), there's the possibility that the Catalog on Meta will start drifting apart from your actual inventory status. Thus, we recommend running full updates for all your products periodically, for example, once per day.
Features
ROI Hunter allows all its feed-related features also for API catalogs. You can
apply image templates, dynamic slideshows
connect product insights from Google Analytics, Google shopping and even connect the custom source with product data
promote products dynamically filtered according
We recommend you to not change this kind of settings too frequently. Bear in mind that if you e.g. apply an image template, we have to re-upload the whole product inventory which can take even several hours based on the number of products and Meta limits.
FAQ
How long does it take to process the request?
It takes about a second to forward the request to Meta. But if you have also image templates applied on the catalog, it may take about a minute based on the count of created/updated products.
Even though we are constantly working on improvements, to ensure correct processing of HTTP requests, you should set the request timeout to 300 seconds, what corresponds to global server time-out of the API.
Is there any limitation in number of requests?
ROI Hunter does not apply any limitation. We accept the limitation defined by Meta for your Product catalog. See more information here.
What I need to check to make sure that my request passed properly and the product is in required state?
How should I react to request issues?
If the HTTP request ends with status code 500, or the error message says Calls to this api have exceeded the rate limit. (613), you can re-try the same request later.
For any other error, you should edit your request accordingly to make it valid. The issues are described in the response message and in batch request status.
How to fix invalid product state (incorrect availability, price, image) for API integrated catalog?
Make sure that you follow this documentation and your requests are passing. Check the latest request containing the product. If you cannot find it, you can just send the same product again.
Check the latest product data that you have sent to us - are they correct? Send the product again with the correct data.
If re-sending did not help, please get in touch with us for detailed investigation. Please provide: Product Catalog ID, problematic product(s) ID(s), expected and actual value.
How can I check that the product is in requested state on Meta?
You can check the products in Commerce Manager (former Catalog Manager) in Meta Business Manager, but please keep in mind that the images displayed on this page might not be always up to date.
If you have access to Meta Graph API, you can check the products also there. Details about Product Items can be seen in Meta Developer documentation.
In this example, you can see a call to check product availability, price and images. The product can be filtered by retailer_id field.
https://graph.facebook.com/v21.0/{catalogMetaId}/products?fields=id,name,retailer_id,url,availability,price,sale_price,image_url,image_cdn_urls,additional_image_urls,additional_image_cdn_urls&filter={"retailer_id":{"eq":"4"}}
Here is an example response in Graph API explorer tool:
The fields image_url and additional_image_urls represent the images provided by you (or by ROI Hunter when the image template is applied).
image_cdn_urls and additional_image_cdn_urls represent images fetched to Meta cache. If these fields are empty, Meta has not fetched the current images yet (no Pixel or App event has not been fired for the product since the last update).
In case of any additional questions, feel free to reach out to our Support team for more info. 😉
