Doofinder comes with a simple yet powerful API to perform searches.
You can also control Doofinder’s features with a number of parameters you send along with the GET request.
We have developed some client libraries which you can use:
Or you can simply write your own, implementing our API which is explained below.
Show me the money!
You want to search for something. You want it quick and you want it accurate. Just provide the search engine’s id ({hashid}
) and the search term.
GET http://eu1-search.doofinder.com/5/search?hashid={hashid}&query=some+query HTTP/1.1
Response
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{
"query_counter":1,
"results_per_page":12,
"page":1,
"total":31,
"query": "some query",
"hashid": "{hashid}",
"max_score":1.1112283,
"results":[
{
"description": "Antena. 5.2 dBi. omnidireccional…",
"dfid": "523093f0ded16148dc005362",
"title": "Cisco Aironet Pillar Mount Diversity Omnidirectional Antenna",
"url": "http://www.example.com/product_description.html",
"image_url": "http://www.example.com/images/product_image.jpg",
"type": "{type}",
"id": "{item_id}"
},
{
"description": "Teclado. USB. España…",
"dfid": "…",
"…"
},
{"…": "…"},
{
"description": "Pila para cámara de vídeo portátil…",
"dfid": "5230943aded16148dc005c52",
"title": "Canon BP 514",
"url": "http://www.example.com/alt_product_description.htm",
"image_url": "http://www.example.com/images/alt_product_image.jpg",
"type": "{type}",
"id": "{item_id}"
}
],
"query_name": "fuzzy"
}
As you can see, the results
attribute of the returned json contains an array with the search results. There is also some other search-related info, we’ll go through that later
Notice: This sample response doesn’t contain facets data.
Basics
You have a bunch of indexed data into Doofinder search engine. Let’s call that data indexed items. They are items (products, articles, web pages content, etc…) that you now have indexed into your Doofinder search engine.
This api will let you search through those indexed items .
All search request are made issuing GET requests to a URL (both HTTP
and HTTPS
protocols supported) like this:
http://eu1-search.doofinder.com/5/search
The name of the search server may vary depending on your location and it usually is something like:
<zone>-search.doofinder.com
Authorization
Every Search API call must be authorized. There are two ways to authentify the requests.
Origin
: This is used when the request is performed from a browser (from the client side). This header is filled in by the browser with the url you are requesting from and you must configure this url in your Allowed Domains whitelist (Security section inside SearchEngine Configuration in your Doofinder Admin Panel). By default your site url is configured as Allowed Domain.Authorization
: When you make a request from your server or device app, you must authentify it with the secret token you will find as part of your API Key (you can generate an API Key from My Account section in your Doofinder Admin Panel). When this header is sent you must useHTTPS
protocol.
cURL Example
Suppose that your API key is:
eu1-14f327ad4389828d22f25bdb78dfff9b027a445d
That means:
- Zone:
eu1
- Token:
14f327ad4389828d22f25bdb78dfff9b027a445d
And suppose that your search engine’s hashid
is:
16ddffffcf151caa1234caaa89d02374
This would request the first 20 gloves found in the index:
curl -XGET -H 'Authorization: 14f327ad4389828d22f25bdb78dfff9b027a445d' \
'https://eu1-search.doofinder.com/5/search?hashid=16ddffffcf151caa1234caaa89d02374&rpp=20&page=1&query=gloves'
So you need at least a token
, a zone
, a hashid
and a query
:
curl -XGET -H 'Authorization: <token>' \
'https://<zone>-search.doofinder.com/5/search?hashid=<hashid>&rpp=20&page=1&query=<query>'
Conventions
Along most of the code samples you will find placeholders for some common variable values. They are:
{hashid}
: The search engine’s unique id. i.e.:d8fdeab7fce96a19d3fc7b0ca7a1e98b
{type}
: The type of the data you’re searching at. i.e.: ‘product’{item_id}
: Unique identificator of an indexed item within its type . i.e.:AOX11302
For the search zone we will always use eu1
. Remember to replace it in your tests by the proper value (you will find it at the beginning of your API key).
The Request
Quite a few things in Doofinder’ search are controlled through request parameters
Basic parameters
hashid
: identificator of the search engine. Mandatoryquery
: the search term. It must be escaped and it can’t be longer than 200 characters. Mandatoryrpp
: “results per page” how many results per page to return. it can’t be bigger than 100page
: page number of the results to returntransformer
: the transformation to apply to the results. If none specified, the results shall have the same fields the indexed items have. The one most commonly used isbasic
.
Notice: You can’t fetch more than 1000 search results in total, so rpp*page
must always be less than 1000
Available transformers
With the transformer parameter, you can choose between two transformers:
basic
(default) : Optimized to be used by our instant results search layer. Returnsid
,title, description, link
, image_link fields.onlyid
: Optimized to provide very light results. returns only theid
field.
Dark magic parameters
type
: the type of the items to search for. i.e.: ‘product’ or ‘page’. you can use multiple values with this.query_name
: Doofinder tries several types of querying the index to get the better results possible. Use this to instruct it to only use the “type of querying” specified by this parameter. Click here to see the available values for this parameternostats
: when present in any search request, this search won’t compute in stats reports.
Filter parameters
This is tricky somehow. Please bear with me:
Doofinder expects the filter parameter grouped like this:
filter: {
color: ['blue', 'red'],
size: ['M', 'S'],
price: {
gte: 4.36,
lt: 99
}
}
For the range filters you can use the following:
gte
Greater than or equallte
Less than or equalgt
Greater thanlt
Less than
Notice: When you’re applying filters, you need to make sure Doofinder uses the same query_name
all the time, so your results are indeed “filtered”. To help you with this, the response comes with the query_name
property too, so you can instruct Doofinder to use that query_name only. Bear in mind that query_name
makes a first filter on how the search term are matched against the index and afterwards filters are applied.
Writing that down in request parameters language is:
filter[color][]=blue&filter[color][]=red&filter[size][]=M&filter[size][]=S&filter[price][][gte]=4.36&filter[price][][lt]=99
Notice: The [
]
characters should be escaped (%5B
and %5D
)
By default the filters make an AND query when they are for different fields, and an OR query when they are for the same field. So, the previous filter would be read as: Search for items which (color is blue OR color is red) AND (size is M OR size is S) AND (price is greater than or equal to 4.36 AND price is less than 99).
If you want to make AND queries into the same field, just add the following parameter to the url: filter_execution=and
. Adding this parameter the query would be read as: Search for items which (color is blue AND color is red) AND (size is M AND size is S) AND (price is greater than or equal to 4.36 AND price is less than 99).
Go the distance: Geo Distance filter
If you have items with geographical position data, you can also filter results by the distance of the items to a certain origin. You need to prepare your data a little bit for that:
Tell Doofinder about your field.
You need to tell Doofinder which fields are expected to contain positional data. You can do that by specifing that field as as a Geo point
field in your Doofinder Admin Panel at the configuration / advanced settings / field types section.
Make sure it has the right format.
Let’s say 41.12
is the lattitude and -71.34
is the longitude. Your positional field (say its named “position” should have the following format:
- API
{
"id": "1",
"title": "my title",
"position": "41.12,-71.34"
}
- xml file:
<item>
<id>1</id>
<title>my title</title>
<position>41.12,-71.34</position>
</item>
- text file:
id|title|position
1|my title|41.12,-71.34
Go filter!
Filter format is quite simple. Say you want to filter red or blue items which are within 200 km from the (40, -70) coords.
filter: {
color: ['blue', 'red'],
geo_distance: {
distance: "200km",
position: "40,-70"
}
}
Notice: Both geo_distance
keys are mandatory, the distance
and the name of your Geo point
field.
Writing that down in request parameters language:
filter[color][]=blue&filter[color][]=red&filter[geo_distance][][distance]=200km&filter[geo_distance][][position]=40,-70
Notice: The query_name and the [,] notices are to be considered, too.
Exclusion parameters
As you can apply normal filters, you can exclude items using negative filters:
Doofinder expects the exclude parameter grouped like this:
exclude: {
color: ['blue', 'red'],
size: ['M', 'S'],
price: {
gte: 4.36,
lt: 99
}
}
For the range filters you can use the following:
gte
Greater than or equallte
Less than or equalgt
Greater thanlt
Less than
Notice: When you’re applying negative filters, you need to make sure Doofinder uses the same query_name
all the time, so your results are indeed “filtered”. To help you with this, the response comes with the query_name
property too, so you can instruct Doofinder to use that query_name only.
Writing that down in request parameters language is:
exclude[color][]=blue&exclude[color][]=red&exclude[size][]=M&exclude[size][]=S&exclude[price][][gte]=4.36&exclude[price][][lt]=99
Notice: The [ and ] characters should be escaped (%5B and %5D)
By default the negative filters make an OR query when they are for different fields, and an OR query when they are for the same field. So, the previous filter would be read as: Search for items which (color is not blue OR color is not red) OR (size is not M OR size is not S) OR (price is not greater than or equal to 4.36 OR price is less than 99).
If you want to make AND queries for exclude filters in different fields, just add the following parameter to the url: exclude_execution=and
. Adding this parameter the query would be read as: Search for items which (color is not blue OR color is red) AND (size is not M OR size is not S) AND (price is not greater than or equal to 4.36 AND price is not less than 99).
Go the distance: Geo Distance negative filter
As you can filter by geo location, the same you can exclude a circle around a point with a determined radius. Look at the Geo Distance Field
Excluding by geo-location
Filter format is quite simple. Assuming location
is a Geo point
field, say you want to exclude red and blue items which are within 200 km from the (40, -70) coords.
exclude: {
color: ['blue', 'red'],
geo_distance: {
distance: "200km",
location: "40,-70"
}
}
Notice: Both geo_distance
keys are mandatory.
Writing that down in request parameters language:
exclude[color][]=blue&exclude[color][]=red&exclude[geo_distance][][distance]=200km&exclude[geo_distance][][position]=40,-70
Notice: The query_name and the [,] notices are to be considered, too.
Sort parameters
Also tricky. What a happy hour we’re having!
You can command Doofinder to return results sorted by certain fields. Doofinder expects sort parameters like any of these:
sort[][price]=asc
sort[][price]=asc&sort[][brand]=desc
Notice: dfscore is a special field name that represents the “quality” Doofinder has assigned to that result. The higher the score, the best result it is.
Of course, you need to send this as request parameters:
sort[][price]=asc
sort[0][price]=asc&sort[1][brand]=desc
Geo Distance Sorting
Assuming location
is a field of type Geo point
:
sort[_geo_distance][location]=40,-70
sort[_geo_distance][order]=asc
The Response
You’ve already have a glimpe of a basic response. You know it’s a json object with a bunch of properties. Here are some more details to whet your appetite:
Basic response properties
page
: Page number of the results being returned in this response.total
: The total number of results that can be obtained.total_found
: The total number of results that match the query.max_score
: For the best result Doofinder could find, this is a numeric estimation of “how good” it is according to Doofinder.query_name
: In order to get the best possible results, Doofinder tries several types of querying. This is the type of the query Doofinder made to obtain these results.query
: The search term.results_per_page
: How many results shown per page.results
: List of search results
Response with facets
When you have facets defined in your search engine, along with the response comes information about different groupings that can be made for certain fields in the search results.
This info comes in the response json, in the facets property:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{
"query":"chair",
"total":"6",
"..":"..",
"results":[
{"…":"…"},
{"…":"…"}
],
"facets":{
"color":{
"doc_count": 6
"missing": {"doc_count": 1},
"terms":{
"buckets": [
{"key":"Green","doc_count":2},
{"key":"Blue","doc_count":2},
{"key":"Red","doc_count":1},
{"key":"Yellow","doc_count":1}
],
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 1
}
},
"brand":{
"doc_count":6,
"missing": {"doc_count": 0},
"terms": {
"buckets": [
{"key":"Red castle","doc_count":5},
{"key":"Maclaren","doc_count":1}
],
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0
}
},
"price":{
"doc_count": 6,
"range":{
"buckets": [
{ "doc_count": 6,
"key": "0.0-*",
"from": 0,
"from-as-string": "0.0",
"stats": {
"from":0,"count":6,
"min":30,"max":94.9000015258789, "avg":84.0833346048991
}
}
]
}
},
"categories":{
"doc_count":12,
"missing": {"doc_count": 0},
"terms": {
"buckets": [
{"key":"walking chairs","doc_count":6},
{"key":"Bags walking chairs","doc_count":5},
{"key": "Blankets, covers","doc_count":1}
],
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0
}
}
}
}
As you can see, Doofinder returns info about the groupings for each facet field in the search results. Therefore, we know that , within our search results:
- You can pick 2 results that are “green”, 5 that are from the brand “Red castle”, or 6 results that belongs to the “walking chairs” category.
- The minimum price is 30, the maximum is 94.9
Notice: As you can see in the example above, we currently support two types of grouping or facets: terms type (like categories
or color
) and range type (like price
).
Response with filters
If you make a search request with filters, the response , along with the basic parameters and the facets information, comes also with a property named filter
that contains the applied filters in the search request.
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{
"query":"chair",
"total":"6",
"..":"..",
"results":[
{"…":"…"},
{"…":"…"}
],
"facets":{
"…":"…"
},
"filter":{
"terms":{
"categories":["Walking chairs"],
"color":["Green"]
}
}
}
Advanced
Registering clicks
With the management api you can obtain stats info about clicks made in search results. Usually our javascript layer takes care of that, but if you plan to use our search API with your “own devices”, then you should “register” the clicks made to a search result item.
Say a user search for “potato” and obtains 3 results: “Raw Potatoes, Mr. Potato accesories, Fish & Chips”. Then the user clicks on “Mr. Potato accesories” result and you want to register that click. To register that click, you have to do this request:
GET https://eu1-search.doofinder.com/5/stats/click?dfid={dfid}&query={query}&random={random_value}
Where:
{dfid}
Is the Doofinder result “doofinder id”. It comes in every Doofinder results for every item. it has the form {hashid}@{type}@{md5id}: i.e.:6a96504dc173514cab1e0198af92e6e9@product@e19347e1c3ca0c0b97de5fb3b690855a
{query}
is the query used to get the result that is being clicked. it’s not mandatory, but important for the “clicktrough” stats{random_value}
in case you’re doing the request from within a browser, you should add arandom
parameter with a random value which changes in every request. This is to avoid meddling with the browser’s cache.
The server will answer with a simple OK
message.
There is also a support article about how to register clicks programatically
Registering cart items
In this section, we are describing the API endpoints and business logic of this API. First and foremost, we need the following:
- Our search engine’s hashid
- A session identifier
With these two, the API is able to discern and uniquely identify the current cart and we can have different carts for different users at the same time.
The API has these main moving parts, adding items to the cart, removing items to the cart and clearing the cart. In these, the cart is stored in a temporary location until there’s a call to the checkout endpoint that registers a checkout stats event, which may be called by your code or by Doofinder’s search layer if it’s configured to do so. If the checkout hashid and session ID match a cart, that cart will be stored in the stats automatically and cleared from the temporary storage.
NOTE: The API holds a cart’s information up to one hour, after which it will be discarded if there’s been no checkout or addition or removal of items in it.
Endpoints
/5/stats/add-to-cart
- Method:
GET
- Parameters:
- hashid: The search engine’s hashid
- datatype: The datatype used for this product in Doofinder, by default will be product.
- session_id: The current session ID, must be unique for each user.
- item_id: The ID of the item to be added (this refers to the ID in the shop’s database)
- amount: The amount of this item to be added to the current cart.
- Description: Adds an item to the cart, or creates a new cart for the given session if it does not exists. If the item is already present in the cart, the amount is added to the item’s current amount.
- Returns: Status 200 and “OK” message.
- Method:
- Sample code:
`fetch(“https://eu1-search.doofinder.com/5/stats/add-to-cart?hashid=c06783a87f&session_id=ac5653b&item_id=56&datatype=product&amount=3”)`
/5/stats/remove-from-cart
- Method:
GET
- Parameters:
- hashid: The search engine’s hashid
- datatype: The datatype used for this product in Doofinder, by default will be product.
- session_id: The current session ID, must be unique for each user.
- item_id: The ID of the item to be removed or substracted (this refers to the ID in the shop’s database)
- amount: How much to remove from the cart of the given item.
- Description: Removes amount from the given item in the cart, removing it completely if the amount present in the cart minus the amount specified in this call is zero or negative, else, it will be updated with the new calculated amount.
- Returns: Status 200 and “OK” message.
- Method:
- Sample code:
`fetch(“https://eu1-search.doofinder.com/5/stats/remove-from-cart?hashid=c06783a87f&session_id=ac5653b&item_id=56&datatype=product&amount=3”)`
/5/stats/clear-cart
- Method: GET
- Parameters:
- hashid: The search engine’s hashid
- session_id: The current session ID, must be unique for each user.
- Description: This call will erase completely a cart identified by the pair of hashid and session ID, if it does exist.
- Returns: Status 200 and “OK” message.
- Sample code:
`fetch(“https://eu1-search.doofinder.com/5/stats/clear-cart?hashid=c06783a87f&session_id=ac5653b”)`
The “query_name” parameter
As you read before, query_name is the type of search Doofinder does in order to obtain results.
The default behavior is to let Doofinder try several and return the first one that matches better, but you may want to instruct doofinder to try one particular type of search by passing the query_name
parameter.
The possible values for the query_name
parameter are:
match_and
Doofinder will return results that contain all the search termsmatch_or
Doofinder will return results that contain any of the search terms. Of course, results that contain all the terms are scored better.fuzzy
Doofinder will try to apply some “fuzzy logic” to determine whether a result, even if it’s not an exact match, is “close enough” to the search terms.phonetic_text
Doofinder will try to match search terms not according to how they’re written but how they’re pronounced. i.e. “cat” and “kat” would be a match.
Bonus Track: The /options call
Besides making search requests to:
https://{zone}-doofinder.com/5/search?hashid={hashid}
(which is all this document is about), you can also ask our search server for certain options you may have configured previously in your Doofinder control panel.
Notice: All conventions are the same as for search requests.
Notice: You need to authorize yourself as described in the #authorization section.
The url to ask to
This the call:
GET http://eu1-search.doofinder.com/5/options/{hashid} HTTP/1.1
no extra parameter, just that.
Notice: Remember that you can use https
protocol, too.
The response to expect
And this is what you get when you do the options call:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{
"currency": {
"thousand": ".",
"symbol": "€",
"precision": 2,
"label": "Euro",
"format": "%v %s",
"decimal": ","
},
"layerSortOptions": [
{
"field": "color",
"sort": "asc",
"label": "Color"
},
{
"field": "size",
"sort": "asc",
"label": "Talla"
}
],
"facets": [
{
"name": "brand",
"label": "Brand",
"type": "terms",
"size": 20
},
{
"name": "price",
"label": "My Price",
"type": "range",
"ranges": [{"from": 0}]
}
],
"noResultsHTML": "<b>Sorry buddy, nothing to show here</b>",
"checkoutURL": "/checkout/onepage/success",
"addons": {
"searchHistory": {}
},
"some_deprecated_option": true,
"some_internal_use_option": "nop"
}
Lots of stuff, here, but before we get to it, a few remarks:
- Only the options documented here are guaranteed to remain stable, you can expect to find more options than the ones documented here. Those options may be deprecated, and prone to disappear, or may be for some new feature we’re trying, and therefore expected to change, or may be just for internal use only. The botton line is expect undocumented options to be in the response, and expect them to change, increase or diminish.
- As long as we’re introducing new “stable” options, we’ll document them so you always know what remains.
- The
addons
option is bound to grow as we add addons to Doofinder.
The stable options
These are the documented options:
currency
: Contains information about the search engine’s currency and how it should be formatted.layerSortOptions
: A list of “sort options” that allow the user to sort by the selected criteria on the results layer.facets
: List with information about the fields you use for filtering, and how they are configured.noResultsHTML
: What to show in the layer in case of no results found.checkoutURL
: The url your website uses for checking out.addons
: Contains all the addons your search engine may have, and how they are configured.