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 1,000, 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":[
    { 
      "clientId": "22", 
      "taskId": "3a37195b-9aa1-40b3-8b57-0a513e9ca89a" 
    }, 
    {
      "clientId": "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 1,000 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" 
            } 
          }
        ] 
      } 
    } 
  ] 
}

 

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": "2015-06-15T10:15:16.000Z", 
    "publishedAt": "2015-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 siteNo
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 Image section.

May contain up to 80 images.
No
statusstringStatus of the ad in your systemNo
createdAtdate string with time zoneDate when ad was created in your system (date time ISO 8601)No
updatedAtdate string with time zoneDate when ad was latest updated by user or admin on your site (date time ISO 8601)No
publishedAtdate string with time zoneDate when ad was public on your site (date time ISO 8601)No
adminUrlstringURL to the ad in your back officeNo
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 information about images associated with your ad.

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

PropertyTypeDescriptionRequired
srcstringUrl to public imageYes
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 user in your back officeNo
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 
}
Time zone information

Dates should be specifed in the UTC time zone using the ISO 8601 notation, for example 2015-06-15T10:15:16.000Z . It makes it possible for us to give you the correct time for moderation events regardless of where your business resides geographically. If no time zone is specified we will assume UTC.

See more information about ISO 8601:
https://en.wikipedia.org/wiki/ISO_8601#Time_zone_designators

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 on changes by the user
When a user change 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 as it will make sure you do not get the same update twice if your service accidentally sends the request twice.

On error from Implio API queue and retry
When an item can not be published to Implio due to a 500 error in Implio, queue it and retry it within a minute

Webhook
Make sure to output something else than 200 OK from your system if you can not consume the request and we will try again.