API documentation

The API allows you as a client to send content to Besedo’s Implio for content moderation services. We at Besedo will then apply the agreed editorial rules and either accept, refuse or optionally edit the content.

Usage

Introduction

The Implio API is built on a RESTful HTTP architecture where the client (your application) makes HTTP requests to perform specific functions within the Implio system. All data must be passed as JSON. All requests are authenticated with an API key, which is verified by the API server before allowing any operations. All communication with the Besedo API is done over SSL. In addition to the RESTful HTTP API, we also support webhooks for receiving processed ads which also is the recommended integration method for retrieving ads.

Authentication

To be able to interact with the Implio system you need to be authenticated. Each request is signed by you the caller using a predefined API key, which is verified by Implio before allowing any operation. You will need to add the key in the header to each of your HTTP call. We use the key to both verify that you are allowed to send in content to us and to identify customers to make sure that only you can access your information.

Since the API is stateless there is no session that you need to keep track of at your side, instead each request should include the API key in the header.

Headers

To be able to communicate with Implio, these two headers need to be set.

HeaderValue
Content-Typeapplication/json
X-Api-KeyAPI key for your Implio team.

You can find this value in the API Integration settings of your Implio team, when logged in as a team administrator.

Here’s a sample request to the Implio API:

curl "https://api.implio.com/v1/ads" -H "X-Api-Key:
XhETCYeYJSaN4YQKucIXdDWlUBWIsAmREsZn3kDzS3tnvR" -H "content-type: 
application/json" -d '[ 
   { 
     "id": "23445", 
     "content": { 
       "title": "My title", 
       "body": "I want to sell XYZ." 
     } 
   }
 ]'

Available Resources

POST/ads Success status: 202

Allows a batch of ads to be submitted to Implio.

Two types of requests can be made. They are formatted almost identically, but serve a different purpose:

  • Moderation requests: used for sending ads for moderation
  • Update requests: used for sending ads for storage or update

Moderation request

Send in a batch of ads for moderation.

The request body is expressed in JSON. The root is an array of objects representing a batch of ads, each array object representing an ad. See Ad format for a complete description of the format.

 [{id:22, content…},{id:23, content…}]

The JSON payload is first validated to ensure it follows the ad structure and satisfies field constraints, and if all OK, accepted for moderation (HTTP 202).

The maximum number of ads per batch is set to 100, and the maximum payload size is set to 256 KB (kilobytes). If the payload exceeds this size, an HTTP 413 status code (Request Entity Too Large) is returned.

Update request

Send in a batch of ads for storage or update in Implio, without moderating them. Ads that already exist in Implio under the same id will be updated, whereas new ones will simply be stored.

Update requests are useful for keeping Implio in sync with any changes made to your ads (updated attributes) or their moderation (updated decisions) outside of Implio, or for importing historical data as you migrate to Implio.

Update requests are formatted like Moderation requests, except that they require an additional result object for each ad in the batch. This object contains the moderation outcome and optional id of the actor (person or automated agent) who took the decision — see Ad format for more information.

Important: all fields/attributes of your ad must be present, even if their values haven’t changed since a previously-submitted version of the ad.

Unlike Moderation requests, Update requests will not trigger any call to the webhook nor cause any change when polling GET /ads.

Response

The response contains two arrays of objects for accepted and rejected ads. Implio will generate a unique taskId for each accepted ad, and a batchId that uniquely identifies the batch.

These identifiers allow the ad submissions to be subsequently referred to in the moderation response. See the How can I identify an item via the API article for more information.

{ 
  "batchId": "53da7871-c368-4950-85f6-db6ddf335676", 
  "accepted":[
    { 
      "id": "22", 
      "taskId": "3a37195b-9aa1-40b3-8b57-0a513e9ca89a" 
    }, 
    {
      "id": "23", 
      "taskId": "b364766e-eca0-480b-8861-be4c56cd7f93" 
    } 
  ], 
  "rejected":[ ] 
}

Troubleshooting

By default, the result will detail the first error spotted with invalid ads sent in (one entry per rejected ad under “rejected”).

By setting the verboseErrors query parameter to true:

/ads?verboseErrors=true

you will receive a detailed report of all JSON schema validation errors, instead of just the first one. This is handy while integrating the Implio API, as it will help you pinpoint problems more easily.

Important: verboseErrors should not be used in production as it will result in noticeably longer response times. Make sure to remove ?verboseErrors=true when you are done integrating the API.

GET/ads?timestamp=[milliseconds since unix epoch]&taskIds=[comma-separated list of task ids] Success status: 200

Retrieve ads and their moderation results, after they have been processed in Implio.

Request

One of the following query parameters is expected in the request. Both can be specified, in which case ads satisfying both criteria will be returned:

  • timestamp expects a number of milliseconds since Unix epoch. Ads processed after this timestamp will be returned.
  • taskIds expects a comma-separated list of task identifiers. See POST /ads section and How can I identify an item via the API article for more information about task identifiers.

Additionally,  the noAdContent query parameter can be set to “true” to avoid receiving the ad content. The ad object will be present, but without the nested content object.
This allows for lighter webhook request entities. Note however that this should only be used if you don’t allow content to be edited in Implio, otherwise you wouldn’t receive the updated content.

Response

The response is a JSON object containing two fields: the pollingInfo object and the ads array.

pollingInfo

Up to 100 ads may be returned in the response.

This object specifies how to poll for subsequent ads and indicates whether more ads are presently available, with the two following properties:

  • newTimestamp timestamp (in milliseconds since unix epoch) of the last ad returned. This should be stored in the customer’s system and specified in the next poll request.
  • newerAdsExist a boolean property that is true if there are more recent ads whose results can be retrieved. If so, repeat the request using the newTimestamp value.
ads

Each value in this array is an object with the following properties specified below:

  • packedAt
  • ad
  • result
  • matchingFilters
packedAt

This property represents the time at which the ad was processed in Implio and results were made available to the customer.

ad

The complete ad in the same format as for submitting the ad to Implio for moderation. See Ad format section for more information.

If any field was changed in Implio (for instance the category or body), the updated value will be reflected in this object.

result

This object contains the result of the moderation:

  • outcome is the moderation decision: “approved” (the ad can be published on the site), “refused” (the ad should not be published on the site) or “no decision” (no decision could be made, the ad should be further examined to determine whether it should published).
  • reasons this array contains the reason(s) why the ad was refused. It is only present when outcome is “refused”.
  • actorId contains the identifier of the actor who made the decision.
  • feedback an array containing optional feedback, allowing for instructions on what to fix or improve to be given to the end user.
matchingFilters

This array contains information about each filter (called rule in the Implio user interface) that matched:

  • id is the unique identifier of the filter.
  • name is the name of the filter as it appears in Implio.
  • vote is the action associated with the filter, as it appears in Implio.
  • wordHighlighting an optional array containing the specifics about the text parts that were matched by the filter.
  • notice an optional object containing the name and severity of the notice associated with the rule. Only present if a notice for the rule has been defined in Implio.
{
  "pollingInfo": { 
    "newTimestamp": 1445518700257, 
    "newerAdsExist": false 
  }, 
  "ads": [ 
    { 
      "packedAt": 1445518700257,
      "ad": { 
        "id": "1", 
        "batchId": "53da7871-c368-4950-85f6-db6ddf335676", 
        "taskId": "3a37195b-9aa1-40b3-8b57-0a513e9ca89a", 
        "content": { 
          "title": "Super cute Rabbit", 
          "body": "A fine rabbit." 
        } 
      }, 
      "result": { 
        "actorId": "name@email.com",
        "outcome": "approved", 
        "reasons": [], 
        "feedback": [ 
          { 
            id: "suggestImprovements", 
            name: "Suggest improvements to user." 
          } 
        ], 
        "matchingFilters": [ 
          { 
            "id": "5636ff91a14f7601009d2189", 
            "name": "refuse all", 
            "vote": "REFUSE", 
            "wordHighlighting": [ 
              { 
                "variableName": "$text", 
                "words": [ 
                  {
                    "word": "test", 
                    "regex": "/\\btest\\b/gi" 
                  }
                ]
              } 
            ], 
            "notice": { 
              "text": "My Notice Text", 
              "severity": "GOOD" 
            } 
          }
        ] 
      } 
    } 
  ] 
}
DELETE/ads?userId=[a specific user id]
/ads?taskId=[a specific task id]
/ads?fromDate=[from date]&toDate=[to date]
Success status: 202

Schedule ads for deletion.

Request

Delete requests support 3 different ad selection criteria, each being mapped onto mutually-exclusive query parameters:

  • userId: delete all ads with the specified user id.
  • taskId: delete a unique ad corresponding to the specified task id. If the corresponding ad is still being processed (for instance pending manual moderation), this will have the effect of canceling the moderation task.
    See POST /ads section and How can I identify an item via the API article for more information about task identifiers.
  • fromDate and toDate: delete all ads that were sent to Implio between the specified from and to dates, expressed using ISO 8601 ‘s combined date and time representation in UTC timezone, e.g. 2020-12-22T09:30Z. See Date/time representation section for more information.
    Both query parameters must be present, and the maximum supported time interval between from and to dates is 1 day.
    For deleting ads over a longer period of time, multiple deleting requests must be made, for each of the corresponding days.

Response

202 (Accepted) status code is returned if the request is properly formatted. Note that this resource does not check whether ads exist for the specified user id, task id or from/to dates. In case there are none, the same status code is returned.
Note that there is no guarantee for how long the deletion job takes to complete, and there is currently no way to be notified of the job’s completion.

400 (Bad Request) status code is returned in any of the following cases:

  • mutually-exclusive parameters were supplied, e.g. userId and taskId
  • a parameter was incorrectly formatted, e.g. fromDate or toDate is not in ISO 8601 format
  • time interval between fromDate and toDate is more than 1 day.

The response body is always empty.

GET/_health Success status: 200

A check to make sure that the service is up and is accepting calls.

{ 
   status: alive 
}

Ad Format

Ads are sent to and retrieved from the Implio API in JSON, see example below.

The structure of an ad and supported fields are fixed. But custom, non-standard fields can be specified using customer-specific fields.

The following sub-sections specify all the fields an ad can have.

Sample ad:

{ 
  "id": "63137115", 
  "customerSpecific": {}, 
  "content": { 
    "title": "Super cute Rabbits", 
    "body": "4 cute rabbits born the 4:th of June for sale.", 
    "url": "http://best.ads.se/Stockholm/63137115.html", 
    "price": { 
      "amount": 100, 
      "currency": "SEK" 
    }, 
    "type": { 
      "id": "s", 
      "name": "For sale" 
    }, 
    "category": { 
      "id": "6083", 
      "name": "Rodents & Rabbits" 
    }, 
    "images": [ 
      { 
        "src": "http://best.ads.se/static/0/images/16/1608376350.jpg" 
      } 
    ], 
    "status": "published", 
    "createdAt": "2020-06-15T10:15:16.000Z", 
    "publishedAt": "2020-06-15T10:15:16.000Z", 
    "customerSpecific": {} 
  }, 
  "user": { 
    "id": "123456", 
    "name": "John Doe", 
    "phoneNumbers": [ 
      "070-123456" 
    ], 
    "emailAddresses": [ 
      "john.doe@gmail.com" 
    ], 
    "customerSpecific": {} 
  }, 
  "location": { 
    "city": "Stockholm", 
    "postalCode": "111 57", 
    "region": "Stockholm", 
    "countryCode": "SE", 
    "ipAddress": "192.168.0.1", 
    "customerSpecific": {} 
  } 
}

Mandatory fields

The only mandatory field of an ad is its id.

The ad should however contain at least one piece of content in the content object, such as a title, body or image.

It is also strongly recommended that you include the id of the corresponding user.

Here’s a minimal viable ad:

[    
   {       
     "id": "63137115",     
     "content": 
       {
        "body": "4 cute rabbits born the 4:th of June for sale."     
       },
     "user": 
       {
        "id": "1234"     
       }
   }
]

Structure

The ad is structured into the following sections specified below:

  • root
  • content
  • user
  • location
  • result
root

The root section contains the following properties, in addition to the sections located underneath it that follow.

PropertyTypeDescriptionRequired
idstringYour internal id for the adYes
customerSpecificobjectCustom fields, see Customer-specific fields section.No
content

This section contains the user-generated content of your ad.

Although all of its fields are optional, the content JSON object must be present in the ad.

PropertyTypeDescriptionRequired
titlestringTitle of your ad.

May contain up to 500 characters.
No
bodystringBody of your ad.

May contain up to 20,000 characters.
No
languageExpectedstringISO 639-1 code of the language in which the ad is expected to be written.

If present, this value will be taken into consideration when the language is automatically detected by Implio, making the language prediction more reliable.
No
urlstringURL to the ad on your site.

If present, Implio will display the link in its user interface, allowing you to quickly jump to the ad on your site.
No
priceobjectPrice associated with the ad, see Price section.No
typeobjectType associated with the ad, see Type section.No
categoryobjectCategory associated with the ad, see Category section.No
imagesarray of objectsImages associated with your ad, see Images section.

May contain up to 80 objects.
No
videosarray of objectsImages associated with your ad, see Videos section.

May contain up to 5 objects.
statusstringStatus of the ad in your systemNo
createdAtstring representing an ISO 8601 date/timeDate when ad was created in your system.No
updatedAtstring representing an ISO 8601 date/timeDate when ad was last updated by user or admin on your site.

Important: setting this field will allow Implio to know which version of an ad is the latest, in case multiple versions get sent.
No
publishedAtstring representing an ISO 8601 date/timeDate when ad was published on your site.No
adminUrlstringURL to the ad in your back-office tool.

If present, Implio will display the link in its user interface, allowing moderators to quickly jump to the ad in your back-office tool.
No
customerSpecificobjectCustom content fields, see Customer-specific fields section.No
content.price

This subsection allows a price for you ad to be specified.

The price object is optional, but if present, it needs to include both the amount and currency properties.

PropertyTypeDescriptionRequired
amountnumberThe price listed in the adYes
currencystringISO 4217 Currency Code.Yes
content.type

Describes the type of an ad on your site. This could for instance be “For sale” or “For rent”.

The type object is optional, but if present, it needs to include both the id and name properties.

PropertyTypeDescriptionRequired
idstringid of the type in your systemYes
namestringDisplay name of the type e.g “For sale”Yes
content.category

Describes the category of an ad on your site. This could for instance be “Cars” or “Electronics”.

The category object is optional, but if present, it needs to include both the id and name properties.

PropertyTypeDescriptionRequired
idstringid of the category in your systemYes
namestringDisplay name of the category e.g “Cars”Yes
content.images

Contains images associated with your ad.

The images array is optional and may contain up to 80 images. Each object in the array must contain a single property named src.

Images will be fetched by Implio from their specified location only once, then stored and subsequently served directly by Implio.

This means you are free to remove images from your servers once the ad has been sent to Implio. You just need to allow sufficient time for Implio to download images from your servers.

PropertyTypeDescriptionRequired
srcstringUrl to public imageYes
content.videos

Contains videos associated with your ad.

The videos array is optional and may contain up to 5 videos. Each object in the array must contain a single property named src.

Unlike images, videos are not stored in Implio. They are served from their specified location every time they are displayed in the user interface.

PropertyTypeDescriptionRequired
srcstringUrl to public videoYes
user

Contains information about the end user who generated the ad on your site.

While the user object is optional, it is strongly recommended to include information about the user.

PropertyTypeDescriptionRequired
idstringId of user in your systemNo
namestringDisplay name of the user in your systemNo
phoneNumbersarray of stringsArray of phone numbersNo
emailAddressesarray of stringsEmail addressesNo
adminUrlstringURL to the ad in your back-office tool.

If present, Implio will display the link in its user interface, allowing moderators to quickly jump to the ad in your back-office tool.
No
customerSpecificobjectCustom user fields, see Customer-specific fields section.No
location

Contains an optional location associated with the ad.

For a classified site for instance, the location may be where the item is located. Or in the case of a dating site, it may be where the user is looking to meet other people.

PropertyTypeCityRequired
citystringCityNo
postalCodestringPostal (zip) codeNo
regionstringRegionNo
countryCodestringTwo-letter country code (ISO 3166)No
ipAddressstringIP address of the user posting the ad.

If a value is found, an attempt to resolve a geolocation from this IP address will be made.
No
customerSpecificstringCustom location fields, see Customer-specific fields section.No
result

Contains the moderation decision of the ad and optional id of the actor (person or automated agent) who took the decision.

Specifying this object will cause the ad to simply be stored rather than moderated. See Update requests for more information.

PropertyTypeDescriptionRequired
outcomestringModeration decision:"approved" or "refused"Yes
actorIdstringId of the actor (person or automated agent) who took the decisionNo
Customer-specific fields

Each section (root, content, user, location) has a predefined set of properties that you can use to send in data. Your fields should be mapped onto these whenever possible.

When there is no possible mapping for a property of your site, you can add custom fields under the customerSpecific object.

This object is supported in all sections, and allows you to include any number of custom fields that you would like Implio to display or make it use of via automation rules.
Each custom field should be placed under the section that is best suited, for instance under the user section for the field corresponds to a user attribute. Note that the section will control where the field appears in the user interface.

Custom fields are specified as JSON key/value pairs, see example below.

Keys must start with a letter. Subsequent characters can only be letters or digits (0-9). They are case sensitive.

"customerSpecific":{
  "engine": "combustion",   
  "transmission": "automatic",   
  "mileage": 14100,
  "professionalSeller": true 
}
Date/time representation

All dates should be expressing using ISO 8601’s combined date and time representation in UTC time zone.

For example, 2020-12-22T09:30:00.000Z or, using a more condensed form that excludes seconds and milliseconds, 2020-12-22T09:30Z.

Specifying all dates in UTC timezone ensures that date/time values are consistent between your platform and Implio, regardless of where your business resides geographically.

If no time zone is specified, we will assume UTC.

Read more about ISO 8601 here:
https://en.wikipedia.org/wiki/ISO_8601

Webhook

You can register an endpoint for being notified of newly-moderated ads. This method is an alternative to polling moderated ads using GET /ads.
It allows for getting results faster, at the expense of increased network and server overhead.

Registering a webhook

A webhook URL can be registered in the Api Integration settings of your Implio team, when logged in as a team administrator.
It needs to be valid HTTPS URL. The server behind this URL must use a valid certificate signed by a trusted authority. Self-signed certificates cannot as the server-to-server connection will fail to establish.

Handling webhook requests

An HTTPS request is made as soon as an ad is moderated, containing the ad itself (with any modification made to it in Implio) and the outcome of the moderation.

Should the server return a success (2xx) HTTP status code, the delivery will be considered successful.

Conversely, if the registered endpoint cannot be reached or the server returns an error code, Implio will retry up to 5 times, gradually increasing the amount of time between retries.

The API key of your team (the same key that is used for authenticating requests to Implio) will be specified in the X-Api-Key header. The server behind the registered webhook URL should verify that the API key specified is indeed your API key, as a means to ensuring the request authenticity.

The format of the JSON payload is almost identical to the one described in GET /ads, with the difference that there is only one ad:

{
  "packedAt": 1445518700257,
  "domain": "00ae9267-2224-754f-b2f5-ed00cb54a8e4",
  "ad": {
    "id": "1",
    "batchId": "53da7871-c368-4950-85f6-db6ddf335676",
    "taskId": "3a37195b-9aa1-40b3-8b57-0a513e9ca89a",
    "content": {
      "title": "Super cute Rabbit", 
      "body": "A fine rabbit."
    }
  },
  "result": {
    "outcome": "approved",
    "reasons": [],
    "feedback": [
      {
        "id": "suggestImprovements",
        "name": "Suggest improvements to user."
      }
    ],
    "matchingFilters": [
      {
        "id": "5636ff91a14f7601009d2189",
        "name": "refuse all",
        "vote": "REFUSE",
        "wordHighlighting": [
          {
            "variableName": "$text",
            "words": [
              {
                "word": "test",
                "regex": "/\\btest\\b/gi"
              }
            ]
          }
        ],
        "notice": { 
          "text": "My Notice Text", 
          "severity": "GOOD" 
        } 
      } 
    ] 
  }
}

Best Practices

Notify Implio of item changes
When a user edits an item on your site, you should send it to Implio again. This is to make sure the latest version is always moderated.

Add the updatedAt field to ensure Implio knows which version is the latest.

On error from Implio API queue and retry
When an item can not be sent to Implio due to a 500 error in Implio, and retry the failed request after a minute.

Webhook
If for some reason your webhook handler is unable to process Implio’s request, return an error code (e.g. 500) Implio will try again the request later.