{"id":9,"date":"2026-03-30T15:35:55","date_gmt":"2026-03-30T15:35:55","guid":{"rendered":"http:\/\/dadi.cloud\/api-2\/"},"modified":"2026-03-30T15:35:55","modified_gmt":"2026-03-30T15:35:55","slug":"api-2","status":"publish","type":"page","link":"https:\/\/dadi.cloud\/docs-sub\/api\/","title":{"rendered":"Api"},"content":{"rendered":"<div class=\"docs docs--api\">\n<h2><a href=\"#requirements\" id=\"requirements\" name=\"requirements\" class=\"anchor\">Anchor link<\/a> <a href=\"#requirements\">Requirements<\/a><\/h2>\n<p class=\"7xtjw4dqwy5mz7w3j\">Microservices in the DADI platform are built on Node.js, a JavaScript runtime built on Google Chrome&#39;s V8 JavaScript engine. Node.js uses an event-driven, non-blocking I\/O model that makes it lightweight and efficient.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">DADI follows the Node.js LTS (Long Term Support) release schedule, and as such the version of Node.js required to run DADI products is coupled to the version of Node.js currently in Active LTS. See the <a href=\"https:\/\/github.com\/nodejs\/LTS\">LTS schedule<\/a> for further information.<\/p>\n<h2><a href=\"#creating-an-api\" id=\"creating-an-api\" name=\"creating-an-api\" class=\"anchor\">Anchor link<\/a> <a href=\"#creating-an-api\">Creating an API<\/a><\/h2>\n<p class=\"7xtjw4dqwy5mz7w3j\">The easiest way to install API is using DADI CLI. CLI is a command line application that can be used to create and maintain installations of DADI products. Follow the simple instructions below, or see <a href=\"https:\/\/dadi.cloud\">more detailed documentation for DADI CLI<\/a>.<\/p>\n<h3><a href=\"#create-new-api-installation\" id=\"create-new-api-installation\" name=\"create-new-api-installation\" class=\"anchor\">Anchor link<\/a> <a href=\"#create-new-api-installation\">Create new API installation<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">There are two ways to create a new API with the CLI: either manually create a new directory for API or let CLI handle that for you. DADI CLI accepts an argument for <code>project-name<\/code> which it uses to create a directory for the installation.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>Manual directory creation<\/em><\/p>\n<pre><code class=\"lang-console\"><span class=\"hljs-meta\">$<\/span><span class=\"bash\"> mkdir my-api<\/span>\n<span class=\"hljs-meta\">$<\/span><span class=\"bash\"> <span class=\"hljs-built_in\">cd<\/span> my-api<\/span>\n<span class=\"hljs-meta\">$<\/span><span class=\"bash\"> npx dadi-cli api new<\/span>\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>Automatic directory creation<\/em><\/p>\n<pre><code class=\"lang-console\"><span class=\"hljs-meta\">$<\/span><span class=\"bash\"> npx dadi-cli api new my-api<\/span>\n<span class=\"hljs-meta\">$<\/span><span class=\"bash\"> <span class=\"hljs-built_in\">cd<\/span> my-api<\/span>\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\">DADI CLI will install the latest version of API and copy a set of files to your chosen directory so you can launch API almost immediately.<\/p>\n<blockquote class=\"\">\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Installing DADI API directly from NPM<\/strong><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">All DADI platform microservices are also available from NPM. To add <em>API<\/em> to an existing project as a dependency:<\/p>\n<\/blockquote>\n<blockquote class=\"advice\">\n<pre><code class=\"lang-console\"><span class=\"hljs-meta\">$<\/span><span class=\"bash\"> <span class=\"hljs-built_in\">cd<\/span> my-existing-node-app<\/span>\n<span class=\"hljs-meta\">$<\/span><span class=\"bash\"> npm install --save @dadi\/api<\/span>\n<\/code><\/pre>\n<\/blockquote>\n<h2><a href=\"#application-anatomy\" id=\"application-anatomy\" name=\"application-anatomy\" class=\"anchor\">Anchor link<\/a> <a href=\"#application-anatomy\">Application anatomy<\/a><\/h2>\n<p class=\"7xtjw4dqwy5mz7w3j\">When CLI finishes creating your API, the application directory will contain the basic requirements for launching your API. The following directories and files have been created for you:<\/p>\n<pre><code class=\"lang-console\"><span class=\"hljs-keyword\">my<\/span>-api\/\n  config\/              <span class=\"hljs-comment\"># contains environment-specific configuration files<\/span>\n    config.development.json\n  server.js            <span class=\"hljs-comment\"># the entry point for the application<\/span>\n  package.json\n  workspace\/\n    collections\/       <span class=\"hljs-comment\"># collection specification files<\/span>\n    endpoints\/         <span class=\"hljs-comment\"># custom JavaScript endpoints<\/span>\n<\/code><\/pre>\n<h2><a href=\"#configuration\" id=\"configuration\" name=\"configuration\" class=\"anchor\">Anchor link<\/a> <a href=\"#configuration\">Configuration<\/a><\/h2>\n<p class=\"7xtjw4dqwy5mz7w3j\">API reads a series of configuration parameters to define its behaviour and to adapt to each environment it runs on. These parameters are defined in JSON files placed inside the <code>config\/<\/code> directory, named as <code>config.{ENVIRONMENT}.json<\/code>, where <code>{ENVIRONMENT}<\/code> is the value of the <code>NODE_ENV<\/code> environment variable. In practice, this allows you to have different configuration parameters for when API is running in development, production and any staging, QA or anything in between, as per the requirements of your development workflow.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">Some configuration parameters also have corresponding environment variables, which will override whatever value is set in the configuration file.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">The following table shows a list of all the available configuration parameters.<\/p>\n<table>\n<thead>\n<tr>\n<th style=\"text-align:left\">Path<\/th>\n<th style=\"text-align:left\">Description<\/th>\n<th style=\"text-align:left\">Environment variable<\/th>\n<th style=\"text-align:left\">Default<\/th>\n<th style=\"text-align:left\">Format<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td style=\"text-align:left\"><code>app.name<\/code><\/td>\n<td style=\"text-align:left\">The applicaton name<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code>DADI API Repo Default<\/code><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>publicUrl.host<\/code><\/td>\n<td style=\"text-align:left\">The host of the URL where the API instance can be publicly accessed at<\/td>\n<td style=\"text-align:left\"><code>URL_HOST<\/code><\/td>\n<td style=\"text-align:left\"><code><\/code><\/td>\n<td style=\"text-align:left\">*<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>publicUrl.port<\/code><\/td>\n<td style=\"text-align:left\">The port of the URL where the API instance can be publicly accessed at<\/td>\n<td style=\"text-align:left\"><code>URL_PORT<\/code><\/td>\n<td style=\"text-align:left\"><code><\/code><\/td>\n<td style=\"text-align:left\">*<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>publicUrl.protocol<\/code><\/td>\n<td style=\"text-align:left\">The protocol of the URL where the API instance can be publicly accessed at<\/td>\n<td style=\"text-align:left\"><code>URL_PROTOCOL<\/code><\/td>\n<td style=\"text-align:left\"><code>http<\/code><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>server.host<\/code><\/td>\n<td style=\"text-align:left\">Accept connections on the specified address. If the host is omitted, the server will accept connections on any IPv6 address (::) when IPv6 is available, or any IPv4 address (0.0.0.0) otherwise.<\/td>\n<td style=\"text-align:left\"><code>HOST<\/code><\/td>\n<td style=\"text-align:left\"><code><\/code><\/td>\n<td style=\"text-align:left\">*<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>server.port<\/code><\/td>\n<td style=\"text-align:left\">Accept connections on the specified port. A value of zero will assign a random port.<\/td>\n<td style=\"text-align:left\"><code>PORT<\/code><\/td>\n<td style=\"text-align:left\"><code>8081<\/code><\/td>\n<td style=\"text-align:left\">Number<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>server.redirectPort<\/code><\/td>\n<td style=\"text-align:left\">Port to redirect http connections to https from<\/td>\n<td style=\"text-align:left\"><code>REDIRECT_PORT<\/code><\/td>\n<td style=\"text-align:left\"><code><\/code><\/td>\n<td style=\"text-align:left\">port<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>server.protocol<\/code><\/td>\n<td style=\"text-align:left\">The protocol the web application will use<\/td>\n<td style=\"text-align:left\"><code>PROTOCOL<\/code><\/td>\n<td style=\"text-align:left\"><code>http<\/code><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>server.sslPassphrase<\/code><\/td>\n<td style=\"text-align:left\">The passphrase of the SSL private key<\/td>\n<td style=\"text-align:left\"><code>SSL_PRIVATE_KEY_PASSPHRASE<\/code><\/td>\n<td style=\"text-align:left\"><code><\/code><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>server.sslPrivateKeyPath<\/code><\/td>\n<td style=\"text-align:left\">The filename of the SSL private key<\/td>\n<td style=\"text-align:left\"><code>SSL_PRIVATE_KEY_PATH<\/code><\/td>\n<td style=\"text-align:left\"><code><\/code><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>server.sslCertificatePath<\/code><\/td>\n<td style=\"text-align:left\">The filename of the SSL certificate<\/td>\n<td style=\"text-align:left\"><code>SSL_CERTIFICATE_PATH<\/code><\/td>\n<td style=\"text-align:left\"><code><\/code><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>server.sslIntermediateCertificatePath<\/code><\/td>\n<td style=\"text-align:left\">The filename of an SSL intermediate certificate, if any<\/td>\n<td style=\"text-align:left\"><code>SSL_INTERMEDIATE_CERTIFICATE_PATH<\/code><\/td>\n<td style=\"text-align:left\"><code><\/code><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>server.sslIntermediateCertificatePaths<\/code><\/td>\n<td style=\"text-align:left\">The filenames of SSL intermediate certificates, overrides sslIntermediateCertificate (singular)<\/td>\n<td style=\"text-align:left\"><code>SSL_INTERMEDIATE_CERTIFICATE_PATHS<\/code><\/td>\n<td style=\"text-align:left\"><code><\/code><\/td>\n<td style=\"text-align:left\">Array<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>datastore<\/code><\/td>\n<td style=\"text-align:left\">The name of the NPM module to use as a data connector for collection data<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code>@dadi\/api-mongodb<\/code><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>auth.tokenUrl<\/code><\/td>\n<td style=\"text-align:left\">The endpoint for bearer token generation<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code>\/token<\/code><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>auth.tokenTtl<\/code><\/td>\n<td style=\"text-align:left\">Number of seconds that bearer tokens are valid for<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code>1800<\/code><\/td>\n<td style=\"text-align:left\">Number<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>auth.clientCollection<\/code><\/td>\n<td style=\"text-align:left\">Name of the collection where clientId\/secret pairs are stored<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code>clientStore<\/code><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>auth.tokenCollection<\/code><\/td>\n<td style=\"text-align:left\">Name of the collection where bearer tokens are stored<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code>tokenStore<\/code><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>auth.datastore<\/code><\/td>\n<td style=\"text-align:left\">The name of the NPM module to use as a data connector for authentication data<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code>@dadi\/api-mongodb<\/code><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>auth.database<\/code><\/td>\n<td style=\"text-align:left\">The name of the database to use for authentication<\/td>\n<td style=\"text-align:left\"><code>DB_AUTH_NAME<\/code><\/td>\n<td style=\"text-align:left\"><code>test<\/code><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>auth.cleanupInterval<\/code><\/td>\n<td style=\"text-align:left\">The interval (in seconds) at which the token store will delete expired tokens from the database<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code>3600<\/code><\/td>\n<td style=\"text-align:left\">Number<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>auth.saltRounds<\/code><\/td>\n<td style=\"text-align:left\">The difficulty factor used when hashing client secrets (lower values mean hashes are faster to generate but easier to crack)<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code>10<\/code><\/td>\n<td style=\"text-align:left\">Number<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>caching.ttl<\/code><\/td>\n<td style=\"text-align:left\">Number of seconds that cached items are valid for<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code>300<\/code><\/td>\n<td style=\"text-align:left\">Number<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>caching.directory.enabled<\/code><\/td>\n<td style=\"text-align:left\">If enabled, cache files will be saved to the filesystem<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code>true<\/code><\/td>\n<td style=\"text-align:left\">Boolean<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>caching.directory.path<\/code><\/td>\n<td style=\"text-align:left\">The relative path to the cache directory<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code>.\/cache\/api<\/code><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>caching.directory.extension<\/code><\/td>\n<td style=\"text-align:left\">The extension to use for cache files<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code>json<\/code><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>caching.directory.autoFlush<\/code><\/td>\n<td style=\"text-align:left\">If true, cached files that are older than the specified TTL setting will be automatically deleted<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code>true<\/code><\/td>\n<td style=\"text-align:left\">Boolean<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>caching.directory.autoFlushInterval<\/code><\/td>\n<td style=\"text-align:left\">Interval to run the automatic flush mechanism, if enabled in <code>autoFlush<\/code><\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code>60<\/code><\/td>\n<td style=\"text-align:left\">Number<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>caching.redis.enabled<\/code><\/td>\n<td style=\"text-align:left\">If enabled, cache files will be saved to the specified Redis server<\/td>\n<td style=\"text-align:left\"><code>REDIS_ENABLED<\/code><\/td>\n<td style=\"text-align:left\"><code><\/code><\/td>\n<td style=\"text-align:left\">Boolean<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>caching.redis.host<\/code><\/td>\n<td style=\"text-align:left\">The Redis server host<\/td>\n<td style=\"text-align:left\"><code>REDIS_HOST<\/code><\/td>\n<td style=\"text-align:left\"><code>127.0.0.1<\/code><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>caching.redis.port<\/code><\/td>\n<td style=\"text-align:left\">The port for the Redis server<\/td>\n<td style=\"text-align:left\"><code>REDIS_PORT<\/code><\/td>\n<td style=\"text-align:left\"><code>6379<\/code><\/td>\n<td style=\"text-align:left\">port<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>caching.redis.password<\/code><\/td>\n<td style=\"text-align:left\">The password for the Redis server<\/td>\n<td style=\"text-align:left\"><code>REDIS_PASSWORD<\/code><\/td>\n<td style=\"text-align:left\"><code><\/code><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>logging.enabled<\/code><\/td>\n<td style=\"text-align:left\">If true, logging is enabled using the following settings.<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code>true<\/code><\/td>\n<td style=\"text-align:left\">Boolean<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>logging.level<\/code><\/td>\n<td style=\"text-align:left\">Sets the logging level.<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code>info<\/code><\/td>\n<td style=\"text-align:left\"><code>debug<\/code> or <code>info<\/code> or <code>warn<\/code> or <code>error<\/code> or <code>trace<\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>logging.path<\/code><\/td>\n<td style=\"text-align:left\">The absolute or relative path to the directory for log files.<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code>.\/log<\/code><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>logging.filename<\/code><\/td>\n<td style=\"text-align:left\">The name to use for the log file, without extension.<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code>api<\/code><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>logging.extension<\/code><\/td>\n<td style=\"text-align:left\">The extension to use for the log file.<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code>log<\/code><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>logging.accessLog.enabled<\/code><\/td>\n<td style=\"text-align:left\">If true, HTTP access logging is enabled. The log file name is similar to the setting used for normal logging, with the addition of \\&quot;access\\&quot;. For example <code>api.access.log<\/code>.<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code>true<\/code><\/td>\n<td style=\"text-align:left\">Boolean<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>logging.accessLog.kinesisStream<\/code><\/td>\n<td style=\"text-align:left\">An AWS Kinesis stream to write to log records to.<\/td>\n<td style=\"text-align:left\"><code>KINESIS_STREAM<\/code><\/td>\n<td style=\"text-align:left\"><code><\/code><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>paths.collections<\/code><\/td>\n<td style=\"text-align:left\">The relative or absolute path to collection specification files<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code>workspace\/collections<\/code><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>paths.endpoints<\/code><\/td>\n<td style=\"text-align:left\">The relative or absolute path to custom endpoint files<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code>workspace\/endpoints<\/code><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>paths.hooks<\/code><\/td>\n<td style=\"text-align:left\">The relative or absolute path to hook specification files<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code>workspace\/hooks<\/code><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>feedback<\/code><\/td>\n<td style=\"text-align:left\">If true, responses to DELETE requests will include a count of deleted and remaining documents, as opposed to an empty response body<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code><\/code><\/td>\n<td style=\"text-align:left\">Boolean<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>status.enabled<\/code><\/td>\n<td style=\"text-align:left\">If true, status endpoint is enabled.<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code><\/code><\/td>\n<td style=\"text-align:left\">Boolean<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>status.routes<\/code><\/td>\n<td style=\"text-align:left\">An array of routes to test. Each route object must contain properties <code>route<\/code> and <code>expectedResponseTime<\/code>.<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code><\/code><\/td>\n<td style=\"text-align:left\">Array<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>query.useVersionFilter<\/code><\/td>\n<td style=\"text-align:left\">If true, the API version parameter is extracted from the request URL and passed to the database query<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code><\/code><\/td>\n<td style=\"text-align:left\">Boolean<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>media.defaultBucket<\/code><\/td>\n<td style=\"text-align:left\">The name of the default media bucket<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code>mediaStore<\/code><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>media.buckets<\/code><\/td>\n<td style=\"text-align:left\">The names of media buckets to be used<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code><\/code><\/td>\n<td style=\"text-align:left\">Array<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>media.tokenSecret<\/code><\/td>\n<td style=\"text-align:left\">The secret key used to sign and verify tokens when uploading media<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code>catboat-beatific-drizzle<\/code><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>media.tokenExpiresIn<\/code><\/td>\n<td style=\"text-align:left\">The duration a signed token is valid for. Expressed in seconds or a string describing a time span (https:\/\/github.com\/zeit\/ms). Eg: 60, \\&quot;2 days\\&quot;, \\&quot;10h\\&quot;, \\&quot;7d\\&quot;<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code>1h<\/code><\/td>\n<td style=\"text-align:left\">*<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>media.storage<\/code><\/td>\n<td style=\"text-align:left\">Determines the storage type for uploads<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code>disk<\/code><\/td>\n<td style=\"text-align:left\"><code>disk<\/code> or <code>s3<\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>media.basePath<\/code><\/td>\n<td style=\"text-align:left\">Sets the root directory for uploads<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code>workspace\/media<\/code><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>media.pathFormat<\/code><\/td>\n<td style=\"text-align:left\">Determines the format for the generation of subdirectories to store uploads<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code>date<\/code><\/td>\n<td style=\"text-align:left\"><code>none<\/code> or <code>date<\/code> or <code>datetime<\/code> or <code>sha1\/4<\/code> or <code>sha1\/5<\/code> or <code>sha1\/8<\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>media.s3.accessKey<\/code><\/td>\n<td style=\"text-align:left\">The S3 access key used to connect to S3<\/td>\n<td style=\"text-align:left\"><code>AWS_S3_ACCESS_KEY<\/code><\/td>\n<td style=\"text-align:left\"><code><\/code><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>media.s3.secretKey<\/code><\/td>\n<td style=\"text-align:left\">The S3 secret key used to connect to S3<\/td>\n<td style=\"text-align:left\"><code>AWS_S3_SECRET_KEY<\/code><\/td>\n<td style=\"text-align:left\"><code><\/code><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>media.s3.bucketName<\/code><\/td>\n<td style=\"text-align:left\">The name of the AWS S3 or Digital Ocean Spaces bucket in which to store uploads<\/td>\n<td style=\"text-align:left\"><code>AWS_S3_BUCKET_NAME<\/code><\/td>\n<td style=\"text-align:left\"><code><\/code><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>media.s3.region<\/code><\/td>\n<td style=\"text-align:left\">The S3 region<\/td>\n<td style=\"text-align:left\"><code>AWS_S3_REGION<\/code><\/td>\n<td style=\"text-align:left\"><code><\/code><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>media.s3.endpoint<\/code><\/td>\n<td style=\"text-align:left\">The S3 endpoint, required for accessing a Digital Ocean Space<\/td>\n<td style=\"text-align:left\"><\/td>\n<td style=\"text-align:left\"><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>env<\/code><\/td>\n<td style=\"text-align:left\">The applicaton environment.<\/td>\n<td style=\"text-align:left\"><code>NODE_ENV<\/code><\/td>\n<td style=\"text-align:left\"><code>development<\/code><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>cluster<\/code><\/td>\n<td style=\"text-align:left\">If true, API runs in cluster mode, starting a worker for each CPU core<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code><\/code><\/td>\n<td style=\"text-align:left\">Boolean<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>cors<\/code><\/td>\n<td style=\"text-align:left\">If true, responses will include headers for cross-domain resource sharing<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code><\/code><\/td>\n<td style=\"text-align:left\">Boolean<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>internalFieldsPrefix<\/code><\/td>\n<td style=\"text-align:left\">The character to be used for prefixing internal fields<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code>_<\/code><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>databaseConnection.maxRetries<\/code><\/td>\n<td style=\"text-align:left\">The maximum number of times to reconnection attempts after a database fails<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code>10<\/code><\/td>\n<td style=\"text-align:left\">Number<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>i18n.defaultLanguage<\/code><\/td>\n<td style=\"text-align:left\">ISO-639-1 code of the default language<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code>en<\/code><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>i18n.languages<\/code><\/td>\n<td style=\"text-align:left\">List of ISO-639-1 codes for the supported languages<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code>[]<\/code><\/td>\n<td style=\"text-align:left\">Array<string><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>i18n.fieldCharacter<\/code><\/td>\n<td style=\"text-align:left\">Special character to denote a translated field<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code>:<\/code><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>search.enabled<\/code><\/td>\n<td style=\"text-align:left\">If true, API responds to collection \/search endpoints and will index content<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code>false<\/code><\/td>\n<td style=\"text-align:left\">Boolean<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>search.minQueryLength<\/code><\/td>\n<td style=\"text-align:left\">Minimum search string length<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code>3<\/code><\/td>\n<td style=\"text-align:left\">Number<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>search.wordCollection<\/code><\/td>\n<td style=\"text-align:left\">The name of the datastore collection that will hold tokenized words<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code>words<\/code><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>search.datastore<\/code><\/td>\n<td style=\"text-align:left\">The datastore module to use for storing and querying indexed documents<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code>@dadi\/api-mongodb<\/code><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>search.database<\/code><\/td>\n<td style=\"text-align:left\">The name of the database to use for storing and querying indexed documents<\/td>\n<td style=\"text-align:left\"><code>DB_SEARCH_NAME<\/code><\/td>\n<td style=\"text-align:left\"><code>search<\/code><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2><a href=\"#authentication\" id=\"authentication\" name=\"authentication\" class=\"anchor\">Anchor link<\/a> <a href=\"#authentication\">Authentication<\/a><\/h2>\n<p class=\"7xtjw4dqwy5mz7w3j\">DADI API provides a full-featured authentication layer based on the <a href=\"http:\/\/oauthbible.com\/#oauth-2-two-legged\">Client Credentials flow of oAuth 2.0<\/a>. Consumers must exchange a set of client credentials for a temporary access token, which must be appended to API requests.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">A client is represented as a set of credentials (ID + secret) and an access type, which can be set to <code>admin<\/code> or <code>user<\/code>. If set to <code>admin<\/code>, the client can perform any operation in API without any restrictions. If not, they will be subject to the rules set in the <a href=\"#access-control\">access control list<\/a>.<\/p>\n<h3><a href=\"#adding-clients\" id=\"adding-clients\" name=\"adding-clients\" class=\"anchor\">Anchor link<\/a> <a href=\"#adding-clients\">Adding clients<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">If you&#39;ve installed <a href=\"https:\/\/dadi.cloud\">DADI CLI<\/a> you can use that to create a new client in the database. See instructions for <a href=\"https:\/\/dadi.cloud#api-clientsadd\">Adding clients with CLI<\/a>.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">Alternatively, use the built in NPM script to start the Client Record Generator which will present you with a series of questions about the new client and insert a record into the configured database.<\/p>\n<pre><code class=\"lang-console\">$ <span class=\"hljs-built_in\">npm<\/span> explore @dadi\/api -- <span class=\"hljs-built_in\">npm<\/span> run create-client\n<\/code><\/pre>\n<blockquote class=\"warning\">\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Creating the client in the correct database<\/strong><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">To ensure the correct database is used for your environment, add an environment variable to the command:<\/p>\n<pre><code class=\"lang-console\">$ <span class=\"hljs-attribute\">NODE_ENV<\/span>=production npm explore @dadi\/api -- npm <span class=\"hljs-builtin-name\">run<\/span> create-client\n<\/code><\/pre>\n<\/blockquote>\n<h3><a href=\"#obtaining-an-access-token\" id=\"obtaining-an-access-token\" name=\"obtaining-an-access-token\" class=\"anchor\">Anchor link<\/a> <a href=\"#obtaining-an-access-token\">Obtaining an access token<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">Obtain an access token by sending a <code>POST<\/code> request to your API&#39;s token endpoint, passing your client credentials in the body of the request. The token endpoint is configurable using the property <a href=\"#configuration\"><code>auth.tokenRoute<\/code><\/a>, with a default value of <code>\/token<\/code>.<\/p>\n<pre><code class=\"lang-http\"><span class=\"hljs-keyword\">POST<\/span> <span class=\"hljs-string\">\/token<\/span> HTTP\/1.1\n<span class=\"hljs-attribute\">Content-Type<\/span>: application\/json\n<span class=\"hljs-attribute\">Host<\/span>: api.somedomain.tech\n<span class=\"hljs-attribute\">Connection<\/span>: close\n<span class=\"hljs-attribute\">Content-Length<\/span>: 65\n<span class=\"json\">{\n  <span class=\"hljs-attr\">\"clientId\"<\/span>: <span class=\"hljs-string\">\"my-client-key\"<\/span>,\n  <span class=\"hljs-attr\">\"secret\"<\/span>: <span class=\"hljs-string\">\"my-client-secret\"<\/span>\n}<\/span>\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\">With a request like the above, you should expect a response containing an access token, as below:<\/p>\n<pre><code class=\"lang-http\">HTTP\/1.1 <span class=\"hljs-number\">200<\/span> OK\n<span class=\"hljs-attribute\">Content-Type<\/span>: application\/json\n<span class=\"hljs-attribute\">Cache-Control<\/span>: no-store\n<span class=\"hljs-attribute\">Content-Length<\/span>: 95\n<span class=\"json\">{\n  <span class=\"hljs-attr\">\"accessToken\"<\/span>: <span class=\"hljs-string\">\"4172bbf1-0890-41c7-b0db-477095a288b6\"<\/span>,\n  <span class=\"hljs-attr\">\"tokenType\"<\/span>: <span class=\"hljs-string\">\"Bearer\"<\/span>,\n  <span class=\"hljs-attr\">\"expiresIn\"<\/span>: <span class=\"hljs-number\">3600<\/span>,\n  <span class=\"hljs-attr\">\"accessType\"<\/span>: <span class=\"hljs-string\">\"admin\"<\/span>\n}<\/span>\n<\/code><\/pre>\n<h3><a href=\"#using-an-access-token\" id=\"using-an-access-token\" name=\"using-an-access-token\" class=\"anchor\">Anchor link<\/a> <a href=\"#using-an-access-token\">Using an access token<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">Once you have an access token, each request to the API should include an <code>Authorization<\/code> header containing the token:<\/p>\n<pre><code class=\"lang-http\"><span class=\"hljs-keyword\">GET<\/span> <span class=\"hljs-string\">\/1.0\/library\/books<\/span> HTTP\/1.1\n<span class=\"hljs-attribute\">Content-Type<\/span>: application\/json\n<span class=\"hljs-attribute\">Authorization<\/span>: Bearer 4172bbf1-0890-41c7-b0db-477095a288b6\n<span class=\"hljs-attribute\">Host<\/span>: api.somedomain.tech\n<span class=\"hljs-attribute\">Connection<\/span>: close\n<\/code><\/pre>\n<h3><a href=\"#access-token-expiry\" id=\"access-token-expiry\" name=\"access-token-expiry\" class=\"anchor\">Anchor link<\/a> <a href=\"#access-token-expiry\">Access token expiry<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">The response returned when requesting an access token contains a property <code>expiresIn<\/code> which is set to the number of seconds the access token is valid for. When this period has elapsed, API automatically invalidates the access token and a subsequent request to API using that access token will return an <a href=\"#authentication-errors\">invalid token error<\/a>.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">The consumer application must request a new access token to continue communicating with the API.<\/p>\n<h3><a href=\"#internal-collections\" id=\"internal-collections\" name=\"internal-collections\" class=\"anchor\">Anchor link<\/a> <a href=\"#internal-collections\">Internal collections<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">Internally, API uses three collections to store authentication data:<\/p>\n<ul>\n<li><code>clientStore<\/code>: stores API clients<\/li>\n<li><code>roleStore<\/code>: stores API <a href=\"#roles\">roles<\/a><\/li>\n<li><code>accessStore<\/code>: stores aggregate data computed from clients, roles and permissions<\/li>\n<\/ul>\n<p class=\"7xtjw4dqwy5mz7w3j\">The names for these collections can be configured using the <code>auth.clientCollection<\/code>, <code>auth.roleCollection<\/code> and <code>auth.accessCollection<\/code> configuration properties, respectively. But unless they happen to clash with the name of one of your collections, you don&#39;t need to worry about setting them.<\/p>\n<h3><a href=\"#collection-authentication\" id=\"collection-authentication\" name=\"collection-authentication\" class=\"anchor\">Anchor link<\/a> <a href=\"#collection-authentication\">Collection authentication<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">By default, collections require all requests to be authenticated and authorised. This behaviour can be changed on a per-collection basis by changing the <code>authenticate<\/code> property in the <a href=\"#collection-settings\">collection settings block<\/a>, which can be set to:<\/p>\n<table>\n<thead>\n<tr>\n<th>Value<\/th>\n<th>Description<\/th>\n<th>Example<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>true<\/code> (default)<\/td>\n<td>Authentication is required for all HTTP verbs<\/td>\n<td><code>true<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>false<\/code><\/td>\n<td>Authentication is not required for any HTTP verb, making the collection fully accessible to anyone<\/td>\n<td><code>false<\/code><\/td>\n<\/tr>\n<tr>\n<td>Array<\/td>\n<td>Authentication is required only for some HTTP verbs, making the remaining verbs accessible to anyone<\/td>\n<td><code>[&quot;PUT&quot;, &quot;DELETE&quot;]<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p class=\"7xtjw4dqwy5mz7w3j\">The following configuration for a collection will allow all GET requests to proceed without authentication, while POST, PUT and DELETE requests will require authentication.<\/p>\n<pre><code class=\"lang-json\"><span class=\"hljs-string\">\"settings\"<\/span>: {\n  <span class=\"hljs-string\">\"authenticate\"<\/span>: [<span class=\"hljs-string\">\"POST\"<\/span>, <span class=\"hljs-string\">\"PUT\"<\/span>, <span class=\"hljs-string\">\"DELETE\"<\/span>]\n}\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\">See <a href=\"#collections\">more information about collection specifications and their configuration<\/a>.<\/p>\n<h3><a href=\"#authentication-errors\" id=\"authentication-errors\" name=\"authentication-errors\" class=\"anchor\">Anchor link<\/a> <a href=\"#authentication-errors\">Authentication errors<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">API responds with HTTP 401 Unauthorized errors when either the supplied credentials are incorrect or an invalid token has been provided. The <code>WWW-Authenticate<\/code> header indicates the nature of the error. In the case of an expired access token, a new one should be requested.<\/p>\n<h4><a href=\"#invalid-credentials\" id=\"invalid-credentials\" name=\"invalid-credentials\" class=\"anchor\">Anchor link<\/a> <a href=\"#invalid-credentials\">Invalid credentials<\/a><\/h4>\n<pre><code class=\"lang-http\">HTTP\/<span class=\"hljs-number\">1.1<\/span> <span class=\"hljs-number\">401<\/span> Unauthorized\nWWW-<span class=\"hljs-string\">Authenticate:<\/span> Bearer, error=<span class=\"hljs-string\">\"invalid_credentials\"<\/span>, error_description=<span class=\"hljs-string\">\"Invalid credentials supplied\"<\/span>\nContent-<span class=\"hljs-string\">Type:<\/span> application\/json\ncontent-<span class=\"hljs-string\">length:<\/span> <span class=\"hljs-number\">18<\/span>\n<span class=\"hljs-string\">Date:<\/span> Sun, <span class=\"hljs-number\">17<\/span> Sep <span class=\"hljs-number\">2017<\/span> <span class=\"hljs-number\">17<\/span>:<span class=\"hljs-number\">44<\/span>:<span class=\"hljs-number\">48<\/span> GMT\n<span class=\"hljs-string\">Connection:<\/span> close\n<\/code><\/pre>\n<h4><a href=\"#invalid-or-expired-token\" id=\"invalid-or-expired-token\" name=\"invalid-or-expired-token\" class=\"anchor\">Anchor link<\/a> <a href=\"#invalid-or-expired-token\">Invalid or expired token<\/a><\/h4>\n<pre><code class=\"lang-http\">HTTP\/<span class=\"hljs-number\">1.1<\/span> <span class=\"hljs-number\">401<\/span> Unauthorized\nWWW-<span class=\"hljs-string\">Authenticate:<\/span> Bearer, error=<span class=\"hljs-string\">\"invalid_token\"<\/span>, error_description=<span class=\"hljs-string\">\"Invalid or expired access token\"<\/span>\nContent-<span class=\"hljs-string\">Type:<\/span> application\/json\ncontent-<span class=\"hljs-string\">length:<\/span> <span class=\"hljs-number\">18<\/span>\n<span class=\"hljs-string\">Date:<\/span> Sun, <span class=\"hljs-number\">17<\/span> Sep <span class=\"hljs-number\">2017<\/span> <span class=\"hljs-number\">17<\/span>:<span class=\"hljs-number\">46<\/span>:<span class=\"hljs-number\">28<\/span> GMT\n<span class=\"hljs-string\">Connection:<\/span> close\n<\/code><\/pre>\n<h2><a href=\"#access-control\" id=\"access-control\" name=\"access-control\" class=\"anchor\">Anchor link<\/a> <a href=\"#access-control\">Access control<\/a><\/h2>\n<p class=\"7xtjw4dqwy5mz7w3j\">API includes a fully-fledged access control list (ACL) that makes it possible to specify in fine detail what each API client has permissions to do.<\/p>\n<blockquote class=\"advice\">\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>ACL terminology<\/strong><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">The access control list specifies which <a href=\"#clients\">clients<\/a> can access the various <a href=\"#resources\">resources<\/a> of an API instance. Clients can have permissions assigned to them directly, or via <a href=\"#roles\">roles<\/a>, which can in their turn extend other roles.<\/p>\n<\/blockquote>\n<h3><a href=\"#resources\" id=\"resources\" name=\"resources\" class=\"anchor\">Anchor link<\/a> <a href=\"#resources\">Resources<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">A <em>resource<\/em> is any entity in API that requires some level of authorisation to be accessed, like a collection or a custom endpoint. Resources are identified by a unique key with the following formats.<\/p>\n<table>\n<thead>\n<tr>\n<th>Key format<\/th>\n<th>Description<\/th>\n<th>Example<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>clients<\/code><\/td>\n<td>Access to API clients<\/td>\n<td><code>clients<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>collection:{DB}_{NAME}<\/code><\/td>\n<td>Access to the collection named <code>NAME<\/code> in the database <code>DB<\/code><\/td>\n<td><code>collection:library_book<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>endpoint:{VERSION}_{NAME}<\/code><\/td>\n<td>Access to the custom endpoint named <code>NAME<\/code> and version <code>VERSION<\/code><\/td>\n<td><code>endpoint:v1_full-book<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>media:{NAME}<\/code><\/td>\n<td>Access to the media bucket named <code>NAME<\/code><\/td>\n<td><code>media:photos<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>roles<\/code><\/td>\n<td>Access to API roles<\/td>\n<td><code>roles<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p class=\"7xtjw4dqwy5mz7w3j\">To specify what permissions someone has over a resource, an <em>access matrix<\/em> is used. It consists of an object that maps each of the CRUD methods (create, read, update and delete) to a value that determines whether that operation is allowed or not.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">For example, the following matrices specify that on the <code>library\/book<\/code> collection, the given client can read any document and update their own documents, whereas in the <code>library\/author<\/code> collection they can create, read and update any documents, being limited to deleting only the documents they have created.<\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"resources\"<\/span>: {\n    <span class=\"hljs-attr\">\"collection:library_book\"<\/span>: {\n      <span class=\"hljs-attr\">\"create\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n      <span class=\"hljs-attr\">\"delete\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n      <span class=\"hljs-attr\">\"deleteOwn\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n      <span class=\"hljs-attr\">\"read\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n      <span class=\"hljs-attr\">\"readOwn\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n      <span class=\"hljs-attr\">\"update\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n      <span class=\"hljs-attr\">\"updateOwn\"<\/span>: <span class=\"hljs-literal\">true<\/span>\n    },\n    <span class=\"hljs-attr\">\"collection:library_author\"<\/span>: {\n      <span class=\"hljs-attr\">\"create\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n      <span class=\"hljs-attr\">\"delete\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n      <span class=\"hljs-attr\">\"deleteOwn\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n      <span class=\"hljs-attr\">\"read\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n      <span class=\"hljs-attr\">\"readOwn\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n      <span class=\"hljs-attr\">\"update\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n      <span class=\"hljs-attr\">\"updateOwn\"<\/span>: <span class=\"hljs-literal\">false<\/span>\n    }\n  }\n}\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\">The table below shows all the CRUD methods supported.<\/p>\n<table>\n<thead>\n<tr>\n<th>Method<\/th>\n<th>Description<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>create<\/code><\/td>\n<td>Permission to create new instances of the resource<\/td>\n<\/tr>\n<tr>\n<td><code>delete<\/code><\/td>\n<td>Permission to delete instances of the resource<\/td>\n<\/tr>\n<tr>\n<td><code>deleteOwn<\/code><\/td>\n<td>Permission to delete instances of the resource that have been created by the requesting client<\/td>\n<\/tr>\n<tr>\n<td><code>read<\/code><\/td>\n<td>Permission to read instances of the resource<\/td>\n<\/tr>\n<tr>\n<td><code>readOwn<\/code><\/td>\n<td>Permission to read instances of the resource that have been created by the requesting client<\/td>\n<\/tr>\n<tr>\n<td><code>update<\/code><\/td>\n<td>Permission to update instances of the resource<\/td>\n<\/tr>\n<tr>\n<td><code>updateOwn<\/code><\/td>\n<td>Permission to update instances of the resource that have been created by the requesting client<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h4><a href=\"#advanced-permissions-for-collection-resources\" id=\"advanced-permissions-for-collection-resources\" name=\"advanced-permissions-for-collection-resources\" class=\"anchor\">Anchor link<\/a> <a href=\"#advanced-permissions-for-collection-resources\">Advanced permissions for collection resources<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">When setting up the access matrix for a collection resource, it&#39;s possible to define finer-grained permissions that limit access to a subset of the fields or to documents that match a certain query.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">To do this, the <em>Boolean<\/em> value that determines whether access is granted (<code>true<\/code>) or denied (<code>false<\/code>) gives way to an object that can contain one or both of the following properties:<\/p>\n<ul>\n<li>\n<p class=\"7xtjw4dqwy5mz7w3j\"><code>fields<\/code>: Limits the fields that the client has access to. Uses the <a href=\"https:\/\/docs.mongodb.com\/manual\/tutorial\/project-fields-from-query-results\/\">MongoDB projection<\/a> format, meaning that fields can be included or excluded, but not both. <\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">  <em>Example:<\/em><\/p>\n<pre><code class=\"lang-json\">  {\n    <span class=\"hljs-attr\">\"read\"<\/span>: {\n      <span class=\"hljs-attr\">\"fields\"<\/span>: {\n        <span class=\"hljs-attr\">\"title\"<\/span>: <span class=\"hljs-number\">1<\/span>,\n        <span class=\"hljs-attr\">\"author\"<\/span>: <span class=\"hljs-number\">1<\/span>\n      }\n    }\n  }\n<\/code><\/pre>\n<\/li>\n<li>\n<p class=\"7xtjw4dqwy5mz7w3j\"><code>filter<\/code>: Limits access to documents that match a given query. Supports any <a href=\"#filtering-documents\">filtering operator<\/a>. <\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">  <em>Example:<\/em><\/p>\n<pre><code class=\"lang-json\">  {\n    <span class=\"hljs-attr\">\"read\"<\/span>: {\n      <span class=\"hljs-attr\">\"filter\"<\/span>: {\n        <span class=\"hljs-attr\">\"category\"<\/span>: {\n          <span class=\"hljs-attr\">\"$in\"<\/span>: [<span class=\"hljs-string\">\"art\"<\/span>, <span class=\"hljs-string\">\"architecture\"<\/span>]\n        }\n      }\n    }\n  }\n<\/code><\/pre>\n<\/li>\n<\/ul>\n<p class=\"7xtjw4dqwy5mz7w3j\">The following table shows how each of these properties is interpreted by the various access types.<\/p>\n<table>\n<thead>\n<tr>\n<th>Method<\/th>\n<th><code>fields<\/code><\/th>\n<th><code>filter<\/code><\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>create<\/code><\/td>\n<td><em>N\/A<\/em><\/td>\n<td><em>N\/A<\/em><\/td>\n<\/tr>\n<tr>\n<td><code>delete<\/code><\/td>\n<td><em>N\/A<\/em><\/td>\n<td>Controls which documents can be deleted<\/td>\n<\/tr>\n<tr>\n<td><code>deleteOwn<\/code><\/td>\n<td><em>N\/A<\/em><\/td>\n<td>Controls which documents can be deleted<\/td>\n<\/tr>\n<tr>\n<td><code>read<\/code><\/td>\n<td>Controls which fields will be displayed<\/td>\n<td>Controls which documents can be read<\/td>\n<\/tr>\n<tr>\n<td><code>readOwn<\/code><\/td>\n<td>Controls which fields will be displayed<\/td>\n<td>Controls which documents can be read<\/td>\n<\/tr>\n<tr>\n<td><code>update<\/code><\/td>\n<td>Controls which fields can be updated<\/td>\n<td>Controls which documents can be updated<\/td>\n<\/tr>\n<tr>\n<td><code>updateOwn<\/code><\/td>\n<td>Controls which fields can be updated<\/td>\n<td>Controls which documents can be updated<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h4><a href=\"#resources-api\" id=\"resources-api\" name=\"resources-api\" class=\"anchor\">Anchor link<\/a> <a href=\"#resources-api\">Resources API<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">The Resources API provides a read-only endpoint for listing all the registered resources.<\/p>\n<details class=\"oar-method oar-method--get\">\n<summary class=\"oar-method__preview\">\n        <span class=\"oar-method-label\">GET<\/span><br \/>\n        <code class=\"oar-method__path\">\/api\/resources<\/code><br \/>\n        <span class=\"7xtjw4dqwy5mz7w3j\">Find all resources<\/span><br \/>\n      <\/summary>\n<div class=\"oar-method__body\">\n<p class=\"oar-method__description\">Returns a list of all the registered resources<\/p>\n<section class=\"oar-method-section\">\n<h4>Parameters<\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">No parameters<\/p>\n<\/section>\n<section class=\"oar-method-section\">\n<h4>Responses<\/h4>\n<table>\n<thead>\n<tr>\n<th>Code<\/th>\n<th>Description<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><strong>200<\/strong><\/td>\n<td class=\"td-main\">Successful operation<br \/>\n              <br class=\"7xtjw4dqwy5mz7w3j\"><br class=\"7xtjw4dqwy5mz7w3j\"><br \/>\n              <em>Example:<\/em><br \/>\n              <br class=\"7xtjw4dqwy5mz7w3j\"><\/p>\n<pre>\n                <code>{\n  <span class=\"hljs-attr\">\"results\"<\/span>: [\n    {\n      <span class=\"hljs-attr\">\"name\"<\/span>: <span class=\"hljs-string\">\"collection:library_book\"<\/span>,\n      <span class=\"hljs-attr\">\"description\"<\/span>: <span class=\"hljs-string\">\"library\/book collection\"<\/span>\n    }\n  ]\n}<\/code>\n              <\/pre>\n<\/td>\n<\/td>\n<tr>\n<td><strong>401<\/strong><\/td>\n<td class=\"td-main\">Access token is missing or invalid<\/td>\n<\/td>\n<tr>\n<td><strong>403<\/strong><\/td>\n<td class=\"td-main\">The client performing the operation doesn\u2019t have appropriate permissions<\/td>\n<\/td>\n<\/tbody>\n<\/table>\n<\/section><\/div>\n<\/details>\n<h3><a href=\"#clients\" id=\"clients\" name=\"clients\" class=\"anchor\">Anchor link<\/a> <a href=\"#clients\">Clients<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">Clients represent users or applications that wish to interact with API. When not given administrator privileges (i.e. <code>{&quot;accessType&quot;: &quot;admin&quot;}<\/code> in the database record), clients are subject to permissions defined in the access control list.<\/p>\n<h4><a href=\"#creating-a-client\" id=\"creating-a-client\" name=\"creating-a-client\" class=\"anchor\">Anchor link<\/a> <a href=\"#creating-a-client\">Creating a client<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">The Clients API makes it possible to create a client using a RESTful endpoint, as long as the requesting client has <code>create<\/code> access to the <code>clients<\/code> resource or has administrator access.<\/p>\n<blockquote class=\"warning\">\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Creating admin clients<\/strong><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">For security reasons, it&apos;s not possible to create clients with administrator access via the Clients API. If you need to create one, see the <a href=\"#adding-clients\">manual method<\/a> of adding a client, using either the DADI CLI or the <code>create-client<\/code> script.<\/p>\n<\/blockquote>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Request<\/strong><\/p>\n<pre><code class=\"lang-http\"><span class=\"hljs-keyword\">POST<\/span> <span class=\"hljs-string\">\/api\/clients<\/span> HTTP\/1.1\n<span class=\"hljs-attribute\">Content-Type<\/span>: application\/json\n<span class=\"hljs-attribute\">Authorization<\/span>: Bearer c389340b-718f-4eed-8e8e-3400a1c6cd5a\n<span class=\"json\">{\n  <span class=\"hljs-attr\">\"clientId\"<\/span>: <span class=\"hljs-string\">\"eduardo\"<\/span>,\n  <span class=\"hljs-attr\">\"secret\"<\/span>: <span class=\"hljs-string\">\"squirrel\"<\/span>\n}<\/span>\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Response<\/strong><\/p>\n<pre><code class=\"lang-http\">HTTP\/1.1 <span class=\"hljs-number\">200<\/span> OK\n<span class=\"hljs-attribute\">Content-Type<\/span>: application\/json\n<span class=\"json\">{\n  <span class=\"hljs-attr\">\"results\"<\/span>: [\n    {\n      <span class=\"hljs-attr\">\"clientId\"<\/span>: <span class=\"hljs-string\">\"eduardo\"<\/span>,\n      <span class=\"hljs-attr\">\"accessType\"<\/span>: <span class=\"hljs-string\">\"user\"<\/span>,\n      <span class=\"hljs-attr\">\"resources\"<\/span>: {},\n      <span class=\"hljs-attr\">\"roles\"<\/span>: []\n    }\n  ]\n}<\/span>\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\">The <code>resources<\/code> property in a client record shows the resources they have access to. By default, a client doesn&#39;t have access to anything until explicitly given the right permissions.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">Let&#39;s see how we can give this client access to some resources.<\/p>\n<h4><a href=\"#assigning-permissions\" id=\"assigning-permissions\" name=\"assigning-permissions\" class=\"anchor\">Anchor link<\/a> <a href=\"#assigning-permissions\">Assigning permissions<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">The Clients API includes a set of RESTful endpoints to manage the resources that a client has access to. The following request would give a client full permissions to access the <code>library\/book<\/code> collection.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Request<\/strong><\/p>\n<pre><code class=\"lang-http\"><span class=\"hljs-keyword\">POST<\/span> <span class=\"hljs-string\">\/api\/clients\/eduardo\/resources<\/span> HTTP\/1.1\n<span class=\"hljs-attribute\">Content-Type<\/span>: application\/json\n<span class=\"hljs-attribute\">Authorization<\/span>: Bearer c389340b-718f-4eed-8e8e-3400a1c6cd5a\n<span class=\"json\">{\n  <span class=\"hljs-attr\">\"name\"<\/span>: <span class=\"hljs-string\">\"collection:library_book\"<\/span>,\n  <span class=\"hljs-attr\">\"access\"<\/span>: {\n    <span class=\"hljs-attr\">\"create\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n    <span class=\"hljs-attr\">\"delete\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n    <span class=\"hljs-attr\">\"read\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n    <span class=\"hljs-attr\">\"update\"<\/span>: <span class=\"hljs-literal\">true<\/span>\n  }\n}<\/span>\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Response<\/strong><\/p>\n<pre><code class=\"lang-http\">HTTP\/1.1 <span class=\"hljs-number\">200<\/span> OK\n<span class=\"hljs-attribute\">Content-Type<\/span>: application\/json\n<span class=\"json\">{\n  <span class=\"hljs-attr\">\"results\"<\/span>: [\n    {\n      <span class=\"hljs-attr\">\"clientId\"<\/span>: <span class=\"hljs-string\">\"eduardo\"<\/span>,\n      <span class=\"hljs-attr\">\"accessType\"<\/span>: <span class=\"hljs-string\">\"user\"<\/span>,\n      <span class=\"hljs-attr\">\"resources\"<\/span>: {\n        <span class=\"hljs-attr\">\"collection:library_book\"<\/span>: {\n          <span class=\"hljs-attr\">\"create\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n          <span class=\"hljs-attr\">\"delete\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n          <span class=\"hljs-attr\">\"deleteOwn\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n          <span class=\"hljs-attr\">\"read\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n          <span class=\"hljs-attr\">\"readOwn\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n          <span class=\"hljs-attr\">\"update\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n          <span class=\"hljs-attr\">\"updateOwn\"<\/span>: <span class=\"hljs-literal\">false<\/span>       \n        }\n      },\n      <span class=\"hljs-attr\">\"roles\"<\/span>: []\n    }\n  ]\n}<\/span>\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\">At this point, <code>eduardo<\/code> can <a href=\"#obtaining-an-access-token\">request an access token<\/a> and access the <code>library\/book<\/code> collection.<\/p>\n<h4><a href=\"#adding-data-to-client-records\" id=\"adding-data-to-client-records\" name=\"adding-data-to-client-records\" class=\"anchor\">Anchor link<\/a> <a href=\"#adding-data-to-client-records\">Adding data to client records<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">The Clients API allows developers to associate arbitrary data with client records. This can be used by consumer applications to store data like personal information, user preferences or any type of metadata.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">This data is stored in an object called <code>data<\/code> within the client record, and it can be written to when a client is created (via a <code>POST<\/code> request) or at any point afterwards via an update (<code>PUT<\/code> request). See the <a href=\"#clients-api\">Clients API specification<\/a> for more details.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">When updating a client, the <code>data<\/code> object in the request body is processed as a partial update, which means the following in relation to any existing data object associated with the record:<\/p>\n<ol>\n<li>New properties will be appended to the existing data object;<\/li>\n<li>Properties with the same name as those in existing data object will be replaced;<\/li>\n<li>Properties set to <code>null<\/code> will be removed from the data object.<\/li>\n<\/ol>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Example 1<\/strong> <em>(creating a client with data):<\/em><\/p>\n<pre><code class=\"lang-http\"><span class=\"hljs-keyword\">POST<\/span> <span class=\"hljs-string\">\/api\/clients<\/span> HTTP\/1.1\n<span class=\"hljs-attribute\">Content-Type<\/span>: application\/json\n<span class=\"hljs-attribute\">Authorization<\/span>: Bearer c389340b-718f-4eed-8e8e-3400a1c6cd5a\n<span class=\"json\">{\n  <span class=\"hljs-attr\">\"clientId\"<\/span>: <span class=\"hljs-string\">\"eduardo\"<\/span>,\n  <span class=\"hljs-attr\">\"secret\"<\/span>: <span class=\"hljs-string\">\"sssshhh!\"<\/span>,\n  <span class=\"hljs-attr\">\"data\"<\/span>: {\n    <span class=\"hljs-attr\">\"firstName\"<\/span>: <span class=\"hljs-string\">\"Eduardo\"<\/span>\n  }\n}<\/span>\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Example 2<\/strong> <em>(adding data to an existing client):<\/em><\/p>\n<pre><code class=\"lang-http\"><span class=\"hljs-keyword\">PUT<\/span> <span class=\"hljs-string\">\/api\/clients\/eduardo<\/span> HTTP\/1.1\n<span class=\"hljs-attribute\">Content-Type<\/span>: application\/json\n<span class=\"hljs-attribute\">Authorization<\/span>: Bearer c389340b-718f-4eed-8e8e-3400a1c6cd5a\n<span class=\"json\">{\n  <span class=\"hljs-attr\">\"data\"<\/span>: {\n    <span class=\"hljs-attr\">\"lastName\"<\/span>: <span class=\"hljs-string\">\"Boucas\"<\/span>\n  }\n}<\/span>\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Example 3<\/strong> <em>(removing a data property from a client):<\/em><\/p>\n<pre><code class=\"lang-http\"><span class=\"hljs-keyword\">PUT<\/span> <span class=\"hljs-string\">\/api\/clients\/eduardo<\/span> HTTP\/1.1\n<span class=\"hljs-attribute\">Content-Type<\/span>: application\/json\n<span class=\"hljs-attribute\">Authorization<\/span>: Bearer c389340b-718f-4eed-8e8e-3400a1c6cd5a\n<span class=\"json\">{\n  <span class=\"hljs-attr\">\"data\"<\/span>: {\n    <span class=\"hljs-attr\">\"firstName\"<\/span>: <span class=\"hljs-literal\">null<\/span>\n  }\n}<\/span>\n<\/code><\/pre>\n<blockquote class=\"advice\">\n<p class=\"7xtjw4dqwy5mz7w3j\">Data properties prefixed with an underscore (e.g. <code>_userId<\/code>) can only be set and modified by admin clients, working as read-only properties for normal clients.<\/p>\n<\/blockquote>\n<h4><a href=\"#clients-api\" id=\"clients-api\" name=\"clients-api\" class=\"anchor\">Anchor link<\/a> <a href=\"#clients-api\">Clients API<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">The Clients API provides a set of RESTful endpoints that allow the creation and management of clients, as well as granting and revoking access to <a href=\"#resources\">resources<\/a> and <a href=\"#roles\">roles<\/a>.<\/p>\n<details class=\"oar-method oar-method--post\">\n<summary class=\"oar-method__preview\">\n        <span class=\"oar-method-label\">POST<\/span><br \/>\n        <code class=\"oar-method__path\">\/api\/clients<\/code><br \/>\n        <span class=\"7xtjw4dqwy5mz7w3j\">Create a client<\/span><br \/>\n      <\/summary>\n<div class=\"oar-method__body\">\n<p class=\"oar-method__description\">Creates a new client. The requesting client must have `create` access to the `clients` resource, or have an `accessType` of `admin`. Optionally, an arbitrary data object can be set using the `data` property.<\/p>\n<section class=\"oar-method-section\">\n<h4>Parameters<\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">No parameters<\/p>\n<\/section>\n<section class=\"oar-method-section\">\n<h4>Request body<\/h4>\n<ul>\n<li>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Content type<\/strong>: application\/json<\/p>\n<table>\n<thead>\n<tr>\n<th>Property<\/th>\n<th>Type<\/th>\n<\/thead>\n<tbody>\n<tr>\n<td>clientId<\/td>\n<td>string<\/td>\n<\/tr>\n<tr>\n<td>secret<\/td>\n<td>string<\/td>\n<\/tr>\n<tr>\n<td>data<\/td>\n<td>object<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<pre>\n              <code>{\n  <span class=\"hljs-attr\">\"clientId\"<\/span>: <span class=\"hljs-string\">\"eduardo\"<\/span>,\n  <span class=\"hljs-attr\">\"secret\"<\/span>: <span class=\"hljs-string\">\"squirrel\"<\/span>,\n  <span class=\"hljs-attr\">\"data\"<\/span>: {\n    <span class=\"hljs-attr\">\"firstName\"<\/span>: <span class=\"hljs-string\">\"Eduardo\"<\/span>\n  }\n}<\/code>\n            <\/pre>\n<\/li>\n<\/ul>\n<\/section>\n<section class=\"oar-method-section\">\n<h4>Responses<\/h4>\n<table>\n<thead>\n<tr>\n<th>Code<\/th>\n<th>Description<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><strong>201<\/strong><\/td>\n<td class=\"td-main\">Client added successfully; the created client is returned with the secret omitted<br \/>\n              <br class=\"7xtjw4dqwy5mz7w3j\"><br class=\"7xtjw4dqwy5mz7w3j\"><br \/>\n              <em>Example:<\/em><br \/>\n              <br class=\"7xtjw4dqwy5mz7w3j\"><\/p>\n<pre>\n                <code>{\n  <span class=\"hljs-attr\">\"results\"<\/span>: [\n    {\n      <span class=\"hljs-attr\">\"clientId\"<\/span>: <span class=\"hljs-string\">\"eduardo\"<\/span>,\n      <span class=\"hljs-attr\">\"accessType\"<\/span>: <span class=\"hljs-string\">\"user\"<\/span>\n    }\n  ]\n}<\/code>\n              <\/pre>\n<\/td>\n<\/td>\n<tr>\n<td><strong>401<\/strong><\/td>\n<td class=\"td-main\">Access token is missing or invalid<\/td>\n<\/td>\n<tr>\n<td><strong>403<\/strong><\/td>\n<td class=\"td-main\">The client performing the operation doesn\u2019t have appropriate permissions<\/td>\n<\/td>\n<tr>\n<td><strong>409<\/strong><\/td>\n<td class=\"td-main\">A client with the given ID already exists<\/td>\n<\/td>\n<\/tbody>\n<\/table>\n<\/section><\/div>\n<\/details>\n<details class=\"oar-method oar-method--get\">\n<summary class=\"oar-method__preview\">\n        <span class=\"oar-method-label\">GET<\/span><br \/>\n        <code class=\"oar-method__path\">\/api\/clients<\/code><br \/>\n        <span class=\"7xtjw4dqwy5mz7w3j\">Find all clients<\/span><br \/>\n      <\/summary>\n<div class=\"oar-method__body\">\n<p class=\"oar-method__description\">Returns an array of client records, with `secret` omitted.<\/p>\n<section class=\"oar-method-section\">\n<h4>Parameters<\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">No parameters<\/p>\n<\/section>\n<section class=\"oar-method-section\">\n<h4>Responses<\/h4>\n<table>\n<thead>\n<tr>\n<th>Code<\/th>\n<th>Description<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><strong>200<\/strong><\/td>\n<td class=\"td-main\">Successful operation; the clients are returned with the secret omitted. Response includes the roles granted and resources they have access to.<br \/>\n              <br class=\"7xtjw4dqwy5mz7w3j\"><br class=\"7xtjw4dqwy5mz7w3j\"><br \/>\n              <em>Example:<\/em><br \/>\n              <br class=\"7xtjw4dqwy5mz7w3j\"><\/p>\n<pre>\n                <code>{\n  <span class=\"hljs-attr\">\"results\"<\/span>: [\n    {\n      <span class=\"hljs-attr\">\"clientId\"<\/span>: <span class=\"hljs-string\">\"eduardo\"<\/span>,\n      <span class=\"hljs-attr\">\"accessType\"<\/span>: <span class=\"hljs-string\">\"user\"<\/span>,\n      <span class=\"hljs-attr\">\"resources\"<\/span>: {\n        <span class=\"hljs-attr\">\"collection:library_book\"<\/span>: {\n          <span class=\"hljs-attr\">\"create\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n          <span class=\"hljs-attr\">\"delete\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n          <span class=\"hljs-attr\">\"deleteOwn\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n          <span class=\"hljs-attr\">\"read\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n          <span class=\"hljs-attr\">\"readOwn\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n          <span class=\"hljs-attr\">\"update\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n          <span class=\"hljs-attr\">\"updateOwn\"<\/span>: <span class=\"hljs-literal\">true<\/span>\n        }\n      }\n    }\n  ]\n}<\/code>\n              <\/pre>\n<\/td>\n<\/td>\n<tr>\n<td><strong>401<\/strong><\/td>\n<td class=\"td-main\">Access token is missing or invalid<\/td>\n<\/td>\n<tr>\n<td><strong>403<\/strong><\/td>\n<td class=\"td-main\">The client performing the operation doesn\u2019t have appropriate permissions<\/td>\n<\/td>\n<\/tbody>\n<\/table>\n<\/section><\/div>\n<\/details>\n<details class=\"oar-method oar-method--get\">\n<summary class=\"oar-method__preview\">\n        <span class=\"oar-method-label\">GET<\/span><br \/>\n        <code class=\"oar-method__path\">\/api\/clients\/{clientId}<\/code><br \/>\n        <span class=\"7xtjw4dqwy5mz7w3j\">Find a client by ID<\/span><br \/>\n      <\/summary>\n<div class=\"oar-method__body\">\n<p class=\"oar-method__description\">Returns a single client<\/p>\n<section class=\"oar-method-section\">\n<h4>Parameters<\/h4>\n<table>\n<thead>\n<tr>\n<th>Name<\/th>\n<th>Type<\/th>\n<th>Description<\/th>\n<th>Required<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>clientId<\/td>\n<td>string (path)<\/td>\n<td>ID of client to return<\/td>\n<td><strong>Yes<\/strong><\/td>\n<\/td>\n<\/tbody>\n<\/table>\n<\/section>\n<section class=\"oar-method-section\">\n<h4>Responses<\/h4>\n<table>\n<thead>\n<tr>\n<th>Code<\/th>\n<th>Description<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><strong>200<\/strong><\/td>\n<td class=\"td-main\">Successful operation; the client is returned with the secret omitted. Response includes the roles granted and resources they have access to.<br \/>\n              <br class=\"7xtjw4dqwy5mz7w3j\"><br class=\"7xtjw4dqwy5mz7w3j\"><br \/>\n              <em>Example:<\/em><br \/>\n              <br class=\"7xtjw4dqwy5mz7w3j\"><\/p>\n<pre>\n                <code>{\n  <span class=\"hljs-attr\">\"results\"<\/span>: [\n    {\n      <span class=\"hljs-attr\">\"clientId\"<\/span>: <span class=\"hljs-string\">\"eduardo\"<\/span>,\n      <span class=\"hljs-attr\">\"accessType\"<\/span>: <span class=\"hljs-string\">\"user\"<\/span>,\n      <span class=\"hljs-attr\">\"resources\"<\/span>: {\n        <span class=\"hljs-attr\">\"collection:library_book\"<\/span>: {\n          <span class=\"hljs-attr\">\"create\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n          <span class=\"hljs-attr\">\"delete\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n          <span class=\"hljs-attr\">\"deleteOwn\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n          <span class=\"hljs-attr\">\"read\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n          <span class=\"hljs-attr\">\"readOwn\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n          <span class=\"hljs-attr\">\"update\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n          <span class=\"hljs-attr\">\"updateOwn\"<\/span>: <span class=\"hljs-literal\">true<\/span>\n        }\n      }\n    }\n  ]\n}<\/code>\n              <\/pre>\n<\/td>\n<\/td>\n<tr>\n<td><strong>401<\/strong><\/td>\n<td class=\"td-main\">Access token is missing or invalid<\/td>\n<\/td>\n<tr>\n<td><strong>403<\/strong><\/td>\n<td class=\"td-main\">The client performing the operation doesn\u2019t have appropriate permissions<\/td>\n<\/td>\n<tr>\n<td><strong>404<\/strong><\/td>\n<td class=\"td-main\">No client found with the given ID<\/td>\n<\/td>\n<\/tbody>\n<\/table>\n<\/section><\/div>\n<\/details>\n<details class=\"oar-method oar-method--put\">\n<summary class=\"oar-method__preview\">\n        <span class=\"oar-method-label\">PUT<\/span><br \/>\n        <code class=\"oar-method__path\">\/api\/clients\/{clientId}<\/code><br \/>\n        <span class=\"7xtjw4dqwy5mz7w3j\">Update an existing client<\/span><br \/>\n      <\/summary>\n<div class=\"oar-method__body\">\n<p class=\"oar-method__description\">Updates a client. It is not possible to change a client ID, as it is immutable. It is also not possible to change any resources or roles using this endpoint \u2013 the resources and roles endpoints should be used for that effect. For a non-admin client to update their own secret, they must include the current secret in the request payload.<\/p>\n<section class=\"oar-method-section\">\n<h4>Parameters<\/h4>\n<table>\n<thead>\n<tr>\n<th>Name<\/th>\n<th>Type<\/th>\n<th>Description<\/th>\n<th>Required<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>clientId<\/td>\n<td>string (path)<\/td>\n<td>ID of client to update<\/td>\n<td><strong>Yes<\/strong><\/td>\n<\/td>\n<\/tbody>\n<\/table>\n<\/section>\n<section class=\"oar-method-section\">\n<h4>Request body<\/h4>\n<ul>\n<li>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Content type<\/strong>: application\/json<\/p>\n<table>\n<thead>\n<tr>\n<th>Property<\/th>\n<th>Type<\/th>\n<\/thead>\n<tbody>\n<tr>\n<td>data<\/td>\n<td>object<\/td>\n<\/tr>\n<tr>\n<td>currentSecret<\/td>\n<td>string<\/td>\n<\/tr>\n<tr>\n<td>secret<\/td>\n<td>string<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<pre>\n              <code>{\n  <span class=\"hljs-attr\">\"data\"<\/span>: {\n    <span class=\"hljs-attr\">\"firstName\"<\/span>: <span class=\"hljs-string\">\"Eduardo\"<\/span>\n  },\n  <span class=\"hljs-attr\">\"currentSecret\"<\/span>: <span class=\"hljs-string\">\"current-secret\"<\/span>,\n  <span class=\"hljs-attr\">\"secret\"<\/span>: <span class=\"hljs-string\">\"new-secret\"<\/span>\n}<\/code>\n            <\/pre>\n<\/li>\n<\/ul>\n<\/section>\n<section class=\"oar-method-section\">\n<h4>Responses<\/h4>\n<table>\n<thead>\n<tr>\n<th>Code<\/th>\n<th>Description<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><strong>200<\/strong><\/td>\n<td class=\"td-main\">Successful operation; the client is returned with the secret omitted. Response includes the roles granted and resources they have access to.<br \/>\n              <br class=\"7xtjw4dqwy5mz7w3j\"><br class=\"7xtjw4dqwy5mz7w3j\"><br \/>\n              <em>Example:<\/em><br \/>\n              <br class=\"7xtjw4dqwy5mz7w3j\"><\/p>\n<pre>\n                <code>{\n  <span class=\"hljs-attr\">\"results\"<\/span>: [\n    {\n      <span class=\"hljs-attr\">\"clientId\"<\/span>: <span class=\"hljs-string\">\"eduardo\"<\/span>,\n      <span class=\"hljs-attr\">\"accessType\"<\/span>: <span class=\"hljs-string\">\"user\"<\/span>,\n      <span class=\"hljs-attr\">\"resources\"<\/span>: {\n        <span class=\"hljs-attr\">\"collection:library_book\"<\/span>: {\n          <span class=\"hljs-attr\">\"create\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n          <span class=\"hljs-attr\">\"delete\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n          <span class=\"hljs-attr\">\"deleteOwn\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n          <span class=\"hljs-attr\">\"read\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n          <span class=\"hljs-attr\">\"readOwn\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n          <span class=\"hljs-attr\">\"update\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n          <span class=\"hljs-attr\">\"updateOwn\"<\/span>: <span class=\"hljs-literal\">true<\/span>\n        }\n      }\n    }\n  ]\n}<\/code>\n              <\/pre>\n<\/td>\n<\/td>\n<tr>\n<td><strong>400<\/strong><\/td>\n<td class=\"td-main\">To update the client secret, the current secret must be supplied via the `currentSecret` property \/ The supplied current secret is not valid<\/td>\n<\/td>\n<tr>\n<td><strong>401<\/strong><\/td>\n<td class=\"td-main\">Access token is missing or invalid<\/td>\n<\/td>\n<tr>\n<td><strong>403<\/strong><\/td>\n<td class=\"td-main\">The client performing the operation doesn\u2019t have appropriate permissions<\/td>\n<\/td>\n<tr>\n<td><strong>404<\/strong><\/td>\n<td class=\"td-main\">No client found with the given ID<\/td>\n<\/td>\n<\/tbody>\n<\/table>\n<\/section><\/div>\n<\/details>\n<details class=\"oar-method oar-method--delete\">\n<summary class=\"oar-method__preview\">\n        <span class=\"oar-method-label\">DELETE<\/span><br \/>\n        <code class=\"oar-method__path\">\/api\/clients\/{clientId}<\/code><br \/>\n        <span class=\"7xtjw4dqwy5mz7w3j\">Delete an existing client<\/span><br \/>\n      <\/summary>\n<div class=\"oar-method__body\">\n<p class=\"oar-method__description\">Deletes a client.<\/p>\n<section class=\"oar-method-section\">\n<h4>Parameters<\/h4>\n<table>\n<thead>\n<tr>\n<th>Name<\/th>\n<th>Type<\/th>\n<th>Description<\/th>\n<th>Required<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>clientId<\/td>\n<td>string (path)<\/td>\n<td><\/td>\n<td><strong>Yes<\/strong><\/td>\n<\/td>\n<\/tbody>\n<\/table>\n<\/section>\n<section class=\"oar-method-section\">\n<h4>Responses<\/h4>\n<table>\n<thead>\n<tr>\n<th>Code<\/th>\n<th>Description<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><strong>204<\/strong><\/td>\n<td class=\"td-main\">Successful operation<\/td>\n<\/td>\n<tr>\n<td><strong>401<\/strong><\/td>\n<td class=\"td-main\">Access token is missing or invalid<\/td>\n<\/td>\n<tr>\n<td><strong>403<\/strong><\/td>\n<td class=\"td-main\">The client performing the operation doesn\u2019t have appropriate permissions<\/td>\n<\/td>\n<tr>\n<td><strong>404<\/strong><\/td>\n<td class=\"td-main\">No client found with the given ID<\/td>\n<\/td>\n<\/tbody>\n<\/table>\n<\/section><\/div>\n<\/details>\n<details class=\"oar-method oar-method--get\">\n<summary class=\"oar-method__preview\">\n        <span class=\"oar-method-label\">GET<\/span><br \/>\n        <code class=\"oar-method__path\">\/api\/client<\/code><br \/>\n        <span class=\"7xtjw4dqwy5mz7w3j\">Find the current client<\/span><br \/>\n      <\/summary>\n<div class=\"oar-method__body\">\n<p class=\"oar-method__description\">Returns the client associated with the bearer token present in the request<\/p>\n<section class=\"oar-method-section\">\n<h4>Parameters<\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">No parameters<\/p>\n<\/section>\n<section class=\"oar-method-section\">\n<h4>Responses<\/h4>\n<table>\n<thead>\n<tr>\n<th>Code<\/th>\n<th>Description<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><strong>200<\/strong><\/td>\n<td class=\"td-main\">Successful operation; the client is returned with the secret omitted. Response includes the roles granted and resources they have access to.<br \/>\n              <br class=\"7xtjw4dqwy5mz7w3j\"><br class=\"7xtjw4dqwy5mz7w3j\"><br \/>\n              <em>Example:<\/em><br \/>\n              <br class=\"7xtjw4dqwy5mz7w3j\"><\/p>\n<pre>\n                <code>{\n  <span class=\"hljs-attr\">\"results\"<\/span>: [\n    {\n      <span class=\"hljs-attr\">\"clientId\"<\/span>: <span class=\"hljs-string\">\"eduardo\"<\/span>,\n      <span class=\"hljs-attr\">\"accessType\"<\/span>: <span class=\"hljs-string\">\"user\"<\/span>,\n      <span class=\"hljs-attr\">\"resources\"<\/span>: {\n        <span class=\"hljs-attr\">\"collection:library_book\"<\/span>: {\n          <span class=\"hljs-attr\">\"create\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n          <span class=\"hljs-attr\">\"delete\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n          <span class=\"hljs-attr\">\"deleteOwn\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n          <span class=\"hljs-attr\">\"read\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n          <span class=\"hljs-attr\">\"readOwn\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n          <span class=\"hljs-attr\">\"update\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n          <span class=\"hljs-attr\">\"updateOwn\"<\/span>: <span class=\"hljs-literal\">true<\/span>\n        }\n      }\n    }\n  ]\n}<\/code>\n              <\/pre>\n<\/td>\n<\/td>\n<tr>\n<td><strong>401<\/strong><\/td>\n<td class=\"td-main\">Access token is missing or invalid<\/td>\n<\/td>\n<tr>\n<td><strong>403<\/strong><\/td>\n<td class=\"td-main\">The client performing the operation doesn\u2019t have appropriate permissions<\/td>\n<\/td>\n<\/tbody>\n<\/table>\n<\/section><\/div>\n<\/details>\n<details class=\"oar-method oar-method--put\">\n<summary class=\"oar-method__preview\">\n        <span class=\"oar-method-label\">PUT<\/span><br \/>\n        <code class=\"oar-method__path\">\/api\/client<\/code><br \/>\n        <span class=\"7xtjw4dqwy5mz7w3j\">Updates the current client<\/span><br \/>\n      <\/summary>\n<div class=\"oar-method__body\">\n<p class=\"oar-method__description\">Updates the client associated with the bearer token present in the request. It is not possible to change a client ID, as it is immutable. It is also not possible to change any resources or roles using this endpoint \u2013 the resources and roles endpoints should be used for that effect. For a non-admin client to update their own secret, they must include the current secret in the request payload.<\/p>\n<section class=\"oar-method-section\">\n<h4>Parameters<\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">No parameters<\/p>\n<\/section>\n<section class=\"oar-method-section\">\n<h4>Request body<\/h4>\n<ul>\n<li>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Content type<\/strong>: application\/json<\/p>\n<table>\n<thead>\n<tr>\n<th>Property<\/th>\n<th>Type<\/th>\n<\/thead>\n<tbody>\n<tr>\n<td>data<\/td>\n<td>object<\/td>\n<\/tr>\n<tr>\n<td>currentSecret<\/td>\n<td>string<\/td>\n<\/tr>\n<tr>\n<td>secret<\/td>\n<td>string<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<pre>\n              <code>{\n  <span class=\"hljs-attr\">\"data\"<\/span>: {\n    <span class=\"hljs-attr\">\"firstName\"<\/span>: <span class=\"hljs-string\">\"Eduardo\"<\/span>\n  },\n  <span class=\"hljs-attr\">\"currentSecret\"<\/span>: <span class=\"hljs-string\">\"current-secret\"<\/span>,\n  <span class=\"hljs-attr\">\"secret\"<\/span>: <span class=\"hljs-string\">\"new-secret\"<\/span>\n}<\/code>\n            <\/pre>\n<\/li>\n<\/ul>\n<\/section>\n<section class=\"oar-method-section\">\n<h4>Responses<\/h4>\n<table>\n<thead>\n<tr>\n<th>Code<\/th>\n<th>Description<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><strong>200<\/strong><\/td>\n<td class=\"td-main\">Successful operation; the client is returned with the secret omitted. Response includes the roles granted and resources they have access to.<br \/>\n              <br class=\"7xtjw4dqwy5mz7w3j\"><br class=\"7xtjw4dqwy5mz7w3j\"><br \/>\n              <em>Example:<\/em><br \/>\n              <br class=\"7xtjw4dqwy5mz7w3j\"><\/p>\n<pre>\n                <code>{\n  <span class=\"hljs-attr\">\"results\"<\/span>: [\n    {\n      <span class=\"hljs-attr\">\"clientId\"<\/span>: <span class=\"hljs-string\">\"eduardo\"<\/span>,\n      <span class=\"hljs-attr\">\"accessType\"<\/span>: <span class=\"hljs-string\">\"user\"<\/span>,\n      <span class=\"hljs-attr\">\"resources\"<\/span>: {\n        <span class=\"hljs-attr\">\"collection:library_book\"<\/span>: {\n          <span class=\"hljs-attr\">\"create\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n          <span class=\"hljs-attr\">\"delete\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n          <span class=\"hljs-attr\">\"deleteOwn\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n          <span class=\"hljs-attr\">\"read\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n          <span class=\"hljs-attr\">\"readOwn\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n          <span class=\"hljs-attr\">\"update\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n          <span class=\"hljs-attr\">\"updateOwn\"<\/span>: <span class=\"hljs-literal\">true<\/span>\n        }\n      }\n    }\n  ]\n}<\/code>\n              <\/pre>\n<\/td>\n<\/td>\n<tr>\n<td><strong>400<\/strong><\/td>\n<td class=\"td-main\">To update the client secret, the current secret must be supplied via the `currentSecret` property \/ The supplied current secret is not valid<\/td>\n<\/td>\n<tr>\n<td><strong>401<\/strong><\/td>\n<td class=\"td-main\">Access token is missing or invalid<\/td>\n<\/td>\n<tr>\n<td><strong>403<\/strong><\/td>\n<td class=\"td-main\">The client performing the operation doesn\u2019t have appropriate permissions<\/td>\n<\/td>\n<\/tbody>\n<\/table>\n<\/section><\/div>\n<\/details>\n<details class=\"oar-method oar-method--post\">\n<summary class=\"oar-method__preview\">\n        <span class=\"oar-method-label\">POST<\/span><br \/>\n        <code class=\"oar-method__path\">\/api\/clients\/{clientId}\/roles<\/code><br \/>\n        <span class=\"7xtjw4dqwy5mz7w3j\">Assign roles to an existing client<\/span><br \/>\n      <\/summary>\n<div class=\"oar-method__body\">\n<p class=\"oar-method__description\">The request body should contain an array of roles to assign to the specified client.<\/p>\n<section class=\"oar-method-section\">\n<h4>Parameters<\/h4>\n<table>\n<thead>\n<tr>\n<th>Name<\/th>\n<th>Type<\/th>\n<th>Description<\/th>\n<th>Required<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>clientId<\/td>\n<td>string (path)<\/td>\n<td>The Client to assign Roles to<\/td>\n<td><strong>Yes<\/strong><\/td>\n<\/td>\n<\/tbody>\n<\/table>\n<\/section>\n<section class=\"oar-method-section\">\n<h4>Request body<\/h4>\n<ul>\n<li>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Content type<\/strong>: application\/json<\/p>\n<table>\n<thead>\n<tr>\n<th>Property<\/th>\n<th>Type<\/th>\n<\/thead>\n<tbody>\n<tr>\n<td>N\/A<\/td>\n<td>array<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<pre>\n              <code>[\n  <span class=\"hljs-string\">\"employee\"<\/span>\n]<\/code>\n            <\/pre>\n<\/li>\n<\/ul>\n<\/section>\n<section class=\"oar-method-section\">\n<h4>Responses<\/h4>\n<table>\n<thead>\n<tr>\n<th>Code<\/th>\n<th>Description<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><strong>200<\/strong><\/td>\n<td class=\"td-main\">Role added to Client successfully; the updated client is returned with the secret omitted<br \/>\n              <br class=\"7xtjw4dqwy5mz7w3j\"><br class=\"7xtjw4dqwy5mz7w3j\"><br \/>\n              <em>Example:<\/em><br \/>\n              <br class=\"7xtjw4dqwy5mz7w3j\"><\/p>\n<pre>\n                <code>{\n  <span class=\"hljs-attr\">\"results\"<\/span>: [\n    {\n      <span class=\"hljs-attr\">\"clientId\"<\/span>: <span class=\"hljs-string\">\"eduardo\"<\/span>,\n      <span class=\"hljs-attr\">\"accessType\"<\/span>: <span class=\"hljs-string\">\"user\"<\/span>,\n      <span class=\"hljs-attr\">\"resources\"<\/span>: {\n        <span class=\"hljs-attr\">\"collection:library_book\"<\/span>: {\n          <span class=\"hljs-attr\">\"create\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n          <span class=\"hljs-attr\">\"delete\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n          <span class=\"hljs-attr\">\"deleteOwn\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n          <span class=\"hljs-attr\">\"read\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n          <span class=\"hljs-attr\">\"readOwn\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n          <span class=\"hljs-attr\">\"update\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n          <span class=\"hljs-attr\">\"updateOwn\"<\/span>: <span class=\"hljs-literal\">true<\/span>\n        }\n      },\n      <span class=\"hljs-attr\">\"roles\"<\/span>: [\n        <span class=\"hljs-string\">\"employee\"<\/span>\n      ]\n    }\n  ]\n}<\/code>\n              <\/pre>\n<\/td>\n<\/td>\n<tr>\n<td><strong>401<\/strong><\/td>\n<td class=\"td-main\">Access token is missing or invalid<\/td>\n<\/td>\n<tr>\n<td><strong>403<\/strong><\/td>\n<td class=\"td-main\">The client performing the operation doesn\u2019t have appropriate permissions<\/td>\n<\/td>\n<tr>\n<td><strong>404<\/strong><\/td>\n<td class=\"td-main\">No client found with the given ID<\/td>\n<\/td>\n<\/tbody>\n<\/table>\n<\/section><\/div>\n<\/details>\n<details class=\"oar-method oar-method--delete\">\n<summary class=\"oar-method__preview\">\n        <span class=\"oar-method-label\">DELETE<\/span><br \/>\n        <code class=\"oar-method__path\">\/api\/clients\/{clientId}\/roles\/{roleName}<\/code><br \/>\n        <span class=\"7xtjw4dqwy5mz7w3j\">Unassign role from an existing client<\/span><br \/>\n      <\/summary>\n<div class=\"oar-method__body\">\n<p class=\"oar-method__description\">\n<section class=\"oar-method-section\">\n<h4>Parameters<\/h4>\n<table>\n<thead>\n<tr>\n<th>Name<\/th>\n<th>Type<\/th>\n<th>Description<\/th>\n<th>Required<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>clientId<\/td>\n<td>string (path)<\/td>\n<td>The client that is being unassigned the specified Role<\/td>\n<td><strong>Yes<\/strong><\/td>\n<\/td>\n<tr>\n<td>roleName<\/td>\n<td>string (path)<\/td>\n<td>The name of the role to unassign<\/td>\n<td><strong>Yes<\/strong><\/td>\n<\/td>\n<\/tbody>\n<\/table>\n<\/section>\n<section class=\"oar-method-section\">\n<h4>Responses<\/h4>\n<table>\n<thead>\n<tr>\n<th>Code<\/th>\n<th>Description<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><strong>204<\/strong><\/td>\n<td class=\"td-main\">Successful operation<\/td>\n<\/td>\n<tr>\n<td><strong>401<\/strong><\/td>\n<td class=\"td-main\">Access token is missing or invalid<\/td>\n<\/td>\n<tr>\n<td><strong>403<\/strong><\/td>\n<td class=\"td-main\">The client performing the operation doesn\u2019t have appropriate permissions<\/td>\n<\/td>\n<tr>\n<td><strong>404<\/strong><\/td>\n<td class=\"td-main\">Client not found or role not assigned to client<\/td>\n<\/td>\n<\/tbody>\n<\/table>\n<\/section><\/div>\n<\/details>\n<details class=\"oar-method oar-method--post\">\n<summary class=\"oar-method__preview\">\n        <span class=\"oar-method-label\">POST<\/span><br \/>\n        <code class=\"oar-method__path\">\/api\/clients\/{clientId}\/resources<\/code><br \/>\n        <span class=\"7xtjw4dqwy5mz7w3j\">Give an existing client permissions to access a resource<\/span><br \/>\n      <\/summary>\n<div class=\"oar-method__body\">\n<p class=\"oar-method__description\">The request body should contain an object mapping access types to either a Boolean (granting or revoking that access type) or an object specifying field-level permissions and\/or permission filters<\/p>\n<section class=\"oar-method-section\">\n<h4>Parameters<\/h4>\n<table>\n<thead>\n<tr>\n<th>Name<\/th>\n<th>Type<\/th>\n<th>Description<\/th>\n<th>Required<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>clientId<\/td>\n<td>string (path)<\/td>\n<td><\/td>\n<td><strong>Yes<\/strong><\/td>\n<\/td>\n<\/tbody>\n<\/table>\n<\/section>\n<section class=\"oar-method-section\">\n<h4>Request body<\/h4>\n<ul>\n<li>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Content type<\/strong>: application\/json<\/p>\n<table>\n<thead>\n<tr>\n<th>Property<\/th>\n<th>Type<\/th>\n<\/thead>\n<tbody>\n<tr>\n<td>name<\/td>\n<td>string<\/td>\n<\/tr>\n<tr>\n<td>access<\/td>\n<td>object<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<pre>\n              <code>{\n  <span class=\"hljs-attr\">\"name\"<\/span>: <span class=\"hljs-string\">\"collection:library_book\"<\/span>,\n  <span class=\"hljs-attr\">\"access\"<\/span>: {\n    <span class=\"hljs-attr\">\"create\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n    <span class=\"hljs-attr\">\"delete\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n    <span class=\"hljs-attr\">\"deleteOwn\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n    <span class=\"hljs-attr\">\"read\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n    <span class=\"hljs-attr\">\"readOwn\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n    <span class=\"hljs-attr\">\"update\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n    <span class=\"hljs-attr\">\"updateOwn\"<\/span>: <span class=\"hljs-literal\">true<\/span>\n  }\n}<\/code>\n            <\/pre>\n<\/li>\n<\/ul>\n<\/section>\n<section class=\"oar-method-section\">\n<h4>Responses<\/h4>\n<table>\n<thead>\n<tr>\n<th>Code<\/th>\n<th>Description<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><strong>200<\/strong><\/td>\n<td class=\"td-main\">Resource added to Client successfully; the updated client is returned with the secret omitted<br \/>\n              <br class=\"7xtjw4dqwy5mz7w3j\"><br class=\"7xtjw4dqwy5mz7w3j\"><br \/>\n              <em>Example:<\/em><br \/>\n              <br class=\"7xtjw4dqwy5mz7w3j\"><\/p>\n<pre>\n                <code>{\n  <span class=\"hljs-attr\">\"results\"<\/span>: [\n    {\n      <span class=\"hljs-attr\">\"clientId\"<\/span>: <span class=\"hljs-string\">\"eduardo\"<\/span>,\n      <span class=\"hljs-attr\">\"accessType\"<\/span>: <span class=\"hljs-string\">\"user\"<\/span>,\n      <span class=\"hljs-attr\">\"resources\"<\/span>: {\n        <span class=\"hljs-attr\">\"collection:library_book\"<\/span>: {\n          <span class=\"hljs-attr\">\"create\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n          <span class=\"hljs-attr\">\"delete\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n          <span class=\"hljs-attr\">\"deleteOwn\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n          <span class=\"hljs-attr\">\"read\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n          <span class=\"hljs-attr\">\"readOwn\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n          <span class=\"hljs-attr\">\"update\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n          <span class=\"hljs-attr\">\"updateOwn\"<\/span>: <span class=\"hljs-literal\">true<\/span>\n        }\n      }\n    }\n  ]\n}<\/code>\n              <\/pre>\n<\/td>\n<\/td>\n<tr>\n<td><strong>401<\/strong><\/td>\n<td class=\"td-main\">Access token is missing or invalid<\/td>\n<\/td>\n<tr>\n<td><strong>403<\/strong><\/td>\n<td class=\"td-main\">The client performing the operation doesn\u2019t have appropriate permissions<\/td>\n<\/td>\n<tr>\n<td><strong>404<\/strong><\/td>\n<td class=\"td-main\">No client found with the given ID<\/td>\n<\/td>\n<\/tbody>\n<\/table>\n<\/section><\/div>\n<\/details>\n<details class=\"oar-method oar-method--delete\">\n<summary class=\"oar-method__preview\">\n        <span class=\"oar-method-label\">DELETE<\/span><br \/>\n        <code class=\"oar-method__path\">\/api\/clients\/{clientId}\/resources\/{resourceId}<\/code><br \/>\n        <span class=\"7xtjw4dqwy5mz7w3j\">Revoke an existing client&#8217;s permission for the specified resource<\/span><br \/>\n      <\/summary>\n<div class=\"oar-method__body\">\n<p class=\"oar-method__description\">\n<section class=\"oar-method-section\">\n<h4>Parameters<\/h4>\n<table>\n<thead>\n<tr>\n<th>Name<\/th>\n<th>Type<\/th>\n<th>Description<\/th>\n<th>Required<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>clientId<\/td>\n<td>string (path)<\/td>\n<td><\/td>\n<td><strong>Yes<\/strong><\/td>\n<\/td>\n<tr>\n<td>resourceId<\/td>\n<td>string (path)<\/td>\n<td><\/td>\n<td><strong>Yes<\/strong><\/td>\n<\/td>\n<\/tbody>\n<\/table>\n<\/section>\n<section class=\"oar-method-section\">\n<h4>Responses<\/h4>\n<table>\n<thead>\n<tr>\n<th>Code<\/th>\n<th>Description<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><strong>204<\/strong><\/td>\n<td class=\"td-main\">Access revoked successfully; the updated client is returned with the secret omitted<\/td>\n<\/td>\n<tr>\n<td><strong>401<\/strong><\/td>\n<td class=\"td-main\">Access token is missing or invalid<\/td>\n<\/td>\n<tr>\n<td><strong>403<\/strong><\/td>\n<td class=\"td-main\">The client performing the operation doesn\u2019t have appropriate permissions<\/td>\n<\/td>\n<tr>\n<td><strong>404<\/strong><\/td>\n<td class=\"td-main\">Client not found or resource not assigned to client<\/td>\n<\/td>\n<\/tbody>\n<\/table>\n<\/section><\/div>\n<\/details>\n<details class=\"oar-method oar-method--put\">\n<summary class=\"oar-method__preview\">\n        <span class=\"oar-method-label\">PUT<\/span><br \/>\n        <code class=\"oar-method__path\">\/api\/clients\/{clientId}\/resources\/{resourceId}<\/code><br \/>\n        <span class=\"7xtjw4dqwy5mz7w3j\">Update an existing clients&#8217; resource permissions<\/span><br \/>\n      <\/summary>\n<div class=\"oar-method__body\">\n<p class=\"oar-method__description\">The request body should contain an object mapping access types to either a Boolean (granting or revoking that access type) or an object specifying field-level permissions and\/or permission filters<\/p>\n<section class=\"oar-method-section\">\n<h4>Parameters<\/h4>\n<table>\n<thead>\n<tr>\n<th>Name<\/th>\n<th>Type<\/th>\n<th>Description<\/th>\n<th>Required<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>clientId<\/td>\n<td>string (path)<\/td>\n<td><\/td>\n<td><strong>Yes<\/strong><\/td>\n<\/td>\n<tr>\n<td>resourceId<\/td>\n<td>string (path)<\/td>\n<td><\/td>\n<td><strong>Yes<\/strong><\/td>\n<\/td>\n<\/tbody>\n<\/table>\n<\/section>\n<section class=\"oar-method-section\">\n<h4>Request body<\/h4>\n<ul>\n<li>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Content type<\/strong>: application\/json<\/p>\n<table>\n<thead>\n<tr>\n<th>Property<\/th>\n<th>Type<\/th>\n<\/thead>\n<tbody>\n<tr>\n<td>create<\/td>\n<td>boolean | object<\/td>\n<\/tr>\n<tr>\n<td>delete<\/td>\n<td>boolean | object<\/td>\n<\/tr>\n<tr>\n<td>deleteOwn<\/td>\n<td>boolean | object<\/td>\n<\/tr>\n<tr>\n<td>read<\/td>\n<td>boolean | object<\/td>\n<\/tr>\n<tr>\n<td>readOwn<\/td>\n<td>boolean | object<\/td>\n<\/tr>\n<tr>\n<td>update<\/td>\n<td>boolean | object<\/td>\n<\/tr>\n<tr>\n<td>updateOwn<\/td>\n<td>boolean | object<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<pre>\n              <code>{\n  <span class=\"hljs-attr\">\"create\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n  <span class=\"hljs-attr\">\"delete\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n  <span class=\"hljs-attr\">\"deleteOwn\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n  <span class=\"hljs-attr\">\"read\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n  <span class=\"hljs-attr\">\"readOwn\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n  <span class=\"hljs-attr\">\"update\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n  <span class=\"hljs-attr\">\"updateOwn\"<\/span>: <span class=\"hljs-literal\">true<\/span>\n}<\/code>\n            <\/pre>\n<\/li>\n<\/ul>\n<\/section>\n<section class=\"oar-method-section\">\n<h4>Responses<\/h4>\n<table>\n<thead>\n<tr>\n<th>Code<\/th>\n<th>Description<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><strong>200<\/strong><\/td>\n<td class=\"td-main\">Resource updated successfully; the updated client is returned with the secret omitted<br \/>\n              <br class=\"7xtjw4dqwy5mz7w3j\"><br class=\"7xtjw4dqwy5mz7w3j\"><br \/>\n              <em>Example:<\/em><br \/>\n              <br class=\"7xtjw4dqwy5mz7w3j\"><\/p>\n<pre>\n                <code>{\n  <span class=\"hljs-attr\">\"results\"<\/span>: [\n    {\n      <span class=\"hljs-attr\">\"clientId\"<\/span>: <span class=\"hljs-string\">\"eduardo\"<\/span>,\n      <span class=\"hljs-attr\">\"accessType\"<\/span>: <span class=\"hljs-string\">\"user\"<\/span>,\n      <span class=\"hljs-attr\">\"resources\"<\/span>: {\n        <span class=\"hljs-attr\">\"collection:library_book\"<\/span>: {\n          <span class=\"hljs-attr\">\"create\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n          <span class=\"hljs-attr\">\"delete\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n          <span class=\"hljs-attr\">\"deleteOwn\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n          <span class=\"hljs-attr\">\"read\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n          <span class=\"hljs-attr\">\"readOwn\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n          <span class=\"hljs-attr\">\"update\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n          <span class=\"hljs-attr\">\"updateOwn\"<\/span>: <span class=\"hljs-literal\">true<\/span>\n        }\n      }\n    }\n  ]\n}<\/code>\n              <\/pre>\n<\/td>\n<\/td>\n<tr>\n<td><strong>401<\/strong><\/td>\n<td class=\"td-main\">Access token is missing or invalid<\/td>\n<\/td>\n<tr>\n<td><strong>403<\/strong><\/td>\n<td class=\"td-main\">The client performing the operation doesn\u2019t have appropriate permissions<\/td>\n<\/td>\n<tr>\n<td><strong>404<\/strong><\/td>\n<td class=\"td-main\">Client not found or resource not assigned to client<\/td>\n<\/td>\n<\/tbody>\n<\/table>\n<\/section><\/div>\n<\/details>\n<h3><a href=\"#roles\" id=\"roles\" name=\"roles\" class=\"anchor\">Anchor link<\/a> <a href=\"#roles\">Roles<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">A role is a group of users that share a set of permissions to access a list of resources. In practice, it&#39;s an alternative way of giving permissions to clients.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">For example, imagine that you wanted to give clients <em>C1<\/em> and <em>C2<\/em> a set of permissions to access resource <em>R<\/em>. You could either grant permissions to that resource individually to each client record, or you could grant the permissions to a role and assign it to both clients.<\/p>\n<h4><a href=\"#reconciling-client-and-role-permissions\" id=\"reconciling-client-and-role-permissions\" name=\"reconciling-client-and-role-permissions\" class=\"anchor\">Anchor link<\/a> <a href=\"#reconciling-client-and-role-permissions\">Reconciling client and role permissions<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">A client may have their own resource permissions as well as permissions given by roles. Whenever a clash occurs, i.e. permissions for the same resource given directly and from a role, the access matrices are merged so that the broadest set of permissions is obtained.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">For example, imagine that a client has the following access matrices for a given resource, one assigned directly and the other resulting from a role.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Matrix 1<\/strong><\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"create\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n  <span class=\"hljs-attr\">\"delete\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n  <span class=\"hljs-attr\">\"deleteOwn\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n  <span class=\"hljs-attr\">\"read\"<\/span>: {\n    <span class=\"hljs-attr\">\"filter\"<\/span>: {\n      <span class=\"hljs-attr\">\"fieldOne\"<\/span>: <span class=\"hljs-string\">\"valueOne\"<\/span>\n    }\n  },\n  <span class=\"hljs-attr\">\"readOwn\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n  <span class=\"hljs-attr\">\"update\"<\/span>: {\n    <span class=\"hljs-attr\">\"fields\"<\/span>: {\n      <span class=\"hljs-attr\">\"fieldOne\"<\/span>: <span class=\"hljs-number\">1<\/span>\n    }\n  },\n  <span class=\"hljs-attr\">\"updateOwn\"<\/span>: <span class=\"hljs-literal\">false<\/span>\n}\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Matrix 2<\/strong><\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"create\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n  <span class=\"hljs-attr\">\"delete\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n  <span class=\"hljs-attr\">\"deleteOwn\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n  <span class=\"hljs-attr\">\"read\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n  <span class=\"hljs-attr\">\"readOwn\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n  <span class=\"hljs-attr\">\"update\"<\/span>: {\n    <span class=\"hljs-attr\">\"fields\"<\/span>: {\n      <span class=\"hljs-attr\">\"fieldTwo\"<\/span>: <span class=\"hljs-number\">1<\/span>,\n      <span class=\"hljs-attr\">\"fieldThree\"<\/span>: <span class=\"hljs-number\">1<\/span>\n    }\n  },\n  <span class=\"hljs-attr\">\"updateOwn\"<\/span>: <span class=\"hljs-literal\">false<\/span>\n}\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Resulting matrix<\/strong><\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"create\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n  <span class=\"hljs-attr\">\"delete\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n  <span class=\"hljs-attr\">\"deleteOwn\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n  <span class=\"hljs-attr\">\"read\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n  <span class=\"hljs-attr\">\"readOwn\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n  <span class=\"hljs-attr\">\"update\"<\/span>: {\n    <span class=\"hljs-attr\">\"fields\"<\/span>: {\n      <span class=\"hljs-attr\">\"fieldOne\"<\/span>: <span class=\"hljs-number\">1<\/span>,\n      <span class=\"hljs-attr\">\"fieldTwo\"<\/span>: <span class=\"hljs-number\">1<\/span>,\n      <span class=\"hljs-attr\">\"fieldThree\"<\/span>: <span class=\"hljs-number\">1<\/span>\n    }\n  },\n  <span class=\"hljs-attr\">\"updateOwn\"<\/span>: <span class=\"hljs-literal\">false<\/span>\n}\n<\/code><\/pre>\n<h4><a href=\"#extending-roles\" id=\"extending-roles\" name=\"extending-roles\" class=\"anchor\">Anchor link<\/a> <a href=\"#extending-roles\">Extending roles<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">Roles can extend (or inherit from) other roles. If role <em>R1<\/em> extends role <em>R2<\/em>, then clients with <em>R1<\/em> will get the permissions granted by that role plus any permissions granted by <em>R2<\/em>. The inheritance chain can go on indefinitely.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">Role inheritance is a good way to represent hierarchy typically present in organisations. For example, you could create a <code>manager<\/code> role that extends an <code>employee<\/code> role, since managers can usually do all the operations available to employees plus some of their own.<\/p>\n<h4><a href=\"#roles-api\" id=\"roles-api\" name=\"roles-api\" class=\"anchor\">Anchor link<\/a> <a href=\"#roles-api\">Roles API<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">The Roles API provides a set of RESTful endpoints that allow the creation and management of roles, including granting and revoking access to <a href=\"#resources\">resources<\/a>.<\/p>\n<details class=\"oar-method oar-method--post\">\n<summary class=\"oar-method__preview\">\n        <span class=\"oar-method-label\">POST<\/span><br \/>\n        <code class=\"oar-method__path\">\/api\/roles<\/code><br \/>\n        <span class=\"7xtjw4dqwy5mz7w3j\">Create a new role<\/span><br \/>\n      <\/summary>\n<div class=\"oar-method__body\">\n<p class=\"oar-method__description\">The body must contain a `name` property with the name of the role to create. Optionally, it may also contain an `extends` property that specifies the name of a role to be extended<\/p>\n<section class=\"oar-method-section\">\n<h4>Parameters<\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">No parameters<\/p>\n<\/section>\n<section class=\"oar-method-section\">\n<h4>Request body<\/h4>\n<ul>\n<li>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Content type<\/strong>: application\/json<\/p>\n<table>\n<thead>\n<tr>\n<th>Property<\/th>\n<th>Type<\/th>\n<\/thead>\n<tbody>\n<tr>\n<td>name<\/td>\n<td>string<\/td>\n<\/tr>\n<tr>\n<td>extends<\/td>\n<td>string<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<pre>\n              <code>{\n  <span class=\"hljs-attr\">\"name\"<\/span>: <span class=\"hljs-string\">\"manager\"<\/span>,\n  <span class=\"hljs-attr\">\"extends\"<\/span>: <span class=\"hljs-string\">\"employee\"<\/span>\n}<\/code>\n            <\/pre>\n<\/li>\n<\/ul>\n<\/section>\n<section class=\"oar-method-section\">\n<h4>Responses<\/h4>\n<table>\n<thead>\n<tr>\n<th>Code<\/th>\n<th>Description<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><strong>201<\/strong><\/td>\n<td class=\"td-main\">Successful operation<br \/>\n              <br class=\"7xtjw4dqwy5mz7w3j\"><br class=\"7xtjw4dqwy5mz7w3j\"><br \/>\n              <em>Example:<\/em><br \/>\n              <br class=\"7xtjw4dqwy5mz7w3j\"><\/p>\n<pre>\n                <code>{\n  <span class=\"hljs-attr\">\"results\"<\/span>: [\n    {\n      <span class=\"hljs-attr\">\"name\"<\/span>: <span class=\"hljs-string\">\"manager\"<\/span>,\n      <span class=\"hljs-attr\">\"extends\"<\/span>: <span class=\"hljs-string\">\"employee\"<\/span>\n    }\n  ]\n}<\/code>\n              <\/pre>\n<\/td>\n<\/td>\n<tr>\n<td><strong>401<\/strong><\/td>\n<td class=\"td-main\">Access token is missing or invalid<\/td>\n<\/td>\n<tr>\n<td><strong>403<\/strong><\/td>\n<td class=\"td-main\">The client performing the operation doesn\u2019t have appropriate permissions<\/td>\n<\/td>\n<tr>\n<td><strong>409<\/strong><\/td>\n<td class=\"td-main\">Role already exists<\/td>\n<\/td>\n<\/tbody>\n<\/table>\n<\/section><\/div>\n<\/details>\n<details class=\"oar-method oar-method--get\">\n<summary class=\"oar-method__preview\">\n        <span class=\"oar-method-label\">GET<\/span><br \/>\n        <code class=\"oar-method__path\">\/api\/roles\/{roleName}<\/code><br \/>\n        <span class=\"7xtjw4dqwy5mz7w3j\">Find a role by name<\/span><br \/>\n      <\/summary>\n<div class=\"oar-method__body\">\n<p class=\"oar-method__description\">Returns a single role<\/p>\n<section class=\"oar-method-section\">\n<h4>Parameters<\/h4>\n<table>\n<thead>\n<tr>\n<th>Name<\/th>\n<th>Type<\/th>\n<th>Description<\/th>\n<th>Required<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>roleName<\/td>\n<td>string (path)<\/td>\n<td>The name of the Role to return<\/td>\n<td><strong>Yes<\/strong><\/td>\n<\/td>\n<\/tbody>\n<\/table>\n<\/section>\n<section class=\"oar-method-section\">\n<h4>Responses<\/h4>\n<table>\n<thead>\n<tr>\n<th>Code<\/th>\n<th>Description<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><strong>200<\/strong><\/td>\n<td class=\"td-main\">Successful operation<br \/>\n              <br class=\"7xtjw4dqwy5mz7w3j\"><br class=\"7xtjw4dqwy5mz7w3j\"><br \/>\n              <em>Example:<\/em><br \/>\n              <br class=\"7xtjw4dqwy5mz7w3j\"><\/p>\n<pre>\n                <code>{\n  <span class=\"hljs-attr\">\"results\"<\/span>: [\n    {\n      <span class=\"hljs-attr\">\"name\"<\/span>: <span class=\"hljs-string\">\"manager\"<\/span>,\n      <span class=\"hljs-attr\">\"extends\"<\/span>: <span class=\"hljs-string\">\"employee\"<\/span>\n    }\n  ]\n}<\/code>\n              <\/pre>\n<\/td>\n<\/td>\n<tr>\n<td><strong>401<\/strong><\/td>\n<td class=\"td-main\">Access token is missing or invalid<\/td>\n<\/td>\n<tr>\n<td><strong>403<\/strong><\/td>\n<td class=\"td-main\">The client performing the operation doesn\u2019t have appropriate permissions<\/td>\n<\/td>\n<tr>\n<td><strong>404<\/strong><\/td>\n<td class=\"td-main\">No role found with the given name<\/td>\n<\/td>\n<\/tbody>\n<\/table>\n<\/section><\/div>\n<\/details>\n<details class=\"oar-method oar-method--put\">\n<summary class=\"oar-method__preview\">\n        <span class=\"oar-method-label\">PUT<\/span><br \/>\n        <code class=\"oar-method__path\">\/api\/roles\/{roleName}<\/code><br \/>\n        <span class=\"7xtjw4dqwy5mz7w3j\">Update an existing role<\/span><br \/>\n      <\/summary>\n<div class=\"oar-method__body\">\n<p class=\"oar-method__description\">The request body may contain an optional object that specifies a role to be extended via the `extends` property; if that property is set to `null`, the inheritance relationship will be removed<\/p>\n<section class=\"oar-method-section\">\n<h4>Parameters<\/h4>\n<table>\n<thead>\n<tr>\n<th>Name<\/th>\n<th>Type<\/th>\n<th>Description<\/th>\n<th>Required<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>roleName<\/td>\n<td>string (path)<\/td>\n<td>The name of the Role to update<\/td>\n<td><strong>Yes<\/strong><\/td>\n<\/td>\n<\/tbody>\n<\/table>\n<\/section>\n<section class=\"oar-method-section\">\n<h4>Request body<\/h4>\n<ul>\n<li>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Content type<\/strong>: application\/json<\/p>\n<table>\n<thead>\n<tr>\n<th>Property<\/th>\n<th>Type<\/th>\n<\/thead>\n<tbody>\n<tr>\n<td>extends<\/td>\n<td>string<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<pre>\n              <code>{\n  <span class=\"hljs-attr\">\"extends\"<\/span>: <span class=\"hljs-string\">\"employee\"<\/span>\n}<\/code>\n            <\/pre>\n<\/li>\n<\/ul>\n<\/section>\n<section class=\"oar-method-section\">\n<h4>Responses<\/h4>\n<table>\n<thead>\n<tr>\n<th>Code<\/th>\n<th>Description<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><strong>200<\/strong><\/td>\n<td class=\"td-main\">Successful operation<br \/>\n              <br class=\"7xtjw4dqwy5mz7w3j\"><br class=\"7xtjw4dqwy5mz7w3j\"><br \/>\n              <em>Example:<\/em><br \/>\n              <br class=\"7xtjw4dqwy5mz7w3j\"><\/p>\n<pre>\n                <code>{\n  <span class=\"hljs-attr\">\"results\"<\/span>: [\n    {\n      <span class=\"hljs-attr\">\"name\"<\/span>: <span class=\"hljs-string\">\"manager\"<\/span>,\n      <span class=\"hljs-attr\">\"extends\"<\/span>: <span class=\"hljs-string\">\"employee\"<\/span>\n    }\n  ]\n}<\/code>\n              <\/pre>\n<\/td>\n<\/td>\n<tr>\n<td><strong>400<\/strong><\/td>\n<td class=\"td-main\">The role being extended does not exist<\/td>\n<\/td>\n<tr>\n<td><strong>401<\/strong><\/td>\n<td class=\"td-main\">Access token is missing or invalid<\/td>\n<\/td>\n<tr>\n<td><strong>403<\/strong><\/td>\n<td class=\"td-main\">The client performing the operation doesn\u2019t have appropriate permissions<\/td>\n<\/td>\n<tr>\n<td><strong>404<\/strong><\/td>\n<td class=\"td-main\">No role found with the given name<\/td>\n<\/td>\n<\/tbody>\n<\/table>\n<\/section><\/div>\n<\/details>\n<details class=\"oar-method oar-method--delete\">\n<summary class=\"oar-method__preview\">\n        <span class=\"oar-method-label\">DELETE<\/span><br \/>\n        <code class=\"oar-method__path\">\/api\/roles\/{roleName}<\/code><br \/>\n        <span class=\"7xtjw4dqwy5mz7w3j\">Delete an existing Role<\/span><br \/>\n      <\/summary>\n<div class=\"oar-method__body\">\n<p class=\"oar-method__description\">\n<section class=\"oar-method-section\">\n<h4>Parameters<\/h4>\n<table>\n<thead>\n<tr>\n<th>Name<\/th>\n<th>Type<\/th>\n<th>Description<\/th>\n<th>Required<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>roleName<\/td>\n<td>string (path)<\/td>\n<td>The name of the Role to delete<\/td>\n<td><strong>Yes<\/strong><\/td>\n<\/td>\n<\/tbody>\n<\/table>\n<\/section>\n<section class=\"oar-method-section\">\n<h4>Responses<\/h4>\n<table>\n<thead>\n<tr>\n<th>Code<\/th>\n<th>Description<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><strong>204<\/strong><\/td>\n<td class=\"td-main\">Successful operation<\/td>\n<\/td>\n<tr>\n<td><strong>401<\/strong><\/td>\n<td class=\"td-main\">Access token is missing or invalid<\/td>\n<\/td>\n<tr>\n<td><strong>403<\/strong><\/td>\n<td class=\"td-main\">The client performing the operation doesn\u2019t have appropriate permissions<\/td>\n<\/td>\n<tr>\n<td><strong>404<\/strong><\/td>\n<td class=\"td-main\">No role found with the given name<\/td>\n<\/td>\n<\/tbody>\n<\/table>\n<\/section><\/div>\n<\/details>\n<details class=\"oar-method oar-method--post\">\n<summary class=\"oar-method__preview\">\n        <span class=\"oar-method-label\">POST<\/span><br \/>\n        <code class=\"oar-method__path\">\/api\/roles\/{roleName}\/resources<\/code><br \/>\n        <span class=\"7xtjw4dqwy5mz7w3j\">Give an existing role permissions to access a resource<\/span><br \/>\n      <\/summary>\n<div class=\"oar-method__body\">\n<p class=\"oar-method__description\">The request body should contain an object mapping access types to either a Boolean (granting or revoking that access type) or an object specifying field-level permissions and\/or permission filters<\/p>\n<section class=\"oar-method-section\">\n<h4>Parameters<\/h4>\n<table>\n<thead>\n<tr>\n<th>Name<\/th>\n<th>Type<\/th>\n<th>Description<\/th>\n<th>Required<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>roleName<\/td>\n<td>string (path)<\/td>\n<td><\/td>\n<td><strong>Yes<\/strong><\/td>\n<\/td>\n<\/tbody>\n<\/table>\n<\/section>\n<section class=\"oar-method-section\">\n<h4>Request body<\/h4>\n<ul>\n<li>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Content type<\/strong>: application\/json<\/p>\n<table>\n<thead>\n<tr>\n<th>Property<\/th>\n<th>Type<\/th>\n<\/thead>\n<tbody>\n<tr>\n<td>name<\/td>\n<td>string<\/td>\n<\/tr>\n<tr>\n<td>access<\/td>\n<td>object<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<pre>\n              <code>{\n  <span class=\"hljs-attr\">\"name\"<\/span>: <span class=\"hljs-string\">\"collection:library_book\"<\/span>,\n  <span class=\"hljs-attr\">\"access\"<\/span>: {\n    <span class=\"hljs-attr\">\"create\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n    <span class=\"hljs-attr\">\"delete\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n    <span class=\"hljs-attr\">\"deleteOwn\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n    <span class=\"hljs-attr\">\"read\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n    <span class=\"hljs-attr\">\"readOwn\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n    <span class=\"hljs-attr\">\"update\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n    <span class=\"hljs-attr\">\"updateOwn\"<\/span>: <span class=\"hljs-literal\">true<\/span>\n  }\n}<\/code>\n            <\/pre>\n<\/li>\n<\/ul>\n<\/section>\n<section class=\"oar-method-section\">\n<h4>Responses<\/h4>\n<table>\n<thead>\n<tr>\n<th>Code<\/th>\n<th>Description<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><strong>200<\/strong><\/td>\n<td class=\"td-main\">Resource added to role successfully; the updated role is returned<br \/>\n              <br class=\"7xtjw4dqwy5mz7w3j\"><br class=\"7xtjw4dqwy5mz7w3j\"><br \/>\n              <em>Example:<\/em><br \/>\n              <br class=\"7xtjw4dqwy5mz7w3j\"><\/p>\n<pre>\n                <code>{\n  <span class=\"hljs-attr\">\"results\"<\/span>: [\n    {\n      <span class=\"hljs-attr\">\"name\"<\/span>: <span class=\"hljs-string\">\"manager\"<\/span>,\n      <span class=\"hljs-attr\">\"extends\"<\/span>: <span class=\"hljs-string\">\"employee\"<\/span>,\n      <span class=\"hljs-attr\">\"resources\"<\/span>: {\n        <span class=\"hljs-attr\">\"collection:library_book\"<\/span>: {\n          <span class=\"hljs-attr\">\"create\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n          <span class=\"hljs-attr\">\"delete\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n          <span class=\"hljs-attr\">\"deleteOwn\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n          <span class=\"hljs-attr\">\"read\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n          <span class=\"hljs-attr\">\"readOwn\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n          <span class=\"hljs-attr\">\"update\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n          <span class=\"hljs-attr\">\"updateOwn\"<\/span>: <span class=\"hljs-literal\">true<\/span>\n        }\n      }\n    }\n  ]\n}<\/code>\n              <\/pre>\n<\/td>\n<\/td>\n<tr>\n<td><strong>401<\/strong><\/td>\n<td class=\"td-main\">Access token is missing or invalid<\/td>\n<\/td>\n<tr>\n<td><strong>403<\/strong><\/td>\n<td class=\"td-main\">The client performing the operation doesn\u2019t have appropriate permissions<\/td>\n<\/td>\n<tr>\n<td><strong>404<\/strong><\/td>\n<td class=\"td-main\">No role found with the given name<\/td>\n<\/td>\n<\/tbody>\n<\/table>\n<\/section><\/div>\n<\/details>\n<details class=\"oar-method oar-method--delete\">\n<summary class=\"oar-method__preview\">\n        <span class=\"oar-method-label\">DELETE<\/span><br \/>\n        <code class=\"oar-method__path\">\/api\/roles\/{roleName}\/resources\/{resourceId}<\/code><br \/>\n        <span class=\"7xtjw4dqwy5mz7w3j\">Revoke an existing role&#8217;s permission for the specified resource<\/span><br \/>\n      <\/summary>\n<div class=\"oar-method__body\">\n<p class=\"oar-method__description\">\n<section class=\"oar-method-section\">\n<h4>Parameters<\/h4>\n<table>\n<thead>\n<tr>\n<th>Name<\/th>\n<th>Type<\/th>\n<th>Description<\/th>\n<th>Required<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>roleName<\/td>\n<td>string (path)<\/td>\n<td><\/td>\n<td><strong>Yes<\/strong><\/td>\n<\/td>\n<tr>\n<td>resourceId<\/td>\n<td>string (path)<\/td>\n<td><\/td>\n<td><strong>Yes<\/strong><\/td>\n<\/td>\n<\/tbody>\n<\/table>\n<\/section>\n<section class=\"oar-method-section\">\n<h4>Responses<\/h4>\n<table>\n<thead>\n<tr>\n<th>Code<\/th>\n<th>Description<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><strong>204<\/strong><\/td>\n<td class=\"td-main\">Access revoked successfully; the updated role is returned<\/td>\n<\/td>\n<tr>\n<td><strong>401<\/strong><\/td>\n<td class=\"td-main\">Access token is missing or invalid<\/td>\n<\/td>\n<tr>\n<td><strong>403<\/strong><\/td>\n<td class=\"td-main\">The client performing the operation doesn\u2019t have appropriate permissions<\/td>\n<\/td>\n<tr>\n<td><strong>404<\/strong><\/td>\n<td class=\"td-main\">Role not found or resource not assigned to role<\/td>\n<\/td>\n<\/tbody>\n<\/table>\n<\/section><\/div>\n<\/details>\n<details class=\"oar-method oar-method--put\">\n<summary class=\"oar-method__preview\">\n        <span class=\"oar-method-label\">PUT<\/span><br \/>\n        <code class=\"oar-method__path\">\/api\/roles\/{roleName}\/resources\/{resourceId}<\/code><br \/>\n        <span class=\"7xtjw4dqwy5mz7w3j\">Update an existing role&#8217;s resource permissions<\/span><br \/>\n      <\/summary>\n<div class=\"oar-method__body\">\n<p class=\"oar-method__description\">The request body should contain an object mapping access types to either a Boolean (granting or revoking that access type) or an object specifying field-level permissions and\/or permission filters<\/p>\n<section class=\"oar-method-section\">\n<h4>Parameters<\/h4>\n<table>\n<thead>\n<tr>\n<th>Name<\/th>\n<th>Type<\/th>\n<th>Description<\/th>\n<th>Required<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>roleName<\/td>\n<td>string (path)<\/td>\n<td><\/td>\n<td><strong>Yes<\/strong><\/td>\n<\/td>\n<tr>\n<td>resourceId<\/td>\n<td>string (path)<\/td>\n<td><\/td>\n<td><strong>Yes<\/strong><\/td>\n<\/td>\n<\/tbody>\n<\/table>\n<\/section>\n<section class=\"oar-method-section\">\n<h4>Request body<\/h4>\n<ul>\n<li>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Content type<\/strong>: application\/json<\/p>\n<table>\n<thead>\n<tr>\n<th>Property<\/th>\n<th>Type<\/th>\n<\/thead>\n<tbody>\n<tr>\n<td>create<\/td>\n<td>boolean | object<\/td>\n<\/tr>\n<tr>\n<td>delete<\/td>\n<td>boolean | object<\/td>\n<\/tr>\n<tr>\n<td>deleteOwn<\/td>\n<td>boolean | object<\/td>\n<\/tr>\n<tr>\n<td>read<\/td>\n<td>boolean | object<\/td>\n<\/tr>\n<tr>\n<td>readOwn<\/td>\n<td>boolean | object<\/td>\n<\/tr>\n<tr>\n<td>update<\/td>\n<td>boolean | object<\/td>\n<\/tr>\n<tr>\n<td>updateOwn<\/td>\n<td>boolean | object<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<pre>\n              <code>{\n  <span class=\"hljs-attr\">\"create\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n  <span class=\"hljs-attr\">\"delete\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n  <span class=\"hljs-attr\">\"deleteOwn\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n  <span class=\"hljs-attr\">\"read\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n  <span class=\"hljs-attr\">\"readOwn\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n  <span class=\"hljs-attr\">\"update\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n  <span class=\"hljs-attr\">\"updateOwn\"<\/span>: <span class=\"hljs-literal\">true<\/span>\n}<\/code>\n            <\/pre>\n<\/li>\n<\/ul>\n<\/section>\n<section class=\"oar-method-section\">\n<h4>Responses<\/h4>\n<table>\n<thead>\n<tr>\n<th>Code<\/th>\n<th>Description<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><strong>200<\/strong><\/td>\n<td class=\"td-main\">Resource updated successfully; the updated role is returned<br \/>\n              <br class=\"7xtjw4dqwy5mz7w3j\"><br class=\"7xtjw4dqwy5mz7w3j\"><br \/>\n              <em>Example:<\/em><br \/>\n              <br class=\"7xtjw4dqwy5mz7w3j\"><\/p>\n<pre>\n                <code>{\n  <span class=\"hljs-attr\">\"results\"<\/span>: [\n    {\n      <span class=\"hljs-attr\">\"name\"<\/span>: <span class=\"hljs-string\">\"manager\"<\/span>,\n      <span class=\"hljs-attr\">\"extends\"<\/span>: <span class=\"hljs-string\">\"employee\"<\/span>,\n      <span class=\"hljs-attr\">\"resources\"<\/span>: {\n        <span class=\"hljs-attr\">\"collection:library_book\"<\/span>: {\n          <span class=\"hljs-attr\">\"create\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n          <span class=\"hljs-attr\">\"delete\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n          <span class=\"hljs-attr\">\"deleteOwn\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n          <span class=\"hljs-attr\">\"read\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n          <span class=\"hljs-attr\">\"readOwn\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n          <span class=\"hljs-attr\">\"update\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n          <span class=\"hljs-attr\">\"updateOwn\"<\/span>: <span class=\"hljs-literal\">true<\/span>\n        }\n      }\n    }\n  ]\n}<\/code>\n              <\/pre>\n<\/td>\n<\/td>\n<tr>\n<td><strong>401<\/strong><\/td>\n<td class=\"td-main\">Access token is missing or invalid<\/td>\n<\/td>\n<tr>\n<td><strong>403<\/strong><\/td>\n<td class=\"td-main\">The client performing the operation doesn\u2019t have appropriate permissions<\/td>\n<\/td>\n<tr>\n<td><strong>404<\/strong><\/td>\n<td class=\"td-main\">Role not found or resource not assigned to role<\/td>\n<\/td>\n<\/tbody>\n<\/table>\n<\/section><\/div>\n<\/details>\n<h3><a href=\"#using-models-directly\" id=\"using-models-directly\" name=\"using-models-directly\" class=\"anchor\">Anchor link<\/a> <a href=\"#using-models-directly\">Using models directly<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">It&#39;s possible to tap into the access control list programmatically, which is useful when creating <a href=\"#endpoints\">custom JavaScript endpoints<\/a> or <a href=\"#hooks\">collection hooks<\/a>. The ACL models allow you to create and modify clients and roles, as well as compute the permissions associated with a client and determine whether they can access a given resource.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">The <code>@dadi\/api<\/code> NPM module exports an <code>ACL<\/code> object with a series of public methods:<\/p>\n<ul>\n<li><a href=\"#access.get\">access.get()<\/a><\/li>\n<li><a href=\"#clientcreate\">client.create()<\/a><\/li>\n<li><a href=\"#clientdelete\">client.delete()<\/a><\/li>\n<li><a href=\"#clientget\">client.get()<\/a><\/li>\n<li><a href=\"#clientresourceadd\">client.resourceAdd()<\/a><\/li>\n<li><a href=\"#clientresourceremove\">client.resourceRemove()<\/a><\/li>\n<li><a href=\"#clientresourceupdate\">client.resourceUpdate()<\/a><\/li>\n<li><a href=\"#clientroleadd\">client.roleAdd()<\/a><\/li>\n<li><a href=\"#clientroleremove\">client.roleRemove()<\/a><\/li>\n<li><a href=\"#clientupdate\">client.update()<\/a><\/li>\n<li><a href=\"#rolecreate\">role.create()<\/a><\/li>\n<li><a href=\"#roledelete\">role.delete()<\/a><\/li>\n<li><a href=\"#roleget\">role.get()<\/a><\/li>\n<li><a href=\"#roleresourceadd\">role.resourceAdd()<\/a><\/li>\n<li><a href=\"#roleresourceremove\">role.resourceRemove()<\/a><\/li>\n<li><a href=\"#roleresourceupdate\">role.resourceUpdate()<\/a><\/li>\n<li><a href=\"#roleupdate\">role.update()<\/a><\/li>\n<\/ul>\n<h4><a href=\"#accessget\" id=\"accessget\" name=\"accessget\" class=\"anchor\">Anchor link<\/a> <a href=\"#accessget\">access.get<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">Returns the <a href=\"#resources\">access matrix<\/a> representing the permissions of a given client to access a resource.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">It expects the ID of the client as well as their access type, which means you may need to obtain this information with a separate query first. The reason for this is that the client ID + access type pair are encoded in the bearer token&#39;s JWT and are easily available via the <code>req.dadiApiClient<\/code> property.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Receives<\/em><\/strong>:<\/p>\n<ul>\n<li><code>client.clientId<\/code> (type: <code>String<\/code>): ID of the client<\/li>\n<li><code>client.accessType<\/code> (type: <code>String<\/code>): Access type of the client<\/li>\n<li><code>resource<\/code> (type: <code>String<\/code>): ID of the resource<\/li>\n<li><code>resolveOwnTypes<\/code> (type: <code>Boolean<\/code>, default: <code>true<\/code>): Whether to translate <code>*Own<\/code> types (e.g. <code>readOwn<\/code>) into a <code>read<\/code> property with a filter<\/li>\n<\/ul>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Returns:<\/em><\/strong><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><code>Promise&lt;Object&gt;<\/code>: an object representing an access matrix.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Example:<\/em><\/strong><\/p>\n<pre><code class=\"lang-js\">const ACL = require('@dadi\/api').ACL\nACL.<span class=\"hljs-keyword\">access<\/span>.get({\n  clientId: <span class=\"hljs-symbol\">'restfulJohn<\/span>',\n  accessType: <span class=\"hljs-symbol\">'user<\/span>'\n}, <span class=\"hljs-symbol\">'collection<\/span>:v1_foobar').<span class=\"hljs-keyword\">then<\/span>(<span class=\"hljs-keyword\">access<\/span> =&gt; {\n  <span class=\"hljs-keyword\">if<\/span> (!<span class=\"hljs-keyword\">access<\/span>.read) {\n    console.log(<span class=\"hljs-symbol\">'Client<\/span> does <span class=\"hljs-keyword\">not<\/span> have `read` <span class=\"hljs-keyword\">access<\/span>!')\n  }\n})\n<\/code><\/pre>\n<h4><a href=\"#clientcreate\" id=\"clientcreate\" name=\"clientcreate\" class=\"anchor\">Anchor link<\/a> <a href=\"#clientcreate\">client.create<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">Creates a new client. <\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">Note that all clients created using the ACL model have an access type of <code>user<\/code>. To create a client with an access type of <code>admin<\/code>, you must do so <a href=\"#adding-clients\">manually<\/a>.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Receives<\/em><\/strong> <em>(named parameters):<\/em><\/p>\n<ul>\n<li><code>clientId<\/code> (type: <code>String<\/code>): ID of the client to create<\/li>\n<li><code>secret<\/code> (type: <code>String<\/code>): The client secret<\/li>\n<\/ul>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Returns:<\/em><\/strong><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><code>Promise&lt;Object&gt;<\/code>: an object representing the newly-created client.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Example:<\/em><\/strong><\/p>\n<pre><code class=\"lang-js\">const ACL = require(<span class=\"hljs-string\">'@dadi\/api'<\/span>)<span class=\"hljs-selector-class\">.ACL<\/span>\nACL<span class=\"hljs-selector-class\">.client<\/span><span class=\"hljs-selector-class\">.create<\/span>({\n  clientId: <span class=\"hljs-string\">'restfulJohn'<\/span>,\n  secret: <span class=\"hljs-string\">'superSecret!'<\/span>\n})\n<\/code><\/pre>\n<h4><a href=\"#clientdelete\" id=\"clientdelete\" name=\"clientdelete\" class=\"anchor\">Anchor link<\/a> <a href=\"#clientdelete\">client.delete<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">Deletes a client.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Receives<\/em><\/strong>:<\/p>\n<ul>\n<li><code>clientId<\/code> (type: <code>String<\/code>): ID of the client to delete<\/li>\n<\/ul>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Returns:<\/em><\/strong><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><code>Promise<\/code> with:<\/p>\n<ul>\n<li><code>{deletedCount, totalCount}<\/code> (<code>Object<\/code>): Object indicating the number of clients that were deleted and the number of clients remaining after the operation<\/li>\n<\/ul>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Example:<\/em><\/strong><\/p>\n<pre><code class=\"lang-js\">const ACL = require(<span class=\"hljs-string\">'@dadi\/api'<\/span>)<span class=\"hljs-selector-class\">.ACL<\/span>\nACL<span class=\"hljs-selector-class\">.client<\/span><span class=\"hljs-selector-class\">.delete<\/span>(<span class=\"hljs-string\">'restfulJohn'<\/span>)\n<\/code><\/pre>\n<h4><a href=\"#clientget\" id=\"clientget\" name=\"clientget\" class=\"anchor\">Anchor link<\/a> <a href=\"#clientget\">client.get<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">Returns a client by ID. <\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">If <code>secret<\/code> is passed as a second argument, only a client that matches both the ID and the secret supplied will be retrieved.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Receives<\/em><\/strong>:<\/p>\n<ul>\n<li><code>clientId<\/code> (type: <code>String<\/code>): ID of the client<\/li>\n<li><code>secret<\/code> (type: <code>String<\/code>, optional): The client secret<\/li>\n<\/ul>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Returns:<\/em><\/strong><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><code>Promise&lt;Object&gt;<\/code>: an object with a <code>results<\/code> property containing an array of matching clients.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Example:<\/em><\/strong><\/p>\n<pre><code class=\"lang-js\">const ACL = <span class=\"hljs-built_in\">require<\/span>(<span class=\"hljs-string\">'@dadi\/api'<\/span>).ACL\nACL.client.get({\n  clientId: <span class=\"hljs-string\">'restfulJohn'<\/span>,\n  secret: <span class=\"hljs-string\">'superSecret!'<\/span>\n}).<span class=\"hljs-keyword\">then<\/span>(<span class=\"hljs-function\"><span class=\"hljs-params\">({results})<\/span> =&gt;<\/span> {\n  <span class=\"hljs-keyword\">if<\/span> (results.length === <span class=\"hljs-number\">0<\/span>) {\n    <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-built_in\">console<\/span>.log(<span class=\"hljs-string\">'Wrong credentials!'<\/span>)\n  }\n  <span class=\"hljs-built_in\">console<\/span>.log(results[<span class=\"hljs-number\">0<\/span>])\n})\n<\/code><\/pre>\n<h4><a href=\"#clientresourceadd\" id=\"clientresourceadd\" name=\"clientresourceadd\" class=\"anchor\">Anchor link<\/a> <a href=\"#clientresourceadd\">client.resourceAdd<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">Gives a client permission to access a given resource.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Receives<\/em><\/strong>:<\/p>\n<ul>\n<li><code>clientId<\/code> (type: <code>String<\/code>): ID of the client<\/li>\n<li><code>resource<\/code> (type: <code>String<\/code>): ID of the resource<\/li>\n<li><code>access<\/code> (type: <code>Object<\/code>): Access matrix<\/li>\n<\/ul>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Returns:<\/em><\/strong><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><code>Promise&lt;Object&gt;<\/code>: the updated client.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Example:<\/em><\/strong><\/p>\n<pre><code class=\"lang-js\">const ACL = <span class=\"hljs-built_in\">require<\/span>(<span class=\"hljs-string\">'@dadi\/api'<\/span>).ACL\nACL.client.resourceAdd(\n  <span class=\"hljs-string\">'restfulJohn'<\/span>,\n  <span class=\"hljs-string\">'collection:v1_things'<\/span>,\n  {<span class=\"hljs-built_in\">create<\/span>: <span class=\"hljs-literal\">true<\/span>, <span class=\"hljs-built_in\">read<\/span>: <span class=\"hljs-literal\">true<\/span>}\n)\n<\/code><\/pre>\n<h4><a href=\"#clientresourceremove\" id=\"clientresourceremove\" name=\"clientresourceremove\" class=\"anchor\">Anchor link<\/a> <a href=\"#clientresourceremove\">client.resourceRemove<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">Removes a client&#39;s permission to access a given resource.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Receives<\/em><\/strong>:<\/p>\n<ul>\n<li><code>clientId<\/code> (type: <code>String<\/code>): ID of the client<\/li>\n<li><code>resource<\/code> (type: <code>String<\/code>): ID of the resource<\/li>\n<\/ul>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Returns:<\/em><\/strong><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><code>Promise&lt;Object&gt;<\/code>: the updated client.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Example:<\/em><\/strong><\/p>\n<pre><code class=\"lang-js\">const ACL = require(<span class=\"hljs-string\">'@dadi\/api'<\/span>)<span class=\"hljs-selector-class\">.ACL<\/span>\nACL<span class=\"hljs-selector-class\">.client<\/span><span class=\"hljs-selector-class\">.resourceRemove<\/span>(\n  <span class=\"hljs-string\">'restfulJohn'<\/span>,\n  <span class=\"hljs-string\">'collection:v1_things'<\/span>\n)\n<\/code><\/pre>\n<h4><a href=\"#clientresourceupdate\" id=\"clientresourceupdate\" name=\"clientresourceupdate\" class=\"anchor\">Anchor link<\/a> <a href=\"#clientresourceupdate\">client.resourceUpdate<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">Updates a client&#39;s permission to access a given resource.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Receives<\/em><\/strong>:<\/p>\n<ul>\n<li><code>clientId<\/code> (type: <code>String<\/code>): ID of the client<\/li>\n<li><code>resource<\/code> (type: <code>String<\/code>): ID of the resource<\/li>\n<li><code>access<\/code> (type: <code>Object<\/code>): New access matrix<\/li>\n<\/ul>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Returns:<\/em><\/strong><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><code>Promise&lt;Object&gt;<\/code>: the updated client.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Example:<\/em><\/strong><\/p>\n<pre><code class=\"lang-js\">const ACL = require(<span class=\"hljs-string\">'@dadi\/api'<\/span>)<span class=\"hljs-selector-class\">.ACL<\/span>\nACL<span class=\"hljs-selector-class\">.client<\/span><span class=\"hljs-selector-class\">.resourceAdd<\/span>(\n  <span class=\"hljs-string\">'restfulJohn'<\/span>,\n  <span class=\"hljs-string\">'collection:v1_things'<\/span>,\n  {create: false, update: true}\n)\n<\/code><\/pre>\n<h4><a href=\"#clientroleadd\" id=\"clientroleadd\" name=\"clientroleadd\" class=\"anchor\">Anchor link<\/a> <a href=\"#clientroleadd\">client.roleAdd<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">Assigns roles to a client.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Receives<\/em><\/strong>:<\/p>\n<ul>\n<li><code>clientId<\/code> (type: <code>String<\/code>): ID of the client<\/li>\n<li><code>roles<\/code> (type: <code>Array&lt;String&gt;<\/code>): Names of roles to assign<\/li>\n<\/ul>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Returns:<\/em><\/strong><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><code>Promise&lt;Object&gt;<\/code>: the updated client.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Example:<\/em><\/strong><\/p>\n<pre><code class=\"lang-js\">const ACL = require(<span class=\"hljs-string\">'@dadi\/api'<\/span>)<span class=\"hljs-selector-class\">.ACL<\/span>\nACL<span class=\"hljs-selector-class\">.client<\/span><span class=\"hljs-selector-class\">.roleAdd<\/span>(\n  <span class=\"hljs-string\">'restfulJohn'<\/span>,\n  [<span class=\"hljs-string\">'operator'<\/span>, <span class=\"hljs-string\">'administrator'<\/span>]\n)\n<\/code><\/pre>\n<h4><a href=\"#clientroleremove\" id=\"clientroleremove\" name=\"clientroleremove\" class=\"anchor\">Anchor link<\/a> <a href=\"#clientroleremove\">client.roleRemove<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">Unassigns roles from a client.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Receives<\/em><\/strong>:<\/p>\n<ul>\n<li><code>clientId<\/code> (type: <code>String<\/code>): ID of the client<\/li>\n<li><code>roles<\/code> (type: <code>Array&lt;String&gt;<\/code>): Names of roles to unassign<\/li>\n<\/ul>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Returns:<\/em><\/strong><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><code>Promise&lt;Object&gt;<\/code>: the updated client.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Example:<\/em><\/strong><\/p>\n<pre><code class=\"lang-js\">const ACL = require(<span class=\"hljs-string\">'@dadi\/api'<\/span>)<span class=\"hljs-selector-class\">.ACL<\/span>\nACL<span class=\"hljs-selector-class\">.client<\/span><span class=\"hljs-selector-class\">.roleRemove<\/span>(\n  <span class=\"hljs-string\">'restfulJohn'<\/span>,\n  [<span class=\"hljs-string\">'operator'<\/span>, <span class=\"hljs-string\">'administrator'<\/span>]\n)\n<\/code><\/pre>\n<h4><a href=\"#clientupdate\" id=\"clientupdate\" name=\"clientupdate\" class=\"anchor\">Anchor link<\/a> <a href=\"#clientupdate\">client.update<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">Updates a client.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Receives<\/em><\/strong>:<\/p>\n<ul>\n<li><code>clientId<\/code> (type: <code>String<\/code>): ID of the client to update<\/li>\n<li><code>update<\/code> (type: <code>Object<\/code>): The update object<\/li>\n<\/ul>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Returns:<\/em><\/strong><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><code>Promise&lt;Object&gt;<\/code>: an object representing the updated client.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Example:<\/em><\/strong><\/p>\n<pre><code class=\"lang-js\">const ACL = require(<span class=\"hljs-string\">'@dadi\/api'<\/span>)<span class=\"hljs-selector-class\">.ACL<\/span>\nACL<span class=\"hljs-selector-class\">.client<\/span><span class=\"hljs-selector-class\">.update<\/span>(\n  <span class=\"hljs-string\">'restfulJohn'<\/span>,\n  {secret: <span class=\"hljs-string\">'newSuperSecret!'<\/span>}\n})\n<\/code><\/pre>\n<h4><a href=\"#rolecreate\" id=\"rolecreate\" name=\"rolecreate\" class=\"anchor\">Anchor link<\/a> <a href=\"#rolecreate\">role.create<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">Creates a new role. <\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Receives<\/em><\/strong> <em>(named parameters):<\/em><\/p>\n<ul>\n<li><code>name<\/code> (type: <code>String<\/code>): Name of the role<\/li>\n<li><code>extends<\/code> (type: <code>String<\/code>, optional): The name of a role to be extended<\/li>\n<\/ul>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Returns:<\/em><\/strong><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><code>Promise&lt;Object&gt;<\/code>: an object representing the newly-created role.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Example:<\/em><\/strong><\/p>\n<pre><code class=\"lang-js\">const ACL = require(<span class=\"hljs-string\">'@dadi\/api'<\/span>)<span class=\"hljs-selector-class\">.ACL<\/span>\nACL<span class=\"hljs-selector-class\">.role<\/span><span class=\"hljs-selector-class\">.create<\/span>({\n  name: <span class=\"hljs-string\">'administrator'<\/span>,\n  extends: <span class=\"hljs-string\">'operator'<\/span>\n})\n<\/code><\/pre>\n<h4><a href=\"#roledelete\" id=\"roledelete\" name=\"roledelete\" class=\"anchor\">Anchor link<\/a> <a href=\"#roledelete\">role.delete<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">Deletes a role. If the role is extended by other roles, their <code>extends<\/code> property will be set to <code>null<\/code>.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Receives<\/em><\/strong>:<\/p>\n<ul>\n<li><code>name<\/code> (type: <code>String<\/code>): Name of the role to be deleted<\/li>\n<\/ul>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Returns:<\/em><\/strong><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><code>Promise<\/code> with:<\/p>\n<ul>\n<li><code>{deletedCount, totalCount}<\/code> (<code>Object<\/code>): Object indicating the number of roles that were deleted and the number of roles remaining after the operation<\/li>\n<\/ul>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Example:<\/em><\/strong><\/p>\n<pre><code class=\"lang-js\">const ACL = require(<span class=\"hljs-string\">'@dadi\/api'<\/span>)<span class=\"hljs-selector-class\">.ACL<\/span>\nACL<span class=\"hljs-selector-class\">.role<\/span><span class=\"hljs-selector-class\">.delete<\/span>(<span class=\"hljs-string\">'operator'<\/span>)\n<\/code><\/pre>\n<h4><a href=\"#roleget\" id=\"roleget\" name=\"roleget\" class=\"anchor\">Anchor link<\/a> <a href=\"#roleget\">role.get<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">Returns roles by name.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Receives<\/em><\/strong>:<\/p>\n<ul>\n<li><code>names<\/code> (type: <code>Array&lt;String&gt;<\/code>): Names of the roles to retrieve<\/li>\n<\/ul>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Returns:<\/em><\/strong><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><code>Promise&lt;Object&gt;<\/code>: an object with a <code>results<\/code> property containing an array of matching roles.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Example:<\/em><\/strong><\/p>\n<pre><code class=\"lang-js\">const ACL = require(<span class=\"hljs-string\">'@dadi\/api'<\/span>)<span class=\"hljs-selector-class\">.ACL<\/span>\nACL<span class=\"hljs-selector-class\">.role<\/span><span class=\"hljs-selector-class\">.get<\/span>([<span class=\"hljs-string\">'operator'<\/span>, <span class=\"hljs-string\">'administrator'<\/span>])\n<\/code><\/pre>\n<h4><a href=\"#roleresourceadd\" id=\"roleresourceadd\" name=\"roleresourceadd\" class=\"anchor\">Anchor link<\/a> <a href=\"#roleresourceadd\">role.resourceAdd<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">Gives a role permission to access a given resource.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Receives<\/em><\/strong>:<\/p>\n<ul>\n<li><code>role<\/code> (type: <code>String<\/code>): Name of the role<\/li>\n<li><code>resource<\/code> (type: <code>String<\/code>): ID of the resource<\/li>\n<li><code>access<\/code> (type: <code>Object<\/code>): Access matrix<\/li>\n<\/ul>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Returns:<\/em><\/strong><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><code>Promise&lt;Object&gt;<\/code>: the updated role.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Example:<\/em><\/strong><\/p>\n<pre><code class=\"lang-js\">const ACL = <span class=\"hljs-built_in\">require<\/span>(<span class=\"hljs-string\">'@dadi\/api'<\/span>).ACL\nACL.role.resourceAdd(\n  <span class=\"hljs-string\">'operator'<\/span>,\n  <span class=\"hljs-string\">'collection:v1_things'<\/span>,\n  {<span class=\"hljs-built_in\">create<\/span>: <span class=\"hljs-literal\">true<\/span>, <span class=\"hljs-built_in\">read<\/span>: <span class=\"hljs-literal\">true<\/span>}\n)\n<\/code><\/pre>\n<h4><a href=\"#roleresourceremove\" id=\"roleresourceremove\" name=\"roleresourceremove\" class=\"anchor\">Anchor link<\/a> <a href=\"#roleresourceremove\">role.resourceRemove<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">Removes a role&#39;s permission to access a given resource.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Receives<\/em><\/strong>:<\/p>\n<ul>\n<li><code>role<\/code> (type: <code>String<\/code>): Name of the role<\/li>\n<li><code>resource<\/code> (type: <code>String<\/code>): ID of the resource<\/li>\n<\/ul>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Returns:<\/em><\/strong><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><code>Promise&lt;Object&gt;<\/code>: the updated role.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Example:<\/em><\/strong><\/p>\n<pre><code class=\"lang-js\">const ACL = require(<span class=\"hljs-string\">'@dadi\/api'<\/span>)<span class=\"hljs-selector-class\">.ACL<\/span>\nACL<span class=\"hljs-selector-class\">.role<\/span><span class=\"hljs-selector-class\">.resourceRemove<\/span>(\n  <span class=\"hljs-string\">'operator'<\/span>,\n  <span class=\"hljs-string\">'collection:v1_things'<\/span>\n)\n<\/code><\/pre>\n<h4><a href=\"#roleresourceupdate\" id=\"roleresourceupdate\" name=\"roleresourceupdate\" class=\"anchor\">Anchor link<\/a> <a href=\"#roleresourceupdate\">role.resourceUpdate<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">Updates a role&#39;s permission to access a given resource.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Receives<\/em><\/strong>:<\/p>\n<ul>\n<li><code>role<\/code> (type: <code>String<\/code>): Name of the role<\/li>\n<li><code>resource<\/code> (type: <code>String<\/code>): ID of the resource<\/li>\n<li><code>access<\/code> (type: <code>Object<\/code>): New access matrix<\/li>\n<\/ul>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Returns:<\/em><\/strong><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><code>Promise&lt;Object&gt;<\/code>: the updated role.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Example:<\/em><\/strong><\/p>\n<pre><code class=\"lang-js\">const ACL = require(<span class=\"hljs-string\">'@dadi\/api'<\/span>)<span class=\"hljs-selector-class\">.ACL<\/span>\nACL<span class=\"hljs-selector-class\">.role<\/span><span class=\"hljs-selector-class\">.resourceAdd<\/span>(\n  <span class=\"hljs-string\">'operator'<\/span>,\n  <span class=\"hljs-string\">'collection:v1_things'<\/span>,\n  {create: false, update: true}\n)\n<\/code><\/pre>\n<h4><a href=\"#roleupdate\" id=\"roleupdate\" name=\"roleupdate\" class=\"anchor\">Anchor link<\/a> <a href=\"#roleupdate\">role.update<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">Updates a role.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Receives<\/em><\/strong>:<\/p>\n<ul>\n<li><code>role<\/code> (type: <code>String<\/code>): Name of the role<\/li>\n<li><code>update<\/code> (type: <code>Object<\/code>): The update object<\/li>\n<\/ul>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Returns:<\/em><\/strong><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><code>Promise&lt;Object&gt;<\/code>: an object representing the updated role.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Example:<\/em><\/strong><\/p>\n<pre><code class=\"lang-js\">const ACL = require(<span class=\"hljs-string\">'@dadi\/api'<\/span>)<span class=\"hljs-selector-class\">.ACL<\/span>\nACL<span class=\"hljs-selector-class\">.role<\/span><span class=\"hljs-selector-class\">.update<\/span>(\n  <span class=\"hljs-string\">'superAdministrator'<\/span>,\n  {extends: <span class=\"hljs-string\">'administrator'<\/span>}\n})\n<\/code><\/pre>\n<h2><a href=\"#collections\" id=\"collections\" name=\"collections\" class=\"anchor\">Anchor link<\/a> <a href=\"#collections\">Collections<\/a><\/h2>\n<p class=\"7xtjw4dqwy5mz7w3j\">A <em>Collection<\/em> represents data within your API. Collections can be thought of as the data models for your application and define how API connects to the underlying data store to store and retrieve data.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">API can handle the creation of new collections or tables in the configured data store simply by creating collection specification files. To connect collections to existing data, simply name the file using the same name as the existing collection\/table.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">All that is required to connect to your data is a collection specification file, and once that is created API provides data access over a REST endpoint and programmatically via the API&#39;s <code>Model<\/code> module.<\/p>\n<h3><a href=\"#collections-directory\" id=\"collections-directory\" name=\"collections-directory\" class=\"anchor\">Anchor link<\/a> <a href=\"#collections-directory\">Collections directory<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">Collection specifications are simply JSON files stored in your application&#39;s <code>collections<\/code> directory. The location of this directory is configurable using the configuration property <code>paths.collections<\/code> but defaults to <code>workspace\/collections<\/code>. The structure of this directory is as follows:<\/p>\n<pre><code class=\"lang-console\"><span class=\"hljs-keyword\">my<\/span>-api\/\n  workspace\/\n    collections\/                    \n      <span class=\"hljs-number\">1.0<\/span>\/                          <span class=\"hljs-comment\"># API version<\/span>\n        library\/                    <span class=\"hljs-comment\"># database<\/span>\n          collection.books.json     <span class=\"hljs-comment\"># collection specification file<\/span>\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>API Version<\/strong><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">Specific versions of your API are represented as sub-directories of the collections directory. Versioning of collections and endpoints acts as a formal contract between the API and its consumers.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">Imagine a situation where a breaking change needs to be introduced \u2014 e.g. adding or removing a collection field, or changing the output format of an endpoint. A good way to handle this would be to introduce the new structure as version 2.0 and retain the old one as version 1.0, warning consumers of its deprecation and potentially giving them a window of time before the functionality is removed.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">All requests to collection and custom endpoints must include the version in the URL, mimicking the hierarchy defined in the folder structure.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Database<\/strong><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">Collection documents may be stored in separate databases in the underlying data store, represented by the name of the &quot;database&quot; directory.<\/p>\n<blockquote class=\"\">\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Note<\/strong> This feature is disabled by default. To enable separate databases in your API the configuration setting <code>database.enableCollectionDatabases<\/code> must be <code>true<\/code>. See <a href=\"#collection-specific-databases\">Collection-specific Databases<\/a> for more information.<\/p>\n<\/blockquote>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Collection specification file<\/strong><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">A collection specification file is a JSON file containing at least one field specification and a configuration block.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">The naming convention for collection specifications is <code>collection.&lt;collection name&gt;.json<\/code> where <code>&lt;collection name&gt;<\/code> is used as the name of the collection\/table in the underlying data store.<\/p>\n<blockquote class=\"advice\">\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Use the plural form<\/strong><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">We recommend you use the plural form when naming collections in order to keep consistency across your API. Using the singular form means a GET request for a list of results can easily be confused with a request for a single entity.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">For example, a collection named <code>book (collection.book.json)<\/code> will accept GET requests at the following endpoints:<\/p>\n<pre><code><span class=\"hljs-symbol\">https:<\/span><span class=\"hljs-comment\">\/\/api.somedomain.tech\/1.0\/library\/book<\/span>\n<span class=\"hljs-symbol\">https:<\/span><span class=\"hljs-comment\">\/\/api.somedomain.tech\/1.0\/library\/book\/560a44b33a4d7de29f168ce4<\/span>\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\">It&apos;s not obvious whether or not the first example is going to return all books, as intended. Using the plural form makes it clear what the endpoint&apos;s intended behaviour is:<\/p>\n<pre><code><span class=\"hljs-symbol\">https:<\/span><span class=\"hljs-comment\">\/\/api.somedomain.tech\/1.0\/library\/books<\/span>\n<span class=\"hljs-symbol\">https:<\/span><span class=\"hljs-comment\">\/\/api.somedomain.tech\/1.0\/library\/books\/560a44b33a4d7de29f168ce4<\/span>\n<\/code><\/pre>\n<\/blockquote>\n<h3><a href=\"#the-collection-endpoint\" id=\"the-collection-endpoint\" name=\"the-collection-endpoint\" class=\"anchor\">Anchor link<\/a> <a href=\"#the-collection-endpoint\">The Collection Endpoint<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">API automatically generates a REST endpoint for each collection specification loaded from the collections directory. The format of the REST endpoint follows this convention <code>\/{version}\/{database}\/{collection name}<\/code> and matches the structure of the collections directory.<\/p>\n<pre><code class=\"lang-console\"><span class=\"hljs-keyword\">my<\/span>-api\/\n  workspace\/\n    collections\/                    \n      <span class=\"hljs-number\">1.0<\/span>\/                          <span class=\"hljs-comment\"># API version<\/span>\n        library\/                    <span class=\"hljs-comment\"># database<\/span>\n          collection.books.json     <span class=\"hljs-comment\"># collection specification file<\/span>\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\">With the above directory structure API will generate this REST endpoint: https:\/\/api.somedomain.tech\/1.0\/library\/books.<\/p>\n<h3><a href=\"#the-json-file\" id=\"the-json-file\" name=\"the-json-file\" class=\"anchor\">Anchor link<\/a> <a href=\"#the-json-file\">The JSON File<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">Collection specification files can be created and edited in any text editor, then added to the API&#39;s <code>collections<\/code> directory. API will load all valid collections when it boots.<\/p>\n<h4><a href=\"#minimum-requirements\" id=\"minimum-requirements\" name=\"minimum-requirements\" class=\"anchor\">Anchor link<\/a> <a href=\"#minimum-requirements\">Minimum Requirements<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">The JSON file must contain a <code>fields<\/code> property and, optionally, a <code>settings<\/code> property.<\/p>\n<ul>\n<li><code>fields<\/code>: must contain at least one field specification. See <a href=\"#collection-fields\">Collection Fields<\/a> for the format of fields.<\/li>\n<li><code>settings<\/code>: API uses sensible defaults for collection configuration, but these can be overridden using properties in the <code>settings<\/code> block. See <a href=\"#collection-settings\">Collection Settings<\/a> for details.<\/li>\n<\/ul>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>A skeleton collection specification<\/strong><\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"fields\"<\/span>: {\n    <span class=\"hljs-attr\">\"field1\"<\/span>: {\n    }\n  },\n  <span class=\"hljs-attr\">\"settings\"<\/span>: {\n  }\n}\n<\/code><\/pre>\n<h3><a href=\"#collection-fields\" id=\"collection-fields\" name=\"collection-fields\" class=\"anchor\">Anchor link<\/a> <a href=\"#collection-fields\">Collection Fields<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">Each field in a collection is defined using the following format. The only required property is <code>type<\/code> which tells API what data types the field can contain.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>A basic field specification<\/strong><\/p>\n<pre><code class=\"lang-json\"><span class=\"hljs-string\">\"fieldName\"<\/span>: {\n  <span class=\"hljs-string\">\"type\"<\/span>: <span class=\"hljs-string\">\"String\"<\/span>\n}\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>A complete field specification<\/strong><\/p>\n<pre><code class=\"lang-json\"><span class=\"hljs-string\">\"fieldName\"<\/span>: {\n  <span class=\"hljs-string\">\"type\"<\/span>: <span class=\"hljs-string\">\"String\"<\/span>,\n  <span class=\"hljs-string\">\"required\"<\/span>: true,\n  <span class=\"hljs-string\">\"label\"<\/span>: <span class=\"hljs-string\">\"Title\"<\/span>,\n  <span class=\"hljs-string\">\"comments\"<\/span>: <span class=\"hljs-string\">\"The title of the entry\"<\/span>,\n  <span class=\"hljs-string\">\"example\"<\/span>: <span class=\"hljs-string\">\"War and Peace\"<\/span>,\n  <span class=\"hljs-string\">\"message\"<\/span>: <span class=\"hljs-string\">\"must not be blank\"<\/span>,\n  <span class=\"hljs-string\">\"default\"<\/span>: <span class=\"hljs-string\">\"Untitled\"<\/span>\n  <span class=\"hljs-string\">\"matchType\"<\/span>: <span class=\"hljs-string\">\"exact\"<\/span>,\n  <span class=\"hljs-string\">\"validation\"<\/span>: {\n    <span class=\"hljs-string\">\"minLength\"<\/span>: <span class=\"hljs-number\">4<\/span>,\n    <span class=\"hljs-string\">\"maxLength\"<\/span>: <span class=\"hljs-number\">20<\/span>,\n    <span class=\"hljs-string\">\"regex\"<\/span>: {\n      <span class=\"hljs-string\">\"pattern\"<\/span>: <span class=\"hljs-string\">\"\/[A-Za-z0-9]*\/\"<\/span>\n    }\n  }\n}\n<\/code><\/pre>\n<table>\n<thead>\n<tr>\n<th style=\"text-align:left\">Property<\/th>\n<th style=\"text-align:left\">Description<\/th>\n<th style=\"text-align:left\">Default<\/th>\n<th style=\"text-align:left\">Example<\/th>\n<th style=\"text-align:left\">Required?<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td style=\"text-align:left\">fieldName<\/td>\n<td style=\"text-align:left\">The name of the field<\/td>\n<td style=\"text-align:left\"><\/td>\n<td style=\"text-align:left\"><code>&quot;title&quot;<\/code><\/td>\n<td style=\"text-align:left\">Yes<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\">type<\/td>\n<td style=\"text-align:left\">The type of the field. Possible values <code>&quot;String&quot;<\/code>, <code>&quot;Number&quot;<\/code>, <code>&quot;DateTime&quot;<\/code>, <code>&quot;Boolean&quot;<\/code>, <code>&quot;Mixed&quot;<\/code>, <code>&quot;Object&quot;<\/code>, <code>&quot;Reference&quot;<\/code><\/td>\n<td style=\"text-align:left\">N\/A<\/td>\n<td style=\"text-align:left\"><code>&quot;String&quot;<\/code><\/td>\n<td style=\"text-align:left\">Yes<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\">label<\/td>\n<td style=\"text-align:left\">The label for the field<\/td>\n<td style=\"text-align:left\"><code>&quot;&quot;<\/code><\/td>\n<td style=\"text-align:left\"><code>&quot;Title&quot;<\/code><\/td>\n<td style=\"text-align:left\">No<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\">comments<\/td>\n<td style=\"text-align:left\">The description of the field<\/td>\n<td style=\"text-align:left\"><code>&quot;&quot;<\/code><\/td>\n<td style=\"text-align:left\"><code>&quot;The article title&quot;<\/code><\/td>\n<td style=\"text-align:left\">No<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\">example<\/td>\n<td style=\"text-align:left\">An example value for the field<\/td>\n<td style=\"text-align:left\"><code>&quot;&quot;<\/code><\/td>\n<td style=\"text-align:left\"><code>&quot;War and Peace&quot;<\/code><\/td>\n<td style=\"text-align:left\">No<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\">validation<\/td>\n<td style=\"text-align:left\">Validation rules, including minimum and maximum length and regular expression patterns.<\/td>\n<td style=\"text-align:left\"><code>{}<\/code><\/td>\n<td style=\"text-align:left\"><\/td>\n<td style=\"text-align:left\">No<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\">validation.minLength<\/td>\n<td style=\"text-align:left\">The minimum length for the field.<\/td>\n<td style=\"text-align:left\">unlimited<\/td>\n<td style=\"text-align:left\"><code>4<\/code><\/td>\n<td style=\"text-align:left\">No<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\">validation.maxLength<\/td>\n<td style=\"text-align:left\">The maximum length for the field.<\/td>\n<td style=\"text-align:left\">unlimited<\/td>\n<td style=\"text-align:left\"><code>20<\/code><\/td>\n<td style=\"text-align:left\">No<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\">validation.regex<\/td>\n<td style=\"text-align:left\">A regular expression the field&#39;s value must match<\/td>\n<td style=\"text-align:left\"><\/td>\n<td style=\"text-align:left\"><code>{ &quot;pattern&quot;: \/[A-Z]*\/ }<\/code><\/td>\n<td style=\"text-align:left\">No<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\">required<\/td>\n<td style=\"text-align:left\">If true, a value must be entered for the field.<\/td>\n<td style=\"text-align:left\"><code>false<\/code><\/td>\n<td style=\"text-align:left\"><code>true<\/code><\/td>\n<td style=\"text-align:left\">No<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\">message<\/td>\n<td style=\"text-align:left\">The message to return if field validation fails.<\/td>\n<td style=\"text-align:left\"><code>&quot;is invalid&quot;<\/code><\/td>\n<td style=\"text-align:left\"><code>&quot;must contain uppercase letters only&quot;<\/code><\/td>\n<td style=\"text-align:left\">No<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\">default<\/td>\n<td style=\"text-align:left\">An optional value to use as a default if no value is supplied for this field<\/td>\n<td style=\"text-align:left\"><\/td>\n<td style=\"text-align:left\"><code>&quot;0&quot;<\/code><\/td>\n<td style=\"text-align:left\">No<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\">matchType<\/td>\n<td style=\"text-align:left\">Specify the type of query that is performed when using this field. If &quot;exact&quot; then API will attempt to match the query value exactly, otherwise it will performa a case-insensitive query.<\/td>\n<td style=\"text-align:left\"><\/td>\n<td style=\"text-align:left\"><code>&quot;exact&quot;<\/code><\/td>\n<td style=\"text-align:left\">No<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\">format<\/td>\n<td style=\"text-align:left\">Used by some fields (e.g. <code>DateTime<\/code>) to specify the expected format for input\/output<\/td>\n<td style=\"text-align:left\"><code>null<\/code><\/td>\n<td style=\"text-align:left\"><code>&quot;YYYY-MM-DD&quot;<\/code><\/td>\n<td style=\"text-align:left\">No<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3><a href=\"#field-types\" id=\"field-types\" name=\"field-types\" class=\"anchor\">Anchor link<\/a> <a href=\"#field-types\">Field Types<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">Every field in a collection must be one of the following types. All documents sent to API are validated against a collection&#39;s field type to ensure that data will be stored in the format intended. See the section on <a href=\"#validation\">Validation<\/a> for more details.<\/p>\n<table>\n<thead>\n<tr>\n<th style=\"text-align:left\">Type<\/th>\n<th style=\"text-align:left\">Description<\/th>\n<th style=\"text-align:left\">Example<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td style=\"text-align:left\">String<\/td>\n<td style=\"text-align:left\">The most basic field type, used for text data. Will also accept arrays of Strings.<\/td>\n<td style=\"text-align:left\"><code>&quot;The quick brown fox&quot;<\/code>,  <code>[&quot;The&quot;, &quot;quick&quot;, &quot;brown&quot;, &quot;fox&quot;]<\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\">Number<\/td>\n<td style=\"text-align:left\">Accepts numeric data types including whole integers and floats<\/td>\n<td style=\"text-align:left\"><code>5<\/code>, <code>5.01<\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\">DateTime<\/td>\n<td style=\"text-align:left\">Stores dates\/times. Accepts numeric values (Unix timestamp), strings in the ISO 8601 format or in any format supported by <a href=\"https:\/\/momentjs.com\/\">Moment.js<\/a> as long as the pattern is defined in the <code>format<\/code> property of the field schema. Internally, values are <em>always<\/em> stored as Unix timestamps.<\/td>\n<td style=\"text-align:left\"><code>&quot;2018-04-27T13:18:15.608Z&quot;<\/code>, <code>1524835111068<\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\">Boolean<\/td>\n<td style=\"text-align:left\">Accepts only two possible values: <code>true<\/code> or <code>false<\/code><\/td>\n<td style=\"text-align:left\"><code>true<\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\">Object<\/td>\n<td style=\"text-align:left\">Accepts single JSON documents or an array of documents<\/td>\n<td style=\"text-align:left\"><code>{ &quot;firstName&quot;: &quot;Steve&quot; }<\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\">Mixed<\/td>\n<td style=\"text-align:left\">Can accept any of the above types: String, Number, Boolean or Object<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\">Reference<\/td>\n<td style=\"text-align:left\">Used for linking documents in the same collection or a different collection, solving the problem of storing subdocuments in documents. See <a href=\"#document-composition\">Document Composition (reference fields)<\/a> for further information.<\/td>\n<td style=\"text-align:left\">the ID of another document as a String: <code>&quot;560a5baf320039f7d6a78d3b&quot;<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3><a href=\"#collection-settings\" id=\"collection-settings\" name=\"collection-settings\" class=\"anchor\">Anchor link<\/a> <a href=\"#collection-settings\">Collection settings<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">Each collection specification can contain a <code>settings<\/code>. API applies sensible defaults to collections, all of which can be overridden using properties in the <code>settings<\/code> block. Collection configuration is controlled in the following way:<\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"settings\"<\/span>: {\n    <span class=\"hljs-attr\">\"cache\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n    <span class=\"hljs-attr\">\"authenticate\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n    <span class=\"hljs-attr\">\"count\"<\/span>: <span class=\"hljs-number\">100<\/span>,\n    <span class=\"hljs-attr\">\"sort\"<\/span>: <span class=\"hljs-string\">\"title\"<\/span>,\n    <span class=\"hljs-attr\">\"sortOrder\"<\/span>: <span class=\"hljs-number\">1<\/span>,\n    <span class=\"hljs-attr\">\"callback\"<\/span>: <span class=\"hljs-literal\">null<\/span>,\n    <span class=\"hljs-attr\">\"storeRevisions\"<\/span>: <span class=\"hljs-literal\">false<\/span>\n    <span class=\"hljs-string\">\"index\"<\/span>: []\n  }\n}\n<\/code><\/pre>\n<table>\n<thead>\n<tr>\n<th style=\"text-align:left\">Property<\/th>\n<th style=\"text-align:left\">Description<\/th>\n<th style=\"text-align:left\">Default<\/th>\n<th style=\"text-align:left\">Example<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td style=\"text-align:left\">displayName<\/td>\n<td style=\"text-align:left\">A friendly name for the collection. Used by the auto-generated documentation plugin.<\/td>\n<td style=\"text-align:left\">n\/a<\/td>\n<td style=\"text-align:left\"><code>&quot;Articles&quot;<\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\">cache<\/td>\n<td style=\"text-align:left\">If true, caching is enabled for this collection. The global config must also have <code>cache: true<\/code> for caching to be enabled<\/td>\n<td style=\"text-align:left\"><code>false<\/code><\/td>\n<td style=\"text-align:left\"><code>true<\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\">authenticate<\/td>\n<td style=\"text-align:left\">Specifies whether requests for this collection require authentication, or if there only certain HTTP methods that must be authenticated<\/td>\n<td style=\"text-align:left\"><code>true<\/code><\/td>\n<td style=\"text-align:left\"><code>false<\/code>, <code>[&quot;POST&quot;]<\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\">count<\/td>\n<td style=\"text-align:left\">The number of results to return when querying the collection<\/td>\n<td style=\"text-align:left\"><code>50<\/code><\/td>\n<td style=\"text-align:left\"><code>100<\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\">sort<\/td>\n<td style=\"text-align:left\">The field to sort results by<\/td>\n<td style=\"text-align:left\"><code>&quot;_id&quot;<\/code><\/td>\n<td style=\"text-align:left\"><code>&quot;title&quot;<\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\">sortOrder<\/td>\n<td style=\"text-align:left\">The sort direction to sort results by<\/td>\n<td style=\"text-align:left\"><code>1<\/code><\/td>\n<td style=\"text-align:left\"><code>1<\/code> = ascending, <code>-1<\/code> = descending<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\">enableVersioning<\/td>\n<td style=\"text-align:left\">Whether to store a new document revision for each update\/delete operation<\/td>\n<td style=\"text-align:left\"><code>true<\/code><\/td>\n<td style=\"text-align:left\"><code>false<\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\">versioningCollection<\/td>\n<td style=\"text-align:left\">The name of the collection used to hold revision documents<\/td>\n<td style=\"text-align:left\">The collection name with the string <code>&quot;Versions&quot;<\/code> appended<\/td>\n<td style=\"text-align:left\"><code>&quot;authorsVersions&quot;<\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\">callback<\/td>\n<td style=\"text-align:left\">Name of a function to use as a JSONP callback<\/td>\n<td style=\"text-align:left\"><code>null<\/code><\/td>\n<td style=\"text-align:left\"><code>setAuthors<\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\">defaultFilters<\/td>\n<td style=\"text-align:left\">Specifies a default query for the collection. A <code>filter<\/code> parameter passed in the querystring will extend these filters.<\/td>\n<td style=\"text-align:left\"><code>{}<\/code><\/td>\n<td style=\"text-align:left\"><code>{ &quot;published&quot;: true }<\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\">fieldLimiters<\/td>\n<td style=\"text-align:left\">Specifies a list of fields for inclusion\/exclusion in the response. Fields can be included or excluded, but not both. See <a href=\"#retrieving-data\">Retrieving data<\/a> for more detail.<\/td>\n<td style=\"text-align:left\"><code>{}<\/code><\/td>\n<td style=\"text-align:left\"><code>{ &quot;title&quot;: 1, &quot;author&quot;: 1 }<\/code>, <code>{ &quot;dob&quot;: 0, &quot;state&quot;: 0 }<\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\">index<\/td>\n<td style=\"text-align:left\">Specifies a set of indexes that should be created for the collection. See <a href=\"#creating-database-indexes\">Creating Database Indexes<\/a> for more detail.<\/td>\n<td style=\"text-align:left\"><code>[]<\/code><\/td>\n<td style=\"text-align:left\"><code>{ &quot;keys&quot;: { &quot;username&quot;: 1 }, &quot;options&quot;: { &quot;unique&quot;: true } }<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<blockquote class=\"advice\">\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Overriding configuration using querystring parameters<\/strong><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">It is possible to override some of these values when requesting data from the endpoint, by using querystring parameters. See <a href=\"#querying\">Querying a collection<\/a> for detailed documentation.<\/p>\n<\/blockquote>\n<h3><a href=\"#collection-configuration-endpoints\" id=\"collection-configuration-endpoints\" name=\"collection-configuration-endpoints\" class=\"anchor\">Anchor link<\/a> <a href=\"#collection-configuration-endpoints\">Collection configuration endpoints<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">Every collection in your API has an additional configuration route available. To use it, append <code>\/config<\/code> to one of your collection endpoints, for example: https:\/\/api.somedomain.tech\/1.0\/libray\/books\/config.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">Making a GET request to the collection&#39;s configuration endpoint returns the collection schema:<\/p>\n<pre><code class=\"lang-http\"><span class=\"hljs-builtin-name\">GET<\/span> \/1.0\/library\/books<span class=\"hljs-built_in\">\/config <\/span>HTTP\/1.1\nContent-Type: application\/json\nAuthorization: Bearer 37f9786b-3f39-4c87-a8ff-9530efd176c3\nHost: api.somedomain.tech\nConnection: close\n<\/code><\/pre>\n<pre><code class=\"lang-http\">HTTP\/1.1 <span class=\"hljs-number\">200<\/span> OK\n<span class=\"hljs-attribute\">Content-Type<\/span>: application\/json\n<span class=\"hljs-attribute\">content-length<\/span>: 12639\n<span class=\"hljs-attribute\">Date<\/span>: Mon, 18 Sep 2017 14:05:44 GMT\n<span class=\"hljs-attribute\">Connection<\/span>: close\n<span class=\"json\">{\n  <span class=\"hljs-attr\">\"fields\"<\/span>: {\n    <span class=\"hljs-attr\">\"published\"<\/span>: {\n      <span class=\"hljs-attr\">\"type\"<\/span>: <span class=\"hljs-string\">\"Object\"<\/span>,\n      <span class=\"hljs-attr\">\"label\"<\/span>: <span class=\"hljs-string\">\"Published State\"<\/span>,\n      <span class=\"hljs-attr\">\"required\"<\/span>: <span class=\"hljs-literal\">true<\/span>\n    }\n  },\n  <span class=\"hljs-attr\">\"settings\"<\/span>: {\n  }\n}<\/span>\n<\/code><\/pre>\n<h2><a href=\"#the-rest-api\" id=\"the-rest-api\" name=\"the-rest-api\" class=\"anchor\">Anchor link<\/a> <a href=\"#the-rest-api\">The REST API<\/a><\/h2>\n<p class=\"7xtjw4dqwy5mz7w3j\">The primary way of interacting with DADI API is via REST endpoints that are automatically generated for each of the <a href=\"#collections\">collections<\/a> added to the application. Each REST endpoint allows you to insert, update, delete and query data stored in the underlying database.<\/p>\n<h3><a href=\"#rest-endpoint-format\" id=\"rest-endpoint-format\" name=\"rest-endpoint-format\" class=\"anchor\">Anchor link<\/a> <a href=\"#rest-endpoint-format\">REST endpoint format<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\"><code>http(s):\/\/api.somedomain.tech\/{version}\/{database}\/{collection name}<\/code><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">The REST endpoints follow the above format, where <code>{version}<\/code> is the current version of the API collections (not the installed version of API), <code>{database}<\/code> is the database that holds the specified collection and <code>{collection name}<\/code> is the actual collection to interact with. See <a href=\"#collections-directory\">Collections directory<\/a> for more detail.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">Example endpoints for each of the supported HTTP verbs:<\/p>\n<pre><code><span class=\"hljs-comment\"># Insert documents<\/span>\nPOST \/<span class=\"hljs-number\">1.0<\/span>\/<span class=\"hljs-keyword\">my<\/span>-database\/<span class=\"hljs-keyword\">my<\/span>-collection\n<span class=\"hljs-comment\"># Update documents<\/span>\nPUT \/<span class=\"hljs-number\">1.0<\/span>\/<span class=\"hljs-keyword\">my<\/span>-database\/<span class=\"hljs-keyword\">my<\/span>-collection\n<span class=\"hljs-comment\"># Delete documents<\/span>\nDELETE \/<span class=\"hljs-number\">1.0<\/span>\/<span class=\"hljs-keyword\">my<\/span>-database\/<span class=\"hljs-keyword\">my<\/span>-collection\n<span class=\"hljs-comment\"># Get documents<\/span>\nGET \/<span class=\"hljs-number\">1.0<\/span>\/<span class=\"hljs-keyword\">my<\/span>-database\/<span class=\"hljs-keyword\">my<\/span>-collection\n<\/code><\/pre>\n<h3><a href=\"#content-type-header\" id=\"content-type-header\" name=\"content-type-header\" class=\"anchor\">Anchor link<\/a> <a href=\"#content-type-header\">Content-type header<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">In almost all cases, the <code>Content-Type<\/code> header should be <code>application\/json<\/code>. API contains some internal endpoints which allow <code>text\/plain<\/code> but for all interaction using the above endpoints you should use <code>application\/json<\/code>.<\/p>\n<h3><a href=\"#authorization-header\" id=\"authorization-header\" name=\"authorization-header\" class=\"anchor\">Anchor link<\/a> <a href=\"#authorization-header\">Authorization header<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">Unless a collection has authentication disabled, every request using the above REST endpoints will require an Authorization header containing an access token. See <a href=\"#obtaining-an-access-token\">Obtaining an Access Token<\/a> for more detail.<\/p>\n<h2><a href=\"#working-with-data\" id=\"working-with-data\" name=\"working-with-data\" class=\"anchor\">Anchor link<\/a> <a href=\"#working-with-data\">Working with data<\/a><\/h2>\n<h3><a href=\"#retrieving-data\" id=\"retrieving-data\" name=\"retrieving-data\" class=\"anchor\">Anchor link<\/a> <a href=\"#retrieving-data\">Retrieving data<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">Sending a request using the <code>GET<\/code> method instructs API to find and retrieve all documents that match a certain criteria.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">There are two types of retrieval operation: one where a single document is to be retrieved and its identifier is known; and the other where one or many documents matching a query should be retrieved.<\/p>\n<h4><a href=\"#retrieve-a-single-resource-by-id\" id=\"retrieve-a-single-resource-by-id\" name=\"retrieve-a-single-resource-by-id\" class=\"anchor\">Anchor link<\/a> <a href=\"#retrieve-a-single-resource-by-id\">Retrieve a single resource by ID<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">To retrieve a document with a known identifier, add the identifier to the REST endpoint for the collection.<\/p>\n<h5><a href=\"#request\" id=\"request\" name=\"request\" class=\"anchor\">Anchor link<\/a> <a href=\"#request\">Request<\/a><\/h5>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Format:<\/strong> <code>GET http:\/\/api.somedomain.tech\/1.0\/library\/books\/{ID}<\/code><\/p>\n<pre><code class=\"lang-http\">GET \/<span class=\"hljs-number\">1.0<\/span>\/library\/books\/560a44b33a4d7de29f168ce4 HTTP\/<span class=\"hljs-number\">1.1<\/span>\nAuthorization: Bearer afd4368e-f312-<span class=\"hljs-number\">4b14<\/span>-bd93-30f35a4b4814\nContent-Type: application\/json\nHost: api.somedomain.tech\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\">Retrieves the document with the identifier of <code>{ID}<\/code> from the specified collection (in this example <code>books<\/code>).<\/p>\n<h4><a href=\"#retrieve-all-documents-matching-a-query\" id=\"retrieve-all-documents-matching-a-query\" name=\"retrieve-all-documents-matching-a-query\" class=\"anchor\">Anchor link<\/a> <a href=\"#retrieve-all-documents-matching-a-query\">Retrieve all documents matching a query<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">Useful for retrieving multiple documents that have a common property or share a pattern. Include the query in the querystring using the <code>filter<\/code> parameter.<\/p>\n<h5><a href=\"#request-1\" id=\"request-1\" name=\"request-1\" class=\"anchor\">Anchor link<\/a> <a href=\"#request-1\">Request<\/a><\/h5>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Format:<\/strong> <code>GET http:\/\/api.somedomain.tech\/1.0\/library\/books?filter={QUERY}<\/code><\/p>\n<pre><code class=\"lang-http\">GET \/<span class=\"hljs-number\">1.0<\/span>\/library\/books?filter={<span class=\"hljs-string\">\"title\"<\/span>:{<span class=\"hljs-string\">\"$regex\"<\/span>:<span class=\"hljs-string\">\"the\"<\/span>}} HTTP\/<span class=\"hljs-number\">1.1<\/span>\nAuthorization: Bearer afd4368e-f312-<span class=\"hljs-number\">4b14<\/span>-bd93-30f35a4b4814\nContent-Type: application\/json\nHost: api.somedomain.tech\n<\/code><\/pre>\n<h4><a href=\"#query-options\" id=\"query-options\" name=\"query-options\" class=\"anchor\">Anchor link<\/a> <a href=\"#query-options\">Query options<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">When querying a collection, the following options can be supplied as URL parameters:<\/p>\n<table>\n<thead>\n<tr>\n<th style=\"text-align:left\">Property<\/th>\n<th style=\"text-align:left\">Description<\/th>\n<th style=\"text-align:left\">Default<\/th>\n<th style=\"text-align:left\">Example<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td style=\"text-align:left\"><code>compose<\/code><\/td>\n<td style=\"text-align:left\">Whether to resolve referenced documents (see the possible values of the <a href=\"#enabling-composition\"><code>compose<\/code> parameter<\/a>)<\/td>\n<td style=\"text-align:left\">The value of <code>settings.compose<\/code> in the collection schema<\/td>\n<td style=\"text-align:left\"><code>compose=true<\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>count<\/code><\/td>\n<td style=\"text-align:left\">The maximum number of documents to be retrieved in one page<\/td>\n<td style=\"text-align:left\">The value of <code>settings.count<\/code> in the collection schema<\/td>\n<td style=\"text-align:left\"><code>count=30<\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>fields<\/code><\/td>\n<td style=\"text-align:left\">The list of fields to include or exclude from the response. Takes an object mapping field names to either <code>1<\/code> or <code>0<\/code>, which will include or exclude the field, respectively.<\/td>\n<td style=\"text-align:left\">The value of <code>settings.compose<\/code> in the collection schema<\/td>\n<td style=\"text-align:left\"><code>fields={&quot;first_name&quot;:1,&quot;l_name&quot;:1}<\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>filter<\/code><\/td>\n<td style=\"text-align:left\">A query to filter results by. See <a href=\"#filtering-documents\">filtering documents<\/a> for more detail.<\/td>\n<td style=\"text-align:left\">The value of <code>settings.compose<\/code> in the collection schema<\/td>\n<td style=\"text-align:left\"><code>fields={&quot;first_name&quot;:1,&quot;l_name&quot;:1}<\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>version<\/code><\/td>\n<td style=\"text-align:left\">The ID of a particular revision of a document to retrieve. Applicable only when retrieving a single document by ID and the collection being queried has document versioning enabled.<\/td>\n<td style=\"text-align:left\"><code>null<\/code><\/td>\n<td style=\"text-align:left\"><code>version=5c54612ed10f781ca6fff604<\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>page<\/code><\/td>\n<td style=\"text-align:left\">The number of the page of results to retrieve<\/td>\n<td style=\"text-align:left\"><code>1<\/code><\/td>\n<td style=\"text-align:left\"><code>page=3<\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>sort<\/code><\/td>\n<td style=\"text-align:left\">The sort direction to sort results by, mapping field names to either <code>1<\/code> or <code>0<\/code>, which will sort results by that field in ascending or descending order, respectively<\/td>\n<td style=\"text-align:left\">The value of <code>settings.sortOrder<\/code> in the collection schema<\/td>\n<td style=\"text-align:left\"><code>sort={&quot;first_name&quot;:1}<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h4><a href=\"#filtering-documents\" id=\"filtering-documents\" name=\"filtering-documents\" class=\"anchor\">Anchor link<\/a> <a href=\"#filtering-documents\">Filtering documents<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">DADI API uses a MongoDB-style format for querying objects, introducing a series of operators that allow powerful queries to be assembled.<\/p>\n<table>\n<thead>\n<tr>\n<th style=\"text-align:left\">Syntax<\/th>\n<th style=\"text-align:left\">Description<\/th>\n<th style=\"text-align:left\">Example<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td style=\"text-align:left\"><code>{field:value}<\/code><\/td>\n<td style=\"text-align:left\">Strict comparison. Matches documents where the value of <code>field<\/code> is exactly <code>value<\/code><\/td>\n<td style=\"text-align:left\"><code>{&quot;first_name&quot;:&quot;John&quot;}<\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>{field:{&quot;$regex&quot;: value}}<\/code><\/td>\n<td style=\"text-align:left\">Matches documents where the value of <code>field<\/code> matches a regular expression defined as <code>\/value\/i<\/code><\/td>\n<td style=\"text-align:left\"><code>{&quot;first_name&quot;:{&quot;$regex&quot;:John&quot;}}<\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>{field:{&quot;$in&quot;:[value1,value2]}}<\/code><\/td>\n<td style=\"text-align:left\">Matches documents where the value of <code>field<\/code> is one of <code>value1<\/code> and <code>value2<\/code><\/td>\n<td style=\"text-align:left\"><code>{&quot;last_name&quot;:{&quot;$in&quot;:[&quot;Doe&quot;,&quot;Spencer&quot;,&quot;Appleseed&quot;]}}<\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>{field:{&quot;$containsAny&quot;:[value1,value2]}}<\/code><\/td>\n<td style=\"text-align:left\">Matches documents where the value of <code>field<\/code> (an array) contains one of <code>value1<\/code> and <code>value2<\/code><\/td>\n<td style=\"text-align:left\"><code>{&quot;tags&quot;:{&quot;$containsAny&quot;:[&quot;dadi&quot;,&quot;dadi-api&quot;,&quot;restful&quot;]}}<\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>{field:{&quot;$gt&quot;: value}}<\/code><\/td>\n<td style=\"text-align:left\">Matches documents where the value of <code>field<\/code> is greater than <code>value<\/code><\/td>\n<td style=\"text-align:left\"><code>{&quot;height&quot;:{&quot;$gt&quot;:175}}<\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>{field:{&quot;$lt&quot;: value}}<\/code><\/td>\n<td style=\"text-align:left\">Matches documents where the value of <code>field<\/code> is less than <code>value<\/code><\/td>\n<td style=\"text-align:left\"><code>{&quot;weight&quot;:{&quot;$lt&quot;:85}}<\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>{field:&quot;$now&quot;}<\/code>, <code>{field:{&quot;$lt&quot;:&quot;$now&quot;}}<\/code>, etc.<\/td>\n<td style=\"text-align:left\"><strong>(DateTime fields only)<\/strong> Matches documents comparing the value of <code>field<\/code> against the current date<\/td>\n<td style=\"text-align:left\"><code>{&quot;publishDate&quot;:{&quot;$lt&quot;:&quot;$now&quot;}}<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3><a href=\"#inserting-data\" id=\"inserting-data\" name=\"inserting-data\" class=\"anchor\">Anchor link<\/a> <a href=\"#inserting-data\">Inserting data<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">Inserting data involves sending a POST request to the endpoint for the collection that will store the data. If the data passes <a href=\"#validation\">validation rules<\/a> imposed by the collection, it is inserted into the collection with a set of internal fields added.<\/p>\n<h4><a href=\"#request-2\" id=\"request-2\" name=\"request-2\" class=\"anchor\">Anchor link<\/a> <a href=\"#request-2\">Request<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Format:<\/strong> <code>POST http:\/\/api.somedomain.tech\/1.0\/library\/books<\/code><\/p>\n<pre><code class=\"lang-http\"><span class=\"hljs-keyword\">POST<\/span> <span class=\"hljs-string\">\/1.0\/library\/books<\/span> HTTP\/1.1\n<span class=\"hljs-attribute\">Authorization<\/span>: Bearer afd4368e-f312-4b14-bd93-30f35a4b4814\n<span class=\"hljs-attribute\">Content-Type<\/span>: application\/json\n<span class=\"hljs-attribute\">Host<\/span>: api.somedomain.tech\n<span class=\"json\">{\n  <span class=\"hljs-attr\">\"title\"<\/span>: <span class=\"hljs-string\">\"The Old Man and the Sea\"<\/span>\n}<\/span>\n<\/code><\/pre>\n<h4><a href=\"#response\" id=\"response\" name=\"response\" class=\"anchor\">Anchor link<\/a> <a href=\"#response\">Response<\/a><\/h4>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"results\"<\/span>: [\n    <span class=\"hljs-string\">\"_id\"<\/span>: <span class=\"hljs-string\">\"5ae1b6464e0b766dd17dbab9\"<\/span>\n    <span class=\"hljs-string\">\"_apiVersion\"<\/span>: <span class=\"hljs-string\">\"1.0\"<\/span>,\n    <span class=\"hljs-string\">\"_createdAt\"<\/span>: <span class=\"hljs-number\">1511875141<\/span>,\n    <span class=\"hljs-string\">\"_createdBy\"<\/span>: <span class=\"hljs-string\">\"your-client-id\"<\/span>,\n    <span class=\"hljs-string\">\"_version\"<\/span>: <span class=\"hljs-number\">1<\/span>,\n    <span class=\"hljs-string\">\"title\"<\/span>: <span class=\"hljs-string\">\"The Old Man and the Sea\"<\/span>\n  ]\n}\n<\/code><\/pre>\n<h4><a href=\"#common-validation-errors\" id=\"common-validation-errors\" name=\"common-validation-errors\" class=\"anchor\">Anchor link<\/a> <a href=\"#common-validation-errors\">Common validation errors<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">In addition to failures caused by validation rules in collection field specifications, you may also receive an <code>HTTP 400 Bad Request<\/code> error if either required fields are missing or extra fields are sent that don&#39;t exist in the collection:<\/p>\n<pre><code>HTTP\/1.1 <span class=\"hljs-number\">400<\/span> Bad Request\n<span class=\"hljs-attribute\">Content-Type<\/span>: application\/json\n<span class=\"hljs-attribute\">content-length<\/span>: 681\n<span class=\"hljs-attribute\">Date<\/span>: Mon, 18 Sep 2017 18:21:04 GMT\n<span class=\"hljs-attribute\">Connection<\/span>: close\n<span class=\"json\">{\n  <span class=\"hljs-attr\">\"success\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n  <span class=\"hljs-attr\">\"errors\"<\/span>: [\n    {\n      <span class=\"hljs-attr\">\"field\"<\/span>: <span class=\"hljs-string\">\"description\"<\/span>,\n      <span class=\"hljs-attr\">\"message\"<\/span>: <span class=\"hljs-string\">\"can't be blank\"<\/span>\n    },\n    {\n      <span class=\"hljs-attr\">\"field\"<\/span>: <span class=\"hljs-string\">\"extra_field\"<\/span>,\n      <span class=\"hljs-attr\">\"message\"<\/span>: <span class=\"hljs-string\">\"doesn't exist in the collection schema\"<\/span>\n    }\n  ]\n}<\/span>\n<\/code><\/pre>\n<h4><a href=\"#batch-inserting-documents\" id=\"batch-inserting-documents\" name=\"batch-inserting-documents\" class=\"anchor\">Anchor link<\/a> <a href=\"#batch-inserting-documents\">Batch inserting documents<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">It is possible to insert multiple documents in a single POST request by sending an array to the endpoint:<\/p>\n<pre><code class=\"lang-http\"><span class=\"hljs-keyword\">POST<\/span> <span class=\"hljs-string\">\/1.0\/library\/books<\/span> HTTP\/1.1\n<span class=\"hljs-attribute\">Authorization<\/span>: Bearer afd4368e-f312-4b14-bd93-30f35a4b4814\n<span class=\"hljs-attribute\">Content-Type<\/span>: application\/json\n<span class=\"hljs-attribute\">Host<\/span>: api.somedomain.tech\n<span class=\"json\">[\n  {\n    <span class=\"hljs-attr\">\"title\"<\/span>: <span class=\"hljs-string\">\"The Old Man and the Sea\"<\/span>\n  },\n  {\n    <span class=\"hljs-attr\">\"title\"<\/span>: <span class=\"hljs-string\">\"For Whom the Bell Tolls\"<\/span>\n  }\n]<\/span>\n<\/code><\/pre>\n<h3><a href=\"#updating-data\" id=\"updating-data\" name=\"updating-data\" class=\"anchor\">Anchor link<\/a> <a href=\"#updating-data\">Updating data<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">Updating data with API involves sending a PUT request to the endpoint for the collection that holds the data.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">There are two types of update operation: one where a single document is to be updated and its identifier is known; and the other where one or many documents matching a query should be updated.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">In both cases, the request body must contain the required update specified as JSON.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">If the data passes <a href=\"#validation\">validation rules<\/a> imposed by the collection, it is updated using the specified update, and the internal fields <code>_lastModifiedAt<\/code>, <code>_lastModifiedBy<\/code> and <code>_version<\/code> are updated.<\/p>\n<h4><a href=\"#update-an-existing-resource\" id=\"update-an-existing-resource\" name=\"update-an-existing-resource\" class=\"anchor\">Anchor link<\/a> <a href=\"#update-an-existing-resource\">Update an existing resource<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">To update a document with a known identifier, add the identifier to the REST endpoint for the collection.<\/p>\n<h5><a href=\"#request-3\" id=\"request-3\" name=\"request-3\" class=\"anchor\">Anchor link<\/a> <a href=\"#request-3\">Request<\/a><\/h5>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Format:<\/strong> <code>PUT http:\/\/api.somedomain.tech\/1.0\/library\/books\/{ID}<\/code><\/p>\n<pre><code class=\"lang-http\"><span class=\"hljs-keyword\">PUT<\/span> <span class=\"hljs-string\">\/1.0\/library\/books\/560a44b33a4d7de29f168ce4<\/span> HTTP\/1.1\n<span class=\"hljs-attribute\">Authorization<\/span>: Bearer afd4368e-f312-4b14-bd93-30f35a4b4814\n<span class=\"hljs-attribute\">Content-Type<\/span>: application\/json\n<span class=\"hljs-attribute\">Host<\/span>: api.somedomain.tech\n<span class=\"json\">{\n  <span class=\"hljs-attr\">\"update\"<\/span>: {\n    <span class=\"hljs-attr\">\"title\"<\/span>: <span class=\"hljs-string\">\"For Whom the Bell Tolls (Kindle Edition)\"<\/span>\n  }\n}<\/span>\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\">Updates the document with the identifier of <code>{ID}<\/code> in the specified collection (in this example <code>books<\/code>). Applies the values from the <code>update<\/code> block specified in the request body.<\/p>\n<h5><a href=\"#response-1\" id=\"response-1\" name=\"response-1\" class=\"anchor\">Anchor link<\/a> <a href=\"#response-1\">Response<\/a><\/h5>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"results\"<\/span>: [\n    {\n      <span class=\"hljs-attr\">\"_apiVersion\"<\/span>: <span class=\"hljs-string\">\"v1\"<\/span>,\n      <span class=\"hljs-attr\">\"_createdAt\"<\/span>: <span class=\"hljs-number\">1524741702962<\/span>,\n      <span class=\"hljs-attr\">\"_createdBy\"<\/span>: <span class=\"hljs-string\">\"testClient\"<\/span>,\n      <span class=\"hljs-attr\">\"_id\"<\/span>: <span class=\"hljs-string\">\"5ae1b6464e0b766dd17dbab9\"<\/span>,\n      <span class=\"hljs-attr\">\"_lastModifiedAt\"<\/span>: <span class=\"hljs-number\">1524741826339<\/span>,\n      <span class=\"hljs-attr\">\"_lastModifiedBy\"<\/span>: <span class=\"hljs-string\">\"testClient\"<\/span>,\n      <span class=\"hljs-attr\">\"_version\"<\/span>: <span class=\"hljs-number\">2<\/span>,\n      <span class=\"hljs-attr\">\"title\"<\/span>: <span class=\"hljs-string\">\"For Whom the Bell Tolls (Kindle Edition)\"<\/span>\n    }\n  ],\n  <span class=\"hljs-attr\">\"metadata\"<\/span>: {\n    <span class=\"hljs-attr\">\"fields\"<\/span>: {},\n    <span class=\"hljs-attr\">\"page\"<\/span>: <span class=\"hljs-number\">1<\/span>,\n    <span class=\"hljs-attr\">\"offset\"<\/span>: <span class=\"hljs-number\">0<\/span>,\n    <span class=\"hljs-attr\">\"totalCount\"<\/span>: <span class=\"hljs-number\">1<\/span>,\n    <span class=\"hljs-attr\">\"totalPages\"<\/span>: <span class=\"hljs-number\">1<\/span>\n  }\n}\n<\/code><\/pre>\n<h4><a href=\"#update-all-documents-matching-a-query\" id=\"update-all-documents-matching-a-query\" name=\"update-all-documents-matching-a-query\" class=\"anchor\">Anchor link<\/a> <a href=\"#update-all-documents-matching-a-query\">Update all documents matching a query<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">Useful for batch updating documents that have a common property. Include the query in the request body, along with the required update.<\/p>\n<h5><a href=\"#request-4\" id=\"request-4\" name=\"request-4\" class=\"anchor\">Anchor link<\/a> <a href=\"#request-4\">Request<\/a><\/h5>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Format:<\/strong> <code>PUT http:\/\/api.somedomain.tech\/1.0\/library\/books<\/code><\/p>\n<pre><code class=\"lang-http\"><span class=\"hljs-keyword\">PUT<\/span> <span class=\"hljs-string\">\/1.0\/library\/books<\/span> HTTP\/1.1\n<span class=\"hljs-attribute\">Authorization<\/span>: Bearer afd4368e-f312-4b14-bd93-30f35a4b4814\n<span class=\"hljs-attribute\">Content-Type<\/span>: application\/json\n<span class=\"hljs-attribute\">Host<\/span>: api.somedomain.tech\n<span class=\"json\">{\n  <span class=\"hljs-attr\">\"query\"<\/span>: {\n    <span class=\"hljs-attr\">\"title\"<\/span>: {\n      <span class=\"hljs-attr\">\"$regex\"<\/span>: <span class=\"hljs-string\">\"the\"<\/span>\n    }\n  },\n  <span class=\"hljs-attr\">\"update\"<\/span>: {\n    <span class=\"hljs-attr\">\"available\"<\/span>: <span class=\"hljs-literal\">false<\/span>\n  }\n}<\/span>\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\">Updates all documents that match the results of the <code>query<\/code> in the specified collection (in this example <code>&quot;books&quot;<\/code>). Applies the values from the <code>update<\/code> block specified in the request body.<\/p>\n<h5><a href=\"#response-2\" id=\"response-2\" name=\"response-2\" class=\"anchor\">Anchor link<\/a> <a href=\"#response-2\">Response<\/a><\/h5>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"results\"<\/span>: [\n    {\n      <span class=\"hljs-attr\">\"_apiVersion\"<\/span>: <span class=\"hljs-string\">\"v1\"<\/span>,\n      <span class=\"hljs-attr\">\"_createdAt\"<\/span>: <span class=\"hljs-number\">1524741702962<\/span>,\n      <span class=\"hljs-attr\">\"_createdBy\"<\/span>: <span class=\"hljs-string\">\"testClient\"<\/span>,\n      <span class=\"hljs-attr\">\"_id\"<\/span>: <span class=\"hljs-string\">\"5ae1b6464e0b766dd17dbab9\"<\/span>,\n      <span class=\"hljs-attr\">\"_lastModifiedAt\"<\/span>: <span class=\"hljs-number\">1524741826339<\/span>,\n      <span class=\"hljs-attr\">\"_lastModifiedBy\"<\/span>: <span class=\"hljs-string\">\"testClient\"<\/span>,\n      <span class=\"hljs-attr\">\"_version\"<\/span>: <span class=\"hljs-number\">2<\/span>,\n      <span class=\"hljs-attr\">\"title\"<\/span>: <span class=\"hljs-string\">\"For Whom the Bell Tolls (Kindle Edition)\"<\/span>,\n      <span class=\"hljs-attr\">\"available\"<\/span>: <span class=\"hljs-literal\">false<\/span>\n    },\n    {\n      <span class=\"hljs-attr\">\"_apiVersion\"<\/span>: <span class=\"hljs-string\">\"v1\"<\/span>,\n      <span class=\"hljs-attr\">\"_createdAt\"<\/span>: <span class=\"hljs-number\">1524741702962<\/span>,\n      <span class=\"hljs-attr\">\"_createdBy\"<\/span>: <span class=\"hljs-string\">\"testClient\"<\/span>,\n      <span class=\"hljs-attr\">\"_id\"<\/span>: <span class=\"hljs-string\">\"5ae1b6464e0b766dd17dbab8\"<\/span>,\n      <span class=\"hljs-attr\">\"_lastModifiedAt\"<\/span>: <span class=\"hljs-number\">1524741826339<\/span>,\n      <span class=\"hljs-attr\">\"_lastModifiedBy\"<\/span>: <span class=\"hljs-string\">\"testClient\"<\/span>,\n      <span class=\"hljs-attr\">\"_version\"<\/span>: <span class=\"hljs-number\">1<\/span>,\n      <span class=\"hljs-attr\">\"title\"<\/span>: <span class=\"hljs-string\">\"The Old Man and the Sea\"<\/span>,\n      <span class=\"hljs-attr\">\"available\"<\/span>: <span class=\"hljs-literal\">false<\/span>\n    }\n  ],\n  <span class=\"hljs-attr\">\"metadata\"<\/span>: {\n    <span class=\"hljs-attr\">\"fields\"<\/span>: {},\n    <span class=\"hljs-attr\">\"page\"<\/span>: <span class=\"hljs-number\">1<\/span>,\n    <span class=\"hljs-attr\">\"offset\"<\/span>: <span class=\"hljs-number\">0<\/span>,\n    <span class=\"hljs-attr\">\"totalCount\"<\/span>: <span class=\"hljs-number\">2<\/span>,\n    <span class=\"hljs-attr\">\"totalPages\"<\/span>: <span class=\"hljs-number\">1<\/span>\n  }\n}\n<\/code><\/pre>\n<h3><a href=\"#deleting-data\" id=\"deleting-data\" name=\"deleting-data\" class=\"anchor\">Anchor link<\/a> <a href=\"#deleting-data\">Deleting data<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">Sending a request using the <code>DELETE<\/code> method instructs API to perform a delete operation on the documents that match the supplied parameters.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">There are two types of delete operation: one where a single document is to be deleted and its identifier is known; and the other where one or many documents matching a query should be deleted.<\/p>\n<h4><a href=\"#delete-an-existing-resource\" id=\"delete-an-existing-resource\" name=\"delete-an-existing-resource\" class=\"anchor\">Anchor link<\/a> <a href=\"#delete-an-existing-resource\">Delete an existing resource<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">To delete a document with a known identifier, add the identifier to the REST endpoint for the collection.<\/p>\n<h5><a href=\"#request-5\" id=\"request-5\" name=\"request-5\" class=\"anchor\">Anchor link<\/a> <a href=\"#request-5\">Request<\/a><\/h5>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Format:<\/strong> <code>DELETE http:\/\/api.somedomain.tech\/1.0\/library\/books\/{ID}<\/code><\/p>\n<pre><code class=\"lang-http\">DELETE \/<span class=\"hljs-number\">1.0<\/span>\/library\/books\/560a44b33a4d7de29f168ce4 HTTP\/<span class=\"hljs-number\">1.1<\/span>\nAuthorization: Bearer afd4368e-f312-<span class=\"hljs-number\">4b14<\/span>-bd93-30f35a4b4814\nContent-Type: application\/json\nHost: api.somedomain.tech\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\">Deletes the document with the identifier of <code>{ID}<\/code> from the specified collection (in this example <code>books<\/code>).<\/p>\n<h4><a href=\"#delete-all-documents-matching-a-query\" id=\"delete-all-documents-matching-a-query\" name=\"delete-all-documents-matching-a-query\" class=\"anchor\">Anchor link<\/a> <a href=\"#delete-all-documents-matching-a-query\">Delete all documents matching a query<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">Useful for batch deleting documents that have a common property. Include the query in the request body.<\/p>\n<h5><a href=\"#request-6\" id=\"request-6\" name=\"request-6\" class=\"anchor\">Anchor link<\/a> <a href=\"#request-6\">Request<\/a><\/h5>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Format:<\/strong> <code>DELETE http:\/\/api.somedomain.tech\/1.0\/library\/books<\/code><\/p>\n<pre><code class=\"lang-http\"><span class=\"hljs-keyword\">DELETE<\/span> <span class=\"hljs-string\">\/1.0\/library\/books<\/span> HTTP\/1.1\n<span class=\"hljs-attribute\">Authorization<\/span>: Bearer afd4368e-f312-4b14-bd93-30f35a4b4814\n<span class=\"hljs-attribute\">Content-Type<\/span>: application\/json\n<span class=\"hljs-attribute\">Host<\/span>: api.somedomain.tech\n<span class=\"json\">{\n  <span class=\"hljs-attr\">\"query\"<\/span>: {\n    <span class=\"hljs-attr\">\"title\"<\/span>: <span class=\"hljs-string\">\"The Old Man and the Sea\"<\/span>\n  }\n}<\/span>\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\">Deletes all documents that match the results of the <code>query<\/code> from the specified collection (in this example <code>books<\/code>).<\/p>\n<h4><a href=\"#delete-response\" id=\"delete-response\" name=\"delete-response\" class=\"anchor\">Anchor link<\/a> <a href=\"#delete-response\">DELETE Response<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">The response returned for a DELETE request depends on the configuration setting for <code>feedback<\/code>.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">The default setting is <code>false<\/code>, in which case API returns an <code>HTTP 204 No Content<\/code> after a successful delete operation.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">If the setting is <code>true<\/code> \u2013 that is, the main configuration file contains <code>&quot;feedback&quot;: true<\/code> \u2013 then a JSON object similar to the following is returned:<\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"status\"<\/span>: <span class=\"hljs-string\">\"success\"<\/span>,\n  <span class=\"hljs-attr\">\"message\"<\/span>: <span class=\"hljs-string\">\"Documents deleted successfully\"<\/span>,\n  <span class=\"hljs-attr\">\"deletedCount\"<\/span>: <span class=\"hljs-number\">1<\/span>,\n  <span class=\"hljs-attr\">\"totalCount\"<\/span>: <span class=\"hljs-number\">99<\/span>\n}\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\">Where <code>deletedCount<\/code> is the number of documents deleted and <code>totalCount<\/code> the number of remaining documents in the collection.<\/p>\n<blockquote class=\"warning\"><p>In versions of API prior to 3.0, only the <code>status<\/code> and <code>message<\/code> fields are returned in the response.\n<\/p><\/blockquote>\n<h3><a href=\"#using-models-directly-1\" id=\"using-models-directly-1\" name=\"using-models-directly-1\" class=\"anchor\">Anchor link<\/a> <a href=\"#using-models-directly-1\">Using models directly<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">When creating <a href=\"#endpoints\">custom JavaScript endpoints<\/a> or <a href=\"#hooks\">collection hooks<\/a> it may be useful to consume or create data, in which case it&#39;s possible to interact with the data model directly, as opposed to using the REST API, which would mean issuing an HTTP request.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">The <code>@dadi\/api<\/code> NPM module exports a factory function, named <code>Model<\/code>, which receives the name of the collection and returns a model instance with the following methods available.<\/p>\n<ul>\n<li><a href=\"#count\">count()<\/a><\/li>\n<li><a href=\"#create\">create()<\/a><\/li>\n<li><a href=\"#createindex\">createIndex()<\/a><\/li>\n<li><a href=\"#delete\">delete()<\/a><\/li>\n<li><a href=\"#find\">find()<\/a><\/li>\n<li><a href=\"#get\">get()<\/a><\/li>\n<li><a href=\"#getindexes\">getIndexes()<\/a><\/li>\n<li><a href=\"#getVersions\">getVersions()<\/a><\/li>\n<li><a href=\"#stats\">stats()<\/a><\/li>\n<li><a href=\"#update\">update()<\/a><\/li>\n<\/ul>\n<blockquote class=\"warning\">\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Note<\/strong><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">API 3.1 introduced a new model API, using Promises instead of callbacks and a few other changes. The <a href=\"https:\/\/dadi.cloud#using-models-directly\">legacy version<\/a> is still supported, but it is now deprecated and developers are encouraged to update their code.<\/p>\n<\/blockquote>\n<h4><a href=\"#count\" id=\"count\" name=\"count\" class=\"anchor\">Anchor link<\/a> <a href=\"#count\">count<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">Searches for documents and returns a count.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Receives<\/em><\/strong> <em>(named parameters):<\/em><\/p>\n<ul>\n<li><code>query<\/code> (type: <code>Object<\/code>): Query to match documents against<\/li>\n<li><code>options<\/code> (type: <code>Object<\/code>, optional): Options object for narrowing down the result set (e.g. <code>{page: 3}<\/code>)<\/li>\n<\/ul>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Returns:<\/em><\/strong><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><code>Promise<\/code> with:<\/p>\n<ul>\n<li><code>results<\/code> (<code>Object<\/code>): Metadata block with document count<\/li>\n<\/ul>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Example:<\/em><\/strong><\/p>\n<pre><code class=\"lang-js\">const <span class=\"hljs-keyword\">Model<\/span> = require(<span class=\"hljs-string\">'@dadi\/api'<\/span>).<span class=\"hljs-keyword\">Model<\/span>\n<span class=\"hljs-keyword\">Model<\/span>(<span class=\"hljs-string\">'books'<\/span>).count({\n  query: {\n    title: <span class=\"hljs-string\">'Harry Potter'<\/span>\n  }\n}).<span class=\"hljs-keyword\">then<\/span>(results) =&gt; {\n  console.<span class=\"hljs-built-in\">log<\/span>(results)\n)\n<\/code><\/pre>\n<h4><a href=\"#create\" id=\"create\" name=\"create\" class=\"anchor\">Anchor link<\/a> <a href=\"#create\">create<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">Creates documents in the database. Runs any <code>beforeCreate<\/code> and <code>afterCreate<\/code> hooks configured in the collection.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Receives<\/em><\/strong> <em>(named parameters):<\/em><\/p>\n<ul>\n<li><code>compose<\/code> (type: <code>Boolean<\/code>, default: <code>true<\/code>): Whether to resolved referenced documents in the output payload<\/li>\n<li><code>documents<\/code> (type: <code>Object<\/code> or <code>Array<\/code>): The document (object) or documents (array of objects) to create<\/li>\n<li><code>internals<\/code> (type: <code>Object<\/code>, optional): A set of internal properties to add to each document (note: <code>_id<\/code> is generated automatically)<\/li>\n<li><code>callback<\/code> (type: <code>Function<\/code>): Callback to process results<\/li>\n<li><code>rawOutput<\/code> (type: <code>Boolean<\/code>, optional): By default, results suffer a series of transformations before being sent back to the consumer. The raw output can be obtained by setting this property to <code>true<\/code><\/li>\n<li><code>req<\/code> (type: <code>Object<\/code>, optional): The instance of <a href=\"https:\/\/nodejs.org\/api\/http.html#http_class_http_incomingmessage\">http.IncomingMessage<\/a> that originated the request<\/li>\n<\/ul>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Returns:<\/em><\/strong><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><code>Promise<\/code> with:<\/p>\n<ul>\n<li><code>{results}<\/code> (type: <code>Object<\/code>): Object with a <code>results<\/code> property containing an array of created documents<\/li>\n<\/ul>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Example:<\/em><\/strong><\/p>\n<pre><code class=\"lang-js\">const Model = require(<span class=\"hljs-string\">'@dadi\/api'<\/span>).Model\nModel(<span class=\"hljs-string\">'books'<\/span>).create({\n  documents: [\n    { title: <span class=\"hljs-string\">'Harry Potter'<\/span> },\n    { title: <span class=\"hljs-string\">'Harry Potter 2'<\/span> }\n  ],\n  internals: { _createdBy: <span class=\"hljs-string\">'johnDoe'<\/span> },\n  req\n}).<span class=\"hljs-keyword\">then<\/span>(({results}) =&gt; {\n  console.log(results)\n})\n<\/code><\/pre>\n<h4><a href=\"#createindex\" id=\"createindex\" name=\"createindex\" class=\"anchor\">Anchor link<\/a> <a href=\"#createindex\">createIndex<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">Creates all the indexes defined in the <code>settings.index<\/code> property of the collection schema.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Receives:<\/em><\/strong><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>N\/A<\/em><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Returns:<\/em><\/strong><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><code>Promise<\/code> with:<\/p>\n<ul>\n<li><code>indexes<\/code> (type: <code>Array<\/code>): Array of indexes created, with each element being an object with a <code>collection<\/code> and <code>index<\/code> properties, which represent the name of the collection and the name of the field, respectively<\/li>\n<\/ul>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Example:<\/em><\/strong><\/p>\n<pre><code class=\"lang-js\"><span class=\"hljs-keyword\">const<\/span> Model = <span class=\"hljs-built_in\">require<\/span>(<span class=\"hljs-string\">'@dadi\/api'<\/span>).Model\nModel(<span class=\"hljs-string\">'books'<\/span>).createIndex().then(<span class=\"hljs-function\"><span class=\"hljs-params\">indexes<\/span> =&gt;<\/span> {\n  indexes.forEach(<span class=\"hljs-function\">(<span class=\"hljs-params\">{collection, index}<\/span>) =&gt;<\/span> {\n    <span class=\"hljs-built_in\">console<\/span>.log(<span class=\"hljs-string\">`Created index <span class=\"hljs-subst\">${index}<\/span> in collectino <span class=\"hljs-subst\">${collection}<\/span>.`<\/span>)\n  })\n})\n<\/code><\/pre>\n<h4><a href=\"#delete\" id=\"delete\" name=\"delete\" class=\"anchor\">Anchor link<\/a> <a href=\"#delete\">delete<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">Deletes documents from the database. Runs any <code>beforeDelete<\/code> and <code>afterDelete<\/code> hooks configured in the collection.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Receives<\/em><\/strong> <em>(named parameters):<\/em><\/p>\n<ul>\n<li><code>query<\/code> (type: <code>Object<\/code>): Query to match documents against<\/li>\n<li><code>req<\/code> (type: <code>Object<\/code>, optional): The instance of <a href=\"https:\/\/nodejs.org\/api\/http.html#http_class_http_incomingmessage\">http.IncomingMessage<\/a> that originated the request<\/li>\n<\/ul>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Returns:<\/em><\/strong><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><code>Promise<\/code> with:<\/p>\n<ul>\n<li><code>{deletedCount, totalCount}<\/code> (<code>Object<\/code>): Object indicating the number of documents that were deleted and the number of documents remaining in the collection after the operation<\/li>\n<\/ul>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Example:<\/em><\/strong><\/p>\n<pre><code class=\"lang-js\">const Model = <span class=\"hljs-built_in\">require<\/span>(<span class=\"hljs-string\">'@dadi\/api'<\/span>).Model\nModel(<span class=\"hljs-string\">'books'<\/span>).<span class=\"hljs-keyword\">delete<\/span>({\n  query: {\n    title: <span class=\"hljs-string\">'Harry Potter'<\/span>\n  },\n  req\n}).<span class=\"hljs-keyword\">then<\/span>(<span class=\"hljs-function\"><span class=\"hljs-params\">({deletedCount, totalCount})<\/span> =&gt;<\/span> {\n  <span class=\"hljs-built_in\">console<\/span>.log(`<span class=\"javascript\">Deleted ${deletedCount} documents, ${totalCount} remaining.<\/span>`)\n})\n<\/code><\/pre>\n<h4><a href=\"#find\" id=\"find\" name=\"find\" class=\"anchor\">Anchor link<\/a> <a href=\"#find\">find<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">Retrieves documents from the database.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Receives<\/em><\/strong> <em>(named parameters):<\/em><\/p>\n<ul>\n<li><code>query<\/code> (type: <code>Object<\/code>): Query to match documents against<\/li>\n<li><code>options<\/code> (type: <code>Object<\/code>, optional): Options object for narrowing down the result set (e.g. <code>{page: 3}<\/code>)<\/li>\n<\/ul>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Returns:<\/em><\/strong><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><code>Promise<\/code> with:<\/p>\n<ul>\n<li><code>{metadata, results}<\/code> (<code>Object<\/code>): Object representing the documents retrieved (<code>results<\/code>) as well as a metadata block indicating various types of metrics about the result set (<code>metadata<\/code>)<\/li>\n<\/ul>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Example:<\/em><\/strong><\/p>\n<pre><code class=\"lang-js\">const Model = <span class=\"hljs-built_in\">require<\/span>(<span class=\"hljs-string\">'@dadi\/api'<\/span>).Model\nModel(<span class=\"hljs-string\">'books'<\/span>).find({\n  options: {\n    limit: <span class=\"hljs-number\">10<\/span>,\n    skip: <span class=\"hljs-number\">5<\/span>\n  }\n  query: {\n    title: <span class=\"hljs-string\">'Harry Potter'<\/span>\n  }\n}).<span class=\"hljs-keyword\">then<\/span>(<span class=\"hljs-function\"><span class=\"hljs-params\">({metadata, results})<\/span> =&gt;<\/span> {\n  <span class=\"hljs-built_in\">console<\/span>.log(results)\n})\n<\/code><\/pre>\n<h4><a href=\"#get\" id=\"get\" name=\"get\" class=\"anchor\">Anchor link<\/a> <a href=\"#get\">get<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">Retrieves documents from the database. Unlike <a href=\"#find\">find<\/a>, it runs any <code>beforeGet<\/code> and <code>afterGet<\/code> hooks configured in the collection.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Receives<\/em><\/strong> <em>(named parameters):<\/em><\/p>\n<ul>\n<li><code>query<\/code> (type: <code>Object<\/code>): Query to match documents against<\/li>\n<li><code>options<\/code> (type: <code>Object<\/code>, optional): Options object for narrowing down the result set (e.g. <code>{page: 3}<\/code>)<\/li>\n<li><code>req<\/code> (type: <code>Object<\/code>, optional): The instance of <a href=\"https:\/\/nodejs.org\/api\/http.html#http_class_http_incomingmessage\">http.IncomingMessage<\/a> that originated the request<\/li>\n<\/ul>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Returns:<\/em><\/strong><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><code>Promise<\/code> with:<\/p>\n<ul>\n<li><code>{metadata, results}<\/code> (<code>Object<\/code>): Object representing the documents retrieved (<code>results<\/code>) as well as a metadata block indicating various types of metrics about the result set (<code>metadata<\/code>)<\/li>\n<\/ul>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Example:<\/em><\/strong><\/p>\n<pre><code class=\"lang-js\">const Model = <span class=\"hljs-built_in\">require<\/span>(<span class=\"hljs-string\">'@dadi\/api'<\/span>).Model\nModel(<span class=\"hljs-string\">'books'<\/span>).get({\n  options: {\n    limit: <span class=\"hljs-number\">10<\/span>,\n    skip: <span class=\"hljs-number\">5<\/span>\n  }\n  query: {\n    title: <span class=\"hljs-string\">'Harry Potter'<\/span>\n  },\n  req\n}).<span class=\"hljs-keyword\">then<\/span>(<span class=\"hljs-function\"><span class=\"hljs-params\">({metadata, results})<\/span> =&gt;<\/span> {\n  <span class=\"hljs-built_in\">console<\/span>.log(results)\n})\n<\/code><\/pre>\n<h4><a href=\"#getindexes\" id=\"getindexes\" name=\"getindexes\" class=\"anchor\">Anchor link<\/a> <a href=\"#getindexes\">getIndexes<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">Retrieves all indexed fields.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Receives:<\/em><\/strong><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>N\/A<\/em><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Returns:<\/em><\/strong><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><code>Promise<\/code> with:<\/p>\n<ul>\n<li><code>indexes<\/code> (<code>Array<\/code>): An array of index objects, each with a name property<\/li>\n<\/ul>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Example:<\/em><\/strong><\/p>\n<pre><code class=\"lang-js\">const <span class=\"hljs-keyword\">Model<\/span> = require(<span class=\"hljs-string\">'@dadi\/api'<\/span>).<span class=\"hljs-keyword\">Model<\/span>\n<span class=\"hljs-keyword\">Model<\/span>(<span class=\"hljs-string\">'books'<\/span>).getIndexes().<span class=\"hljs-keyword\">then<\/span>(indexes =&gt; {\n  console.<span class=\"hljs-built-in\">log<\/span>(indexes)\n})\n<\/code><\/pre>\n<h4><a href=\"#getversions\" id=\"getversions\" name=\"getversions\" class=\"anchor\">Anchor link<\/a> <a href=\"#getversions\">getVersions<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">Retrieves all past revisions of a document.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Receives<\/em><\/strong> <em>(named parameters):<\/em><\/p>\n<ul>\n<li><code>documentId<\/code> (type: <code>String<\/code>): ID of the document<\/li>\n<\/ul>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Returns:<\/em><\/strong><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><code>Promise<\/code> with:<\/p>\n<ul>\n<li><code>results<\/code> (<code>Array<\/code>): The revision documents<\/li>\n<\/ul>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Example:<\/em><\/strong><\/p>\n<pre><code class=\"lang-js\">const <span class=\"hljs-keyword\">Model<\/span> = require(<span class=\"hljs-string\">'@dadi\/api'<\/span>).<span class=\"hljs-keyword\">Model<\/span>\n<span class=\"hljs-keyword\">Model<\/span>(<span class=\"hljs-string\">'books'<\/span>).getVersions({\n  documentId: <span class=\"hljs-string\">'560a44b33a4d7de29f168ce4'<\/span>\n}).<span class=\"hljs-keyword\">then<\/span>(results =&gt; {\n  console.<span class=\"hljs-built-in\">log<\/span>(results)\n})\n<\/code><\/pre>\n<h4><a href=\"#getstats\" id=\"getstats\" name=\"getstats\" class=\"anchor\">Anchor link<\/a> <a href=\"#getstats\">getStats<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">Retrieves statistics about a given collection.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Receives<\/em><\/strong> <em>(named parameters):<\/em><\/p>\n<ul>\n<li><code>options<\/code> (type: <code>Object<\/code>, optional): Options object for narrowing down the result set<\/li>\n<\/ul>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Returns:<\/em><\/strong><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><code>Promise<\/code> with:<\/p>\n<ul>\n<li><code>stats<\/code> (<code>Object<\/code>): Collection statistics<\/li>\n<\/ul>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Example:<\/em><\/strong><\/p>\n<pre><code class=\"lang-js\">const <span class=\"hljs-keyword\">Model<\/span> = require(<span class=\"hljs-string\">'@dadi\/api'<\/span>).<span class=\"hljs-keyword\">Model<\/span>\n<span class=\"hljs-keyword\">Model<\/span>(<span class=\"hljs-string\">'books'<\/span>).getStats().<span class=\"hljs-keyword\">then<\/span>(stats =&gt; {\n  console.<span class=\"hljs-built-in\">log<\/span>(stats)\n})\n<\/code><\/pre>\n<h4><a href=\"#update\" id=\"update\" name=\"update\" class=\"anchor\">Anchor link<\/a> <a href=\"#update\">update<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">Updates documents in the database. Runs any <code>beforeUpdate<\/code> and <code>afterUpdate<\/code> hooks configured in the collection.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Receives<\/em><\/strong> <em>(named parameters):<\/em><\/p>\n<ul>\n<li><code>compose<\/code> (type: <code>Boolean<\/code>, default: <code>true<\/code>): Whether to resolved referenced documents in the output payload<\/li>\n<li><code>query<\/code> (type: <code>Object<\/code>): Query to match documents against<\/li>\n<li><code>update<\/code> (type: <code>Object<\/code>): Set of properties and values to update the documents affected by the query<\/li>\n<li><code>internals<\/code> (type: <code>Object<\/code>): A set of internal properties to add to each document<\/li>\n<li><code>rawOutput<\/code> (type: <code>Boolean<\/code>, default: <code>false<\/code>): By default, results suffer a series of transformations before being sent back to the consumer. The raw output can be obtained by setting this property to <code>true<\/code><\/li>\n<li><code>req<\/code> (type: <code>Object<\/code>, optional): The instance of <a href=\"https:\/\/nodejs.org\/api\/http.html#http_class_http_incomingmessage\">http.IncomingMessage<\/a> that originated the request<\/li>\n<\/ul>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Returns:<\/em><\/strong><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><code>Promise<\/code> with:<\/p>\n<ul>\n<li><code>{results}<\/code> (<code>Object<\/code>): Object with a <code>results<\/code> property containing the array of updated documents with their new state<\/li>\n<\/ul>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><em>Example:<\/em><\/strong><\/p>\n<pre><code class=\"lang-js\">const Model = require(<span class=\"hljs-string\">'@dadi\/api'<\/span>).Model\nModel(<span class=\"hljs-string\">'books'<\/span>).<span class=\"hljs-keyword\">update<\/span>({\n  internals: {\n    _lastModifiedBy: <span class=\"hljs-string\">'johnDoe'<\/span>\n  },\n  query: {\n    title: <span class=\"hljs-string\">'Harry Potter'<\/span>\n  },\n  req,\n  update: {\n    author: <span class=\"hljs-string\">'J K Rowling'<\/span>\n  }\n}).<span class=\"hljs-keyword\">then<\/span>(({results}) =&gt; {\n  console.log(results)\n})\n<\/code><\/pre>\n<h2><a href=\"#validating-data\" id=\"validating-data\" name=\"validating-data\" class=\"anchor\">Anchor link<\/a> <a href=\"#validating-data\">Validating data<\/a><\/h2>\n<p class=\"7xtjw4dqwy5mz7w3j\">Documents sent to the API as part of create or update requests are validated against the rules defined in the <a href=\"#collection-schemas\">collection schemas<\/a>.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">The most basic validation operators work across all fields and are used to ensure that values sent to API have the correct data type and that mandatory fields are not left blank. On top of those, DADI API includes other operators that only work with certain field types. These are defined in a <code>validation<\/code> block within the field schema.<\/p>\n<blockquote class=\"advice\">\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Validation outside of DADI API<\/strong><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">All the logic for validating the various field types is available via the <a href=\"https:\/\/github.com\/dadi\/api-validator\">@dadi\/api-validator<\/a> npm module. This allows you to validate documents in any application that interacts with DADI API without even sending data to API.<\/p>\n<\/blockquote>\n<h3><a href=\"#data-type-validation\" id=\"data-type-validation\" name=\"data-type-validation\" class=\"anchor\">Anchor link<\/a> <a href=\"#data-type-validation\">Data type validation<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">When validating a document, API will always check that the value submitted for each field is compatible with the type defined in the schema. It&#39;s not possible to disable this type of validation.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">The <code>type<\/code> property must contain a string that matches one of the <a href=\"#field-types\">field types<\/a> supported by DADI API.<\/p>\n<pre><code class=\"lang-json\"><span class=\"hljs-string\">\"fields\"<\/span>: {\n  <span class=\"hljs-string\">\"title\"<\/span>: {\n    <span class=\"hljs-string\">\"type\"<\/span>: <span class=\"hljs-string\">\"String\"<\/span>\n  },\n  <span class=\"hljs-string\">\"dateOfBirth\"<\/span>: {\n    <span class=\"hljs-string\">\"type\"<\/span>: <span class=\"hljs-string\">\"DateTime\"<\/span>\n  },\n  <span class=\"hljs-string\">\"isAdministrator\"<\/span>: {\n    <span class=\"hljs-string\">\"type\"<\/span>: <span class=\"hljs-string\">\"Boolean\"<\/span>\n  }\n}\n<\/code><\/pre>\n<h3><a href=\"#mandatory-field-validation\" id=\"mandatory-field-validation\" name=\"mandatory-field-validation\" class=\"anchor\">Anchor link<\/a> <a href=\"#mandatory-field-validation\">Mandatory field validation<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">Fields can be made mandatory by setting their <code>required<\/code> property to <code>true<\/code>. DADI API will check that a value has been supplied for the field when creating new documents. Mandatory fields are not validated on update requests, as they would have already been populated with data when the document was first created.<\/p>\n<pre><code class=\"lang-json\"><span class=\"hljs-string\">\"fields\"<\/span>: {\n  <span class=\"hljs-string\">\"title\"<\/span>: {\n    <span class=\"hljs-string\">\"type\"<\/span>: <span class=\"hljs-string\">\"String\"<\/span>,\n    <span class=\"hljs-string\">\"required\"<\/span>: true\n  }\n}\n<\/code><\/pre>\n<h3><a href=\"#datetime-validation\" id=\"datetime-validation\" name=\"datetime-validation\" class=\"anchor\">Anchor link<\/a> <a href=\"#datetime-validation\"><code>DateTime<\/code> validation<\/a><\/h3>\n<ul>\n<li><a href=\"#after\">after<\/a><\/li>\n<li><a href=\"#before\">before<\/a><\/li>\n<li><a href=\"#dynamic-values\">Dynamic values<\/a><\/li>\n<\/ul>\n<h4><a href=\"#after\" id=\"after\" name=\"after\" class=\"anchor\">Anchor link<\/a> <a href=\"#after\"><code>after<\/code><\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">When the <code>after<\/code> validation operator is defined, validation will fail if the supplied value represents a date prior to the one defined.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>Schema:<\/em><\/p>\n<pre><code class=\"lang-json\"><span class=\"hljs-string\">\"fields\"<\/span>: {\n  <span class=\"hljs-string\">\"dateOfBirth\"<\/span>: {\n    <span class=\"hljs-string\">\"type\"<\/span>: <span class=\"hljs-string\">\"DateTime\"<\/span>,\n    <span class=\"hljs-string\">\"format\"<\/span>: <span class=\"hljs-string\">\"YYYY-MM-DD\"<\/span>,\n    <span class=\"hljs-string\">\"validation\"<\/span>: {\n      <span class=\"hljs-string\">\"after\"<\/span>: <span class=\"hljs-string\">\"2018-10-30\"<\/span>\n    }\n  }\n}\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>Sample response:<\/em><\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"success\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n  <span class=\"hljs-attr\">\"errors\"<\/span>: [\n    {\n      <span class=\"hljs-attr\">\"field\"<\/span>: <span class=\"hljs-string\">\"dateOfBirth\"<\/span>,\n      <span class=\"hljs-attr\">\"code\"<\/span>: <span class=\"hljs-string\">\"ERROR_AFTER\"<\/span>,\n      <span class=\"hljs-attr\">\"message\"<\/span>: <span class=\"hljs-string\">\"is prior to 2018-10-30\"<\/span>\n    }\n  ]\n}\n<\/code><\/pre>\n<h4><a href=\"#before\" id=\"before\" name=\"before\" class=\"anchor\">Anchor link<\/a> <a href=\"#before\"><code>before<\/code><\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">When the <code>before<\/code> validation operator is defined, validation will fail if the supplied value represents a date after the one defined.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>Schema:<\/em><\/p>\n<pre><code class=\"lang-json\"><span class=\"hljs-string\">\"fields\"<\/span>: {\n  <span class=\"hljs-string\">\"dateOfBirth\"<\/span>: {\n    <span class=\"hljs-string\">\"type\"<\/span>: <span class=\"hljs-string\">\"DateTime\"<\/span>,\n    <span class=\"hljs-string\">\"format\"<\/span>: <span class=\"hljs-string\">\"YYYY-MM-DD\"<\/span>,\n    <span class=\"hljs-string\">\"validation\"<\/span>: {\n      <span class=\"hljs-string\">\"before\"<\/span>: <span class=\"hljs-string\">\"2018-10-30\"<\/span>\n    }\n  }\n}\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>Sample response:<\/em><\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"success\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n  <span class=\"hljs-attr\">\"errors\"<\/span>: [\n    {\n      <span class=\"hljs-attr\">\"field\"<\/span>: <span class=\"hljs-string\">\"dateOfBirth\"<\/span>,\n      <span class=\"hljs-attr\">\"code\"<\/span>: <span class=\"hljs-string\">\"ERROR_AFTER\"<\/span>,\n      <span class=\"hljs-attr\">\"message\"<\/span>: <span class=\"hljs-string\">\"is after 2018-10-30\"<\/span>\n    }\n  ]\n}\n<\/code><\/pre>\n<h4><a href=\"#dynamic-values\" id=\"dynamic-values\" name=\"dynamic-values\" class=\"anchor\">Anchor link<\/a> <a href=\"#dynamic-values\">Dynamic values<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">When defining validation rules for fields of type <code>DateTime<\/code>, the following placeholders will be dynamically replaced by API:<\/p>\n<ul>\n<li>\n<p class=\"7xtjw4dqwy5mz7w3j\"><code>$now<\/code>: Replaced by the current date at the time of the request<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">  <em>Schema:<\/em><\/p>\n<pre><code class=\"lang-json\">  <span class=\"hljs-string\">\"fields\"<\/span>: {\n    <span class=\"hljs-string\">\"pastDate\"<\/span>: {\n      <span class=\"hljs-string\">\"type\"<\/span>: <span class=\"hljs-string\">\"DateTime\"<\/span>,\n      <span class=\"hljs-string\">\"validation\"<\/span>: {\n        <span class=\"hljs-string\">\"before\"<\/span>: <span class=\"hljs-string\">\"$now\"<\/span>\n      }\n    },\n    <span class=\"hljs-string\">\"futureDate\"<\/span>: {\n      <span class=\"hljs-string\">\"type\"<\/span>: <span class=\"hljs-string\">\"DateTime\"<\/span>,\n      <span class=\"hljs-string\">\"validation\"<\/span>: {\n        <span class=\"hljs-string\">\"after\"<\/span>: <span class=\"hljs-string\">\"$now\"<\/span>\n      }\n    }\n  }\n<\/code><\/pre>\n<\/li>\n<\/ul>\n<h3><a href=\"#media-validation\" id=\"media-validation\" name=\"media-validation\" class=\"anchor\">Anchor link<\/a> <a href=\"#media-validation\"><code>Media<\/code> validation<\/a><\/h3>\n<ul>\n<li><a href=\"#mimetypes\">mimeTypes<\/a><\/li>\n<\/ul>\n<h4><a href=\"#mimetypes\" id=\"mimetypes\" name=\"mimetypes\" class=\"anchor\">Anchor link<\/a> <a href=\"#mimetypes\"><code>mimeTypes<\/code><\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">When the <code>mimeTypes<\/code> validation operator is defined, its should contain an array of accepted MIME types for referenced media objects. Validation will fail if the supplied value does not correspond to the ID of a valid media object with an accepted MIME type.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>Schema:<\/em><\/p>\n<pre><code class=\"lang-json\"><span class=\"hljs-string\">\"fields\"<\/span>: {\n  <span class=\"hljs-string\">\"profileImage\"<\/span>: {\n    <span class=\"hljs-string\">\"type\"<\/span>: <span class=\"hljs-string\">\"Media\"<\/span>,\n    <span class=\"hljs-string\">\"validation\"<\/span>: {\n      <span class=\"hljs-string\">\"mimeTypes\"<\/span>: [<span class=\"hljs-string\">\"image\/jpeg\"<\/span>, <span class=\"hljs-string\">\"image\/png\"<\/span>]\n    }\n  }\n}\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>Sample response:<\/em><\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"success\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n  <span class=\"hljs-attr\">\"errors\"<\/span>: [\n    {\n      <span class=\"hljs-attr\">\"field\"<\/span>: <span class=\"hljs-string\">\"profileImage\"<\/span>,\n      <span class=\"hljs-attr\">\"code\"<\/span>: <span class=\"hljs-string\">\"ERROR_INVALID_MIME_TYPE\"<\/span>,\n      <span class=\"hljs-attr\">\"message\"<\/span>: <span class=\"hljs-string\">\"has invalid MIME type. Expected: image\/jpeg, image\/png\"<\/span>\n    }\n  ]\n}\n<\/code><\/pre>\n<h3><a href=\"#number-validation\" id=\"number-validation\" name=\"number-validation\" class=\"anchor\">Anchor link<\/a> <a href=\"#number-validation\"><code>Number<\/code> validation<\/a><\/h3>\n<ul>\n<li><a href=\"#equalto\">equalTo<\/a><\/li>\n<li><a href=\"#even\">even<\/a><\/li>\n<li><a href=\"#greaterthan\">greaterThan<\/a><\/li>\n<li><a href=\"#greaterthanorqualto\">greaterThanOrEqualTo<\/a><\/li>\n<li><a href=\"#integer\">integer<\/a><\/li>\n<li><a href=\"#lessthan\">lessThan<\/a><\/li>\n<li><a href=\"#lessthanorequalto\">lessThanOrEqualTo<\/a><\/li>\n<\/ul>\n<h4><a href=\"#equalto\" id=\"equalto\" name=\"equalto\" class=\"anchor\">Anchor link<\/a> <a href=\"#equalto\"><code>equalTo<\/code><\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">When the <code>equalTo<\/code> validation operator is defined, validation will fail if the candidate value is not equal to the value specified.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>Schema:<\/em><\/p>\n<pre><code class=\"lang-json\"><span class=\"hljs-string\">\"fields\"<\/span>: {\n  <span class=\"hljs-string\">\"linesOfCode\"<\/span>: {\n    <span class=\"hljs-string\">\"type\"<\/span>: <span class=\"hljs-string\">\"Number\"<\/span>,\n    <span class=\"hljs-string\">\"validation\"<\/span>: {\n      <span class=\"hljs-string\">\"equalTo\"<\/span>: <span class=\"hljs-number\">500<\/span>\n    }\n  }\n}\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>Sample response:<\/em><\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"success\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n  <span class=\"hljs-attr\">\"errors\"<\/span>: [\n    {\n      <span class=\"hljs-attr\">\"field\"<\/span>: <span class=\"hljs-string\">\"linesOfCode\"<\/span>,\n      <span class=\"hljs-attr\">\"code\"<\/span>: <span class=\"hljs-string\">\"ERROR_EQUAL_TO\"<\/span>,\n      <span class=\"hljs-attr\">\"message\"<\/span>: <span class=\"hljs-string\">\"is not equal to 500\"<\/span>\n    }\n  ]\n}\n<\/code><\/pre>\n<h4><a href=\"#even\" id=\"even\" name=\"even\" class=\"anchor\">Anchor link<\/a> <a href=\"#even\"><code>even<\/code><\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">The <code>even<\/code> validation operator looks at the parity of candidate values. If <code>even<\/code> is set to <code>true<\/code>, validation will fail if the candidate value is odd. Conversely, if <code>even<\/code> is set to <code>false<\/code>, validation will fail if the candidate value is even.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>Schema:<\/em><\/p>\n<pre><code class=\"lang-json\"><span class=\"hljs-string\">\"fields\"<\/span>: {\n  <span class=\"hljs-string\">\"evenSteven\"<\/span>: {\n    <span class=\"hljs-string\">\"type\"<\/span>: <span class=\"hljs-string\">\"Number\"<\/span>,\n    <span class=\"hljs-string\">\"validation\"<\/span>: {\n      <span class=\"hljs-string\">\"even\"<\/span>: true\n    }\n  },\n  <span class=\"hljs-string\">\"oddBall\"<\/span>: {\n    <span class=\"hljs-string\">\"type\"<\/span>: <span class=\"hljs-string\">\"Number\"<\/span>,\n    <span class=\"hljs-string\">\"validation\"<\/span>: {\n      <span class=\"hljs-string\">\"even\"<\/span>: false\n    }\n  }\n}\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>Sample response:<\/em><\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"success\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n  <span class=\"hljs-attr\">\"errors\"<\/span>: [\n    {\n      <span class=\"hljs-attr\">\"field\"<\/span>: <span class=\"hljs-string\">\"evenSteven\"<\/span>,\n      <span class=\"hljs-attr\">\"code\"<\/span>: <span class=\"hljs-string\">\"ERROR_EVEN\"<\/span>,\n      <span class=\"hljs-attr\">\"message\"<\/span>: <span class=\"hljs-string\">\"is not even\"<\/span>\n    },\n    {\n      <span class=\"hljs-attr\">\"field\"<\/span>: <span class=\"hljs-string\">\"oddBall\"<\/span>,\n      <span class=\"hljs-attr\">\"code\"<\/span>: <span class=\"hljs-string\">\"ERROR_ODD\"<\/span>,\n      <span class=\"hljs-attr\">\"message\"<\/span>: <span class=\"hljs-string\">\"is not odd\"<\/span>\n    }\n  ]\n}\n<\/code><\/pre>\n<h4><a href=\"#greaterthan\" id=\"greaterthan\" name=\"greaterthan\" class=\"anchor\">Anchor link<\/a> <a href=\"#greaterthan\"><code>greaterThan<\/code><\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">When the <code>greaterThan<\/code> validation operator is defined, validation will fail if the candidate value is not greater than the value specified.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>Schema:<\/em><\/p>\n<pre><code class=\"lang-json\"><span class=\"hljs-string\">\"fields\"<\/span>: {\n  <span class=\"hljs-string\">\"linesOfCode\"<\/span>: {\n    <span class=\"hljs-string\">\"type\"<\/span>: <span class=\"hljs-string\">\"Number\"<\/span>,\n    <span class=\"hljs-string\">\"validation\"<\/span>: {\n      <span class=\"hljs-string\">\"greaterThan\"<\/span>: <span class=\"hljs-number\">500<\/span>\n    }\n  }\n}\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>Sample response:<\/em><\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"success\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n  <span class=\"hljs-attr\">\"errors\"<\/span>: [\n    {\n      <span class=\"hljs-attr\">\"field\"<\/span>: <span class=\"hljs-string\">\"linesOfCode\"<\/span>,\n      <span class=\"hljs-attr\">\"code\"<\/span>: <span class=\"hljs-string\">\"ERROR_GREATER_THAN\"<\/span>,\n      <span class=\"hljs-attr\">\"message\"<\/span>: <span class=\"hljs-string\">\"is not greater than 500\"<\/span>\n    }\n  ]\n}\n<\/code><\/pre>\n<h4><a href=\"#greaterthanorequalto\" id=\"greaterthanorequalto\" name=\"greaterthanorequalto\" class=\"anchor\">Anchor link<\/a> <a href=\"#greaterthanorequalto\"><code>greaterThanOrEqualTo<\/code><\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">When the <code>greaterThanOrEqualTo<\/code> validation operator is defined, validation will fail if the candidate value is not greater than or equal to the value specified.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>Schema:<\/em><\/p>\n<pre><code class=\"lang-json\"><span class=\"hljs-string\">\"fields\"<\/span>: {\n  <span class=\"hljs-string\">\"linesOfCode\"<\/span>: {\n    <span class=\"hljs-string\">\"type\"<\/span>: <span class=\"hljs-string\">\"Number\"<\/span>,\n    <span class=\"hljs-string\">\"validation\"<\/span>: {\n      <span class=\"hljs-string\">\"greaterThanOrEqualTo\"<\/span>: <span class=\"hljs-number\">500<\/span>\n    }\n  }\n}\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>Sample response:<\/em><\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"success\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n  <span class=\"hljs-attr\">\"errors\"<\/span>: [\n    {\n      <span class=\"hljs-attr\">\"field\"<\/span>: <span class=\"hljs-string\">\"linesOfCode\"<\/span>,\n      <span class=\"hljs-attr\">\"code\"<\/span>: <span class=\"hljs-string\">\"ERROR_GREATER_THAN_OR_EQUAL_TO\"<\/span>,\n      <span class=\"hljs-attr\">\"message\"<\/span>: <span class=\"hljs-string\">\"is not greater than or equal to 500\"<\/span>\n    }\n  ]\n}\n<\/code><\/pre>\n<h4><a href=\"#integer\" id=\"integer\" name=\"integer\" class=\"anchor\">Anchor link<\/a> <a href=\"#integer\"><code>integer<\/code><\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">The <code>integer<\/code> validation operator looks at the existence of a fractional component in the candidate value. If <code>integer<\/code> is set to <code>true<\/code>, validation will fail if the candidate value is not an integer. Conversely, if <code>integer<\/code> is set to <code>false<\/code>, validation will fail if the candidate value is an integer.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>Schema:<\/em><\/p>\n<pre><code class=\"lang-json\"><span class=\"hljs-string\">\"fields\"<\/span>: {\n  <span class=\"hljs-string\">\"wholeGrain\"<\/span>: {\n    <span class=\"hljs-string\">\"type\"<\/span>: <span class=\"hljs-string\">\"Number\"<\/span>,\n    <span class=\"hljs-string\">\"validation\"<\/span>: {\n      <span class=\"hljs-string\">\"integer\"<\/span>: true\n    }\n  },\n  <span class=\"hljs-string\">\"floatingDevice\"<\/span>: {\n    <span class=\"hljs-string\">\"type\"<\/span>: <span class=\"hljs-string\">\"Number\"<\/span>,\n    <span class=\"hljs-string\">\"validation\"<\/span>: {\n      <span class=\"hljs-string\">\"integer\"<\/span>: false\n    }\n  }\n}\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>Sample response:<\/em><\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"success\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n  <span class=\"hljs-attr\">\"errors\"<\/span>: [\n    {\n      <span class=\"hljs-attr\">\"field\"<\/span>: <span class=\"hljs-string\">\"wholeGrain\"<\/span>,\n      <span class=\"hljs-attr\">\"code\"<\/span>: <span class=\"hljs-string\">\"ERROR_NOT_INTEGER\"<\/span>,\n      <span class=\"hljs-attr\">\"message\"<\/span>: <span class=\"hljs-string\">\"is not integer\"<\/span>\n    },\n    {\n      <span class=\"hljs-attr\">\"field\"<\/span>: <span class=\"hljs-string\">\"floatingDevice\"<\/span>,\n      <span class=\"hljs-attr\">\"code\"<\/span>: <span class=\"hljs-string\">\"ERROR_INTEGER\"<\/span>,\n      <span class=\"hljs-attr\">\"message\"<\/span>: <span class=\"hljs-string\">\"is integer\"<\/span>\n    }\n  ]\n}\n<\/code><\/pre>\n<h4><a href=\"#lessthan\" id=\"lessthan\" name=\"lessthan\" class=\"anchor\">Anchor link<\/a> <a href=\"#lessthan\"><code>lessThan<\/code><\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">When the <code>lessThan<\/code> validation operator is defined, validation will fail if the candidate value is not less than the value specified.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>Schema:<\/em><\/p>\n<pre><code class=\"lang-json\"><span class=\"hljs-string\">\"fields\"<\/span>: {\n  <span class=\"hljs-string\">\"linesOfCode\"<\/span>: {\n    <span class=\"hljs-string\">\"type\"<\/span>: <span class=\"hljs-string\">\"Number\"<\/span>,\n    <span class=\"hljs-string\">\"validation\"<\/span>: {\n      <span class=\"hljs-string\">\"lessThan\"<\/span>: <span class=\"hljs-number\">500<\/span>\n    }\n  }\n}\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>Sample response:<\/em><\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"success\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n  <span class=\"hljs-attr\">\"errors\"<\/span>: [\n    {\n      <span class=\"hljs-attr\">\"field\"<\/span>: <span class=\"hljs-string\">\"linesOfCode\"<\/span>,\n      <span class=\"hljs-attr\">\"code\"<\/span>: <span class=\"hljs-string\">\"ERROR_LESS_THAN\"<\/span>,\n      <span class=\"hljs-attr\">\"message\"<\/span>: <span class=\"hljs-string\">\"is not less than 500\"<\/span>\n    }\n  ]\n}\n<\/code><\/pre>\n<h4><a href=\"#lessthanorequalto\" id=\"lessthanorequalto\" name=\"lessthanorequalto\" class=\"anchor\">Anchor link<\/a> <a href=\"#lessthanorequalto\"><code>lessThanOrEqualTo<\/code><\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">When the <code>lessThanOrEqualTo<\/code> validation operator is defined, validation will fail if the candidate value is not less than or equal to the value specified.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>Schema:<\/em><\/p>\n<pre><code class=\"lang-json\"><span class=\"hljs-string\">\"fields\"<\/span>: {\n  <span class=\"hljs-string\">\"linesOfCode\"<\/span>: {\n    <span class=\"hljs-string\">\"type\"<\/span>: <span class=\"hljs-string\">\"Number\"<\/span>,\n    <span class=\"hljs-string\">\"validation\"<\/span>: {\n      <span class=\"hljs-string\">\"lessThanOrEqualTo\"<\/span>: <span class=\"hljs-number\">500<\/span>\n    }\n  }\n}\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>Sample response:<\/em><\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"success\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n  <span class=\"hljs-attr\">\"errors\"<\/span>: [\n    {\n      <span class=\"hljs-attr\">\"field\"<\/span>: <span class=\"hljs-string\">\"linesOfCode\"<\/span>,\n      <span class=\"hljs-attr\">\"code\"<\/span>: <span class=\"hljs-string\">\"ERROR_LESS_THAN_OR_EQUAL_TO\"<\/span>,\n      <span class=\"hljs-attr\">\"message\"<\/span>: <span class=\"hljs-string\">\"is not less than or equal to 500\"<\/span>\n    }\n  ]\n}\n<\/code><\/pre>\n<h3><a href=\"#string-validation\" id=\"string-validation\" name=\"string-validation\" class=\"anchor\">Anchor link<\/a> <a href=\"#string-validation\"><code>String<\/code> validation<\/a><\/h3>\n<ul>\n<li><a href=\"#maxlength\">maxLength<\/a><\/li>\n<li><a href=\"#minlength\">minLength<\/a><\/li>\n<li><a href=\"#regex\">regex<\/a> <\/li>\n<\/ul>\n<h4><a href=\"#maxlength\" id=\"maxlength\" name=\"maxlength\" class=\"anchor\">Anchor link<\/a> <a href=\"#maxlength\"><code>maxLength<\/code><\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">When the <code>maxLength<\/code> validation operator is defined, validation will fail if the length of the candidate value is less than the specified limit.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>Schema:<\/em><\/p>\n<pre><code class=\"lang-json\"><span class=\"hljs-string\">\"fields\"<\/span>: {\n  <span class=\"hljs-string\">\"username\"<\/span>: {\n    <span class=\"hljs-string\">\"type\"<\/span>: <span class=\"hljs-string\">\"String\"<\/span>,\n    <span class=\"hljs-string\">\"validation\"<\/span>: {\n      <span class=\"hljs-string\">\"maxLength\"<\/span>: <span class=\"hljs-number\">16<\/span>\n    }\n  }\n}\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>Sample response:<\/em><\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"success\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n  <span class=\"hljs-attr\">\"errors\"<\/span>: [\n    {\n      <span class=\"hljs-attr\">\"field\"<\/span>: <span class=\"hljs-string\">\"username\"<\/span>,\n      <span class=\"hljs-attr\">\"code\"<\/span>: <span class=\"hljs-string\">\"ERROR_MAX_LENGTH\"<\/span>,\n      <span class=\"hljs-attr\">\"message\"<\/span>: <span class=\"hljs-string\">\"is too long\"<\/span>\n    }\n  ]\n}\n<\/code><\/pre>\n<h4><a href=\"#minlength\" id=\"minlength\" name=\"minlength\" class=\"anchor\">Anchor link<\/a> <a href=\"#minlength\"><code>minLength<\/code><\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">When the <code>minLength<\/code> validation operator is defined, validation will fail if the length of the candidate value is greater than the specified limit.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>Schema:<\/em><\/p>\n<pre><code class=\"lang-json\"><span class=\"hljs-string\">\"fields\"<\/span>: {\n  <span class=\"hljs-string\">\"username\"<\/span>: {\n    <span class=\"hljs-string\">\"type\"<\/span>: <span class=\"hljs-string\">\"String\"<\/span>,\n    <span class=\"hljs-string\">\"validation\"<\/span>: {\n      <span class=\"hljs-string\">\"minLength\"<\/span>: <span class=\"hljs-number\">6<\/span>\n    }\n  }\n}\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>Sample response:<\/em><\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"success\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n  <span class=\"hljs-attr\">\"errors\"<\/span>: [\n    {\n      <span class=\"hljs-attr\">\"field\"<\/span>: <span class=\"hljs-string\">\"username\"<\/span>,\n      <span class=\"hljs-attr\">\"code\"<\/span>: <span class=\"hljs-string\">\"ERROR_MIN_LENGTH\"<\/span>,\n      <span class=\"hljs-attr\">\"message\"<\/span>: <span class=\"hljs-string\">\"is too short\"<\/span>\n    }\n  ]\n}\n<\/code><\/pre>\n<h4><a href=\"#regex\" id=\"regex\" name=\"regex\" class=\"anchor\">Anchor link<\/a> <a href=\"#regex\"><code>regex<\/code><\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">When the <code>regex<\/code> validation operator is defined, validation will fail if the candidate value doesn&#39;t match the pattern defined.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>Schema:<\/em><\/p>\n<pre><code class=\"lang-json\"><span class=\"hljs-string\">\"fields\"<\/span>: {\n  <span class=\"hljs-string\">\"username\"<\/span>: {\n    <span class=\"hljs-string\">\"type\"<\/span>: <span class=\"hljs-string\">\"String\"<\/span>,\n    <span class=\"hljs-string\">\"validation\"<\/span>: {\n      <span class=\"hljs-string\">\"regex\"<\/span>: {\n        <span class=\"hljs-string\">\"pattern\"<\/span>: <span class=\"hljs-string\">\"^A\"<\/span>\n      }\n    }\n  }\n}\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>Sample response:<\/em><\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"success\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n  <span class=\"hljs-attr\">\"errors\"<\/span>: [\n    {\n      <span class=\"hljs-attr\">\"field\"<\/span>: <span class=\"hljs-string\">\"username\"<\/span>,\n      <span class=\"hljs-attr\">\"code\"<\/span>: <span class=\"hljs-string\">\"ERROR_REGEX\"<\/span>,\n      <span class=\"hljs-attr\">\"message\"<\/span>: <span class=\"hljs-string\">\"should match the pattern ^A\"<\/span>\n    }\n  ]\n}\n<\/code><\/pre>\n<h3><a href=\"#failed-validation-response\" id=\"failed-validation-response\" name=\"failed-validation-response\" class=\"anchor\">Anchor link<\/a> <a href=\"#failed-validation-response\">Failed validation response<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">If a document fails validation, an errors array will be returned indicating which fields have failed validation, along with a machine-readable error code and a human-friendly error message.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">Each validation operator will generate its own default error message, but it&#39;s also possible to customise error messages on a per-field basis using the <code>message<\/code> property within the <code>validation<\/code> block.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>Schema:<\/em><\/p>\n<pre><code class=\"lang-json\"><span class=\"hljs-string\">\"fields\"<\/span>: {\n  <span class=\"hljs-string\">\"username\"<\/span>: {\n    <span class=\"hljs-string\">\"type\"<\/span>: <span class=\"hljs-string\">\"String\"<\/span>,\n    <span class=\"hljs-string\">\"validation\"<\/span>: {\n      <span class=\"hljs-string\">\"message\"<\/span>: <span class=\"hljs-string\">\"must start with an A\"<\/span>,\n      <span class=\"hljs-string\">\"regex\"<\/span>: {\n        <span class=\"hljs-string\">\"pattern\"<\/span>: <span class=\"hljs-string\">\"^A\"<\/span>\n      }\n    }\n  },\n  <span class=\"hljs-string\">\"linesOfCode\"<\/span>: {\n    <span class=\"hljs-string\">\"type\"<\/span>: <span class=\"hljs-string\">\"Number\"<\/span>,\n    <span class=\"hljs-string\">\"validation\"<\/span>: {\n      <span class=\"hljs-string\">\"lessThanOrEqualTo\"<\/span>: <span class=\"hljs-number\">500<\/span>\n    }\n  }\n}\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>Sample response:<\/em><\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"success\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n  <span class=\"hljs-attr\">\"errors\"<\/span>: [\n    {\n      <span class=\"hljs-attr\">\"field\"<\/span>: <span class=\"hljs-string\">\"username\"<\/span>,\n      <span class=\"hljs-attr\">\"code\"<\/span>: <span class=\"hljs-string\">\"ERROR_REGEX\"<\/span>,\n      <span class=\"hljs-attr\">\"message\"<\/span>: <span class=\"hljs-string\">\"should match the pattern ^A\"<\/span>\n    }\n  ]\n}\n<\/code><\/pre>\n<pre><code class=\"lang-http\">HTTP\/1.1 <span class=\"hljs-number\">400<\/span> Bad Request\n<span class=\"hljs-attribute\">Content-Type<\/span>: application\/json\n<span class=\"json\">{\n  <span class=\"hljs-attr\">\"success\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n  <span class=\"hljs-attr\">\"errors\"<\/span>: [\n    {\n      <span class=\"hljs-attr\">\"field\"<\/span>: <span class=\"hljs-string\">\"username\"<\/span>,\n      <span class=\"hljs-attr\">\"code\"<\/span>: <span class=\"hljs-string\">\"ERROR_REGEX\"<\/span>,\n      <span class=\"hljs-attr\">\"message\"<\/span>: <span class=\"hljs-string\">\"must start with an A\"<\/span>\n    },\n    {\n      <span class=\"hljs-attr\">\"field\"<\/span>: <span class=\"hljs-string\">\"linesOfCode\"<\/span>,\n      <span class=\"hljs-attr\">\"code\"<\/span>: <span class=\"hljs-string\">\"ERROR_LESS_THAN_OR_EQUAL_TO\"<\/span>,\n      <span class=\"hljs-attr\">\"message\"<\/span>: <span class=\"hljs-string\">\"is not less than or equal to 500\"<\/span>\n    }\n  ]\n}<\/span>\n<\/code><\/pre>\n<h2><a href=\"#searching-data\" id=\"searching-data\" name=\"searching-data\" class=\"anchor\">Anchor link<\/a> <a href=\"#searching-data\">Searching data<\/a><\/h2>\n<p class=\"7xtjw4dqwy5mz7w3j\">In versions 4.1 and above, DADI API ships with the ability to add search to your document collections. The data connector used must support searching with the inclusion of a <code>search()<\/code> method. Currently this is only supported by the MongoDB connector <code>@dadi\/api-mongodb<\/code>.<\/p>\n<h3><a href=\"#configuration-1\" id=\"configuration-1\" name=\"configuration-1\" class=\"anchor\">Anchor link<\/a> <a href=\"#configuration-1\">Configuration<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">A <code>search<\/code> block must be added to the configuration file:<\/p>\n<pre><code class=\"lang-json\"><span class=\"hljs-string\">\"search\"<\/span>: {\n  <span class=\"hljs-string\">\"enabled\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n  <span class=\"hljs-string\">\"minQueryLength\"<\/span>: <span class=\"hljs-number\">3<\/span>,\n  <span class=\"hljs-string\">\"datastore\"<\/span>: <span class=\"hljs-string\">\"@dadi\/api-mongodb\"<\/span>,\n  <span class=\"hljs-string\">\"database\"<\/span>: <span class=\"hljs-string\">\"search\"<\/span>\n}\n<\/code><\/pre>\n<table>\n<thead>\n<tr>\n<th style=\"text-align:left\">Path<\/th>\n<th style=\"text-align:left\">Description<\/th>\n<th style=\"text-align:left\">Environment variable<\/th>\n<th style=\"text-align:left\">Default<\/th>\n<th style=\"text-align:left\">Format<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td style=\"text-align:left\"><code>enabled<\/code><\/td>\n<td style=\"text-align:left\">If true, API responds to collection \/search endpoints and will index content<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code>false<\/code><\/td>\n<td style=\"text-align:left\">Boolean<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>minQueryLength<\/code><\/td>\n<td style=\"text-align:left\">Minimum search string length<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code>3<\/code><\/td>\n<td style=\"text-align:left\">Number<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>wordCollection<\/code><\/td>\n<td style=\"text-align:left\">The name of the datastore collection that will hold tokenized words<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code>words<\/code><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>datastore<\/code><\/td>\n<td style=\"text-align:left\">The datastore module to use for storing and querying indexed documents<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code>@dadi\/api-mongodb<\/code><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>database<\/code><\/td>\n<td style=\"text-align:left\">The name of the database to use for storing and querying indexed documents<\/td>\n<td style=\"text-align:left\"><code>DB_SEARCH_NAME<\/code><\/td>\n<td style=\"text-align:left\"><code>search<\/code><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3><a href=\"#running-a-query\" id=\"running-a-query\" name=\"running-a-query\" class=\"anchor\">Anchor link<\/a> <a href=\"#running-a-query\">Running a query<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">Query an indexed collection by adding <code>\/search<\/code> to the collection&#39;s endpoint and include a <code>q<\/code> parameter in the querystring:<\/p>\n<pre><code class=\"lang-http\"><span class=\"hljs-keyword\">GET<\/span> <span class=\"hljs-string\">\/1.0\/library\/books\/search?q=wizard<\/span> HTTP\/1.1\n<span class=\"hljs-attribute\">Content-Type<\/span>: application\/json\n<span class=\"hljs-attribute\">Host<\/span>: api.somedomain.tech\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\">A response is returned in the same format as when performing any other GET query:<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Response<\/strong><\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"results\"<\/span>: [\n    {\n      <span class=\"hljs-attr\">\"_apiVersion\"<\/span>: <span class=\"hljs-string\">\"1.0\"<\/span>,\n      <span class=\"hljs-attr\">\"_createdAt\"<\/span>: <span class=\"hljs-number\">1532957892998<\/span>,\n      <span class=\"hljs-attr\">\"_createdBy\"<\/span>: <span class=\"hljs-string\">\"api-client\"<\/span>,\n      <span class=\"hljs-attr\">\"_id\"<\/span>: <span class=\"hljs-string\">\"5b5f14c4894d81942cb24aaf\"<\/span>,\n      <span class=\"hljs-attr\">\"_version\"<\/span>: <span class=\"hljs-number\">1<\/span>,\n      <span class=\"hljs-attr\">\"title\"<\/span>: <span class=\"hljs-string\">\"The Wizards of Once\"<\/span>\n    },\n    {\n      <span class=\"hljs-attr\">\"_apiVersion\"<\/span>: <span class=\"hljs-string\">\"1.0\"<\/span>,\n      <span class=\"hljs-attr\">\"_createdAt\"<\/span>: <span class=\"hljs-number\">1532958892932<\/span>,\n      <span class=\"hljs-attr\">\"_createdBy\"<\/span>: <span class=\"hljs-string\">\"api-client\"<\/span>,\n      <span class=\"hljs-attr\">\"_id\"<\/span>: <span class=\"hljs-string\">\"5b5f14c4894d81942cb24aacd\"<\/span>,\n      <span class=\"hljs-attr\">\"_version\"<\/span>: <span class=\"hljs-number\">1<\/span>,\n      <span class=\"hljs-attr\">\"title\"<\/span>: <span class=\"hljs-string\">\"Off to Be the Wizard\"<\/span>\n    }\n  ],\n  <span class=\"hljs-attr\">\"metadata\"<\/span>: {\n    <span class=\"hljs-attr\">\"search\"<\/span>: <span class=\"hljs-string\">\"wizard\"<\/span>,\n    <span class=\"hljs-attr\">\"limit\"<\/span>: <span class=\"hljs-number\">40<\/span>,\n    <span class=\"hljs-attr\">\"page\"<\/span>: <span class=\"hljs-number\">1<\/span>,\n    <span class=\"hljs-attr\">\"fields\"<\/span>: {},\n    <span class=\"hljs-attr\">\"offset\"<\/span>: <span class=\"hljs-number\">0<\/span>,\n    <span class=\"hljs-attr\">\"totalCount\"<\/span>: <span class=\"hljs-number\">2<\/span>,\n    <span class=\"hljs-attr\">\"totalPages\"<\/span>: <span class=\"hljs-number\">1<\/span>\n  }\n}\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\">Field filters can be applied in the same way as collection filtering:<\/p>\n<pre><code class=\"lang-http\">GET <span class=\"hljs-regexp\">\/1.0\/<\/span>library<span class=\"hljs-regexp\">\/books\/<\/span>search?q=wizard&fields={\"title\": <span class=\"hljs-number\">1<\/span>} HTTP\/<span class=\"hljs-number\">1.1<\/span>\nContent-<span class=\"hljs-string\">Type:<\/span> application\/json\n<span class=\"hljs-string\">Host:<\/span> api.somedomain.tech\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Response<\/strong><\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"results\"<\/span>: [\n    {\n      <span class=\"hljs-attr\">\"_id\"<\/span>: <span class=\"hljs-string\">\"5b5f14c4894d81942cb24aaf\"<\/span>,\n      <span class=\"hljs-attr\">\"title\"<\/span>: <span class=\"hljs-string\">\"The Wizards of Once\"<\/span>\n    },\n    {\n      <span class=\"hljs-attr\">\"_id\"<\/span>: <span class=\"hljs-string\">\"5b5f14c4894d81942cb24aacd\"<\/span>,\n      <span class=\"hljs-attr\">\"title\"<\/span>: <span class=\"hljs-string\">\"Off to Be the Wizard\"<\/span>\n    }\n  ],\n  <span class=\"hljs-attr\">\"metadata\"<\/span>: {\n    <span class=\"hljs-attr\">\"search\"<\/span>: <span class=\"hljs-string\">\"wizard\"<\/span>,\n    <span class=\"hljs-attr\">\"limit\"<\/span>: <span class=\"hljs-number\">40<\/span>,\n    <span class=\"hljs-attr\">\"page\"<\/span>: <span class=\"hljs-number\">1<\/span>,\n    <span class=\"hljs-attr\">\"fields\"<\/span>: {\n      <span class=\"hljs-attr\">\"title\"<\/span>: <span class=\"hljs-number\">1<\/span>\n    },\n    <span class=\"hljs-attr\">\"offset\"<\/span>: <span class=\"hljs-number\">0<\/span>,\n    <span class=\"hljs-attr\">\"totalCount\"<\/span>: <span class=\"hljs-number\">2<\/span>,\n    <span class=\"hljs-attr\">\"totalPages\"<\/span>: <span class=\"hljs-number\">1<\/span>\n  }\n}\n<\/code><\/pre>\n<h3><a href=\"#indexing-documents-for-search\" id=\"indexing-documents-for-search\" name=\"indexing-documents-for-search\" class=\"anchor\">Anchor link<\/a> <a href=\"#indexing-documents-for-search\">Indexing documents for search<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">To enable document indexing you must specify a <code>search<\/code> block for each field you&#39;d like indexed within the collection schema, including the weight:<\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"fields\"<\/span>: {\n    <span class=\"hljs-attr\">\"title\"<\/span>: {\n      <span class=\"hljs-attr\">\"type\"<\/span>: <span class=\"hljs-string\">\"String\"<\/span>,\n      <span class=\"hljs-attr\">\"label\"<\/span>: <span class=\"hljs-string\">\"Title\"<\/span>,\n      <span class=\"hljs-attr\">\"search\"<\/span>: {\n        <span class=\"hljs-attr\">\"weight\"<\/span>: <span class=\"hljs-number\">2<\/span>\n      }\n    }\n  }\n}\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Weight<\/strong><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">This value is a multiplier applied to the final relevance index to boost a document&#39;s position in the results.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">It allows a field to take further priority over other fields within a given document thus causing the document to return with a higher rank. <\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">For example if two documents contain the word &quot;banana&quot;, one in the title and the other in another field, if a weight of 2 has been applied to the title field, the document with &quot;banana&quot; in the title will receive a higher rank.<\/p>\n<h4><a href=\"#indexing-all-content\" id=\"indexing-all-content\" name=\"indexing-all-content\" class=\"anchor\">Anchor link<\/a> <a href=\"#indexing-all-content\">Indexing all content<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">To start a background indexing process, send a POST request to the indexing endpoint. Ensure you have a valid bearer token in the Authorization header when making this request.<\/p>\n<pre><code class=\"lang-http\"><span class=\"hljs-keyword\">POST<\/span> <span class=\"hljs-string\">\/api\/index<\/span> HTTP\/1.1\n<span class=\"hljs-attribute\">Content-Type<\/span>: application\/json\n<span class=\"hljs-attribute\">Host<\/span>: api.somedomain.tech\n<span class=\"hljs-attribute\">Authorization<\/span>: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjbGllbnRJZCI6InRlc3QiLCJhY2Nlc3NUeXBlIjoiYWRtaW4iLCJpYXQiOjE1MzMwNTgwODMsImV4cCI6MTUzNDg1ODA4M30.xnM17sNEmVd1mO7azs0uVv1EIsVCX_rt6qCvyUtaf40\n<\/code><\/pre>\n<h2><a href=\"#working-with-files\" id=\"working-with-files\" name=\"working-with-files\" class=\"anchor\">Anchor link<\/a> <a href=\"#working-with-files\">Working with files<\/a><\/h2>\n<p class=\"7xtjw4dqwy5mz7w3j\">In addition to the standard collections that hold text-based documents, DADI API includes a set of special collections that allow you to store any type of file, such as images, videos or PDFs. These are called <em>media buckets<\/em>.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">Each media bucket provides a set of endpoints for generating signed URLs, uploading and querying files with the same level of functionality available for document collections.<\/p>\n<h3><a href=\"#configuration-2\" id=\"configuration-2\" name=\"configuration-2\" class=\"anchor\">Anchor link<\/a> <a href=\"#configuration-2\">Configuration<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">The <code>media<\/code> configuration block can be used to define how media files are handled and stored by API. For example, this is where you can configure whether files are stored locally on disk or remotely in an S3 bucket.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">The following table shows all the available configuration properties.<\/p>\n<table>\n<thead>\n<tr>\n<th style=\"text-align:left\">Path<\/th>\n<th style=\"text-align:left\">Description<\/th>\n<th style=\"text-align:left\">Environment variable<\/th>\n<th style=\"text-align:left\">Default<\/th>\n<th style=\"text-align:left\">Format<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td style=\"text-align:left\"><code>defaultBucket<\/code><\/td>\n<td style=\"text-align:left\">The name of the default media bucket<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code>mediaStore<\/code><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>buckets<\/code><\/td>\n<td style=\"text-align:left\">The names of media buckets to be used<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code><\/code><\/td>\n<td style=\"text-align:left\">Array<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>tokenSecret<\/code><\/td>\n<td style=\"text-align:left\">The secret key used to sign and verify tokens when uploading media<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code>catboat-beatific-drizzle<\/code><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>tokenExpiresIn<\/code><\/td>\n<td style=\"text-align:left\">The duration a signed token is valid for. Expressed in seconds or a string describing a time span (https:\/\/github.com\/zeit\/ms). Eg: 60, \\&quot;2 days\\&quot;, \\&quot;10h\\&quot;, \\&quot;7d\\&quot;<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code>1h<\/code><\/td>\n<td style=\"text-align:left\">*<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>storage<\/code><\/td>\n<td style=\"text-align:left\">Determines the storage type for uploads<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code>disk<\/code><\/td>\n<td style=\"text-align:left\"><code>disk<\/code> or <code>s3<\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>basePath<\/code><\/td>\n<td style=\"text-align:left\">Sets the root directory for uploads<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code>workspace\/media<\/code><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>pathFormat<\/code><\/td>\n<td style=\"text-align:left\">Determines the format for the generation of subdirectories to store uploads<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code>date<\/code><\/td>\n<td style=\"text-align:left\"><code>none<\/code> or <code>date<\/code> or <code>datetime<\/code> or <code>sha1\/4<\/code> or <code>sha1\/5<\/code> or <code>sha1\/8<\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>s3.accessKey<\/code><\/td>\n<td style=\"text-align:left\">The access key used to connect to an S3-compatible storage provider<\/td>\n<td style=\"text-align:left\"><code>AWS_S3_ACCESS_KEY<\/code><\/td>\n<td style=\"text-align:left\"><code><\/code><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>s3.secretKey<\/code><\/td>\n<td style=\"text-align:left\">The secret key used to connect to an S3-compatible storage provider<\/td>\n<td style=\"text-align:left\"><code>AWS_S3_SECRET_KEY<\/code><\/td>\n<td style=\"text-align:left\"><code><\/code><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>s3.bucketName<\/code><\/td>\n<td style=\"text-align:left\">The name of the S3 bucket in which to store uploads<\/td>\n<td style=\"text-align:left\"><code>AWS_S3_BUCKET_NAME<\/code><\/td>\n<td style=\"text-align:left\"><code><\/code><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>s3.region<\/code><\/td>\n<td style=\"text-align:left\">The region for an S3-compatible storage provider<\/td>\n<td style=\"text-align:left\"><code>AWS_S3_REGION<\/code><\/td>\n<td style=\"text-align:left\"><code><\/code><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>s3.endpoint<\/code><\/td>\n<td style=\"text-align:left\">The endpoint for an S3-compatible storage provider<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code><\/code><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3><a href=\"#available-path-formats\" id=\"available-path-formats\" name=\"available-path-formats\" class=\"anchor\">Anchor link<\/a> <a href=\"#available-path-formats\">Available path formats<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">The <code>pathFormat<\/code> property determines the directory structure that API will use when storing files. This allows splitting files across many directories rather than storing them all in one directory. While this <a href=\"http:\/\/docs.aws.amazon.com\/AmazonS3\/latest\/dev\/BucketRestrictions.html\">isn&#39;t a problem when using S3<\/a>, when using the local filesystem storing a large number of files in one directory could negatively affect performance.<\/p>\n<table>\n<thead>\n<tr>\n<th style=\"text-align:left\">Format<\/th>\n<th style=\"text-align:left\">Description<\/th>\n<th style=\"text-align:left\">Example<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td style=\"text-align:left\"><code>&quot;none&quot;<\/code><\/td>\n<td style=\"text-align:left\">Doesn&#39;t create a directory structure, storing all uploads for a collection in a subdirectory of the <code>basePath<\/code> location<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>&quot;date&quot;<\/code><\/td>\n<td style=\"text-align:left\">Creates a directory structure using parts derived from the current date<\/td>\n<td style=\"text-align:left\"><code>2016\/12\/19\/my-image.jpg<\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>&quot;datetime&quot;<\/code><\/td>\n<td style=\"text-align:left\">Creates a directory structure using parts derived from the current date and time<\/td>\n<td style=\"text-align:left\"><code>2016\/12\/19\/13\/07\/22\/my-image.jpg<\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>&quot;sha1\/4&quot;<\/code><\/td>\n<td style=\"text-align:left\">Splits SHA1 hash of the image&#39;s filename into 4 character chunks<\/td>\n<td style=\"text-align:left\"><code>cb56\/<\/code> <code>7524\/<\/code> <code>77ca\/<\/code> <code>e640\/<\/code> <code>5f85\/<\/code> <code>b131\/<\/code> <code>872c\/<\/code> <code>60d2\/<\/code> <code>1b96\/<\/code> <code>7c6a\/<\/code> <code>my-image.jpg<\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>&quot;sha1\/5&quot;<\/code><\/td>\n<td style=\"text-align:left\">Splits SHA1 hash of the image&#39;s filename into 5 character chunks<\/td>\n<td style=\"text-align:left\"><code>cb567\/<\/code> <code>52477\/<\/code> <code>cae64\/<\/code> <code>05f85\/<\/code> <code>b1318\/<\/code> <code>72c60\/<\/code> <code>d21b9\/<\/code> <code>67c6a\/<\/code> <code>my-image.jpg<\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>&quot;sha1\/8&quot;<\/code><\/td>\n<td style=\"text-align:left\">Splits SHA1 hash of the image&#39;s filename into 8 character chunks<\/td>\n<td style=\"text-align:left\"><code>cb567524\/<\/code> <code>77cae640\/<\/code> <code>5f85b131\/<\/code> <code>872c60d2\/<\/code> <code>1b967c6a\/<\/code> <code>my-image.jpg<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3><a href=\"#configuring-media-buckets\" id=\"configuring-media-buckets\" name=\"configuring-media-buckets\" class=\"anchor\">Anchor link<\/a> <a href=\"#configuring-media-buckets\">Configuring media buckets<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">Each media bucket comes with its own set of endpoints, such as <code>\/sign<\/code> for generating signed URLs or <code>\/upload<\/code> for uploading files. All of these are prefixed with the name of the media bucket, except for the default bucket which, for convenience, is pegged to the root of the <code>\/media<\/code> route.<\/p>\n<table>\n<thead>\n<tr>\n<th>Name<\/th>\n<th>Is default<\/th>\n<th>Query<\/th>\n<th>Sign<\/th>\n<th>Upload<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>mediaStore<\/td>\n<td><strong>Yes<\/strong><\/td>\n<td><code>\/media\/mediaStore\/count<\/code> or <code>\/media\/count<\/code><\/td>\n<td><code>\/media\/mediaStore\/sign<\/code> or <code>\/media\/sign<\/code><\/td>\n<td><code>\/media\/mediaStore\/upload<\/code> or <code>\/media\/upload<\/code><\/td>\n<\/tr>\n<tr>\n<td>otherBucket<\/td>\n<td>No<\/td>\n<td><code>\/media\/otherBucket\/count<\/code><\/td>\n<td><code>\/media\/otherBucket\/sign<\/code><\/td>\n<td><code>\/media\/otherBucket\/upload<\/code><\/td>\n<\/tr>\n<tr>\n<td>someOtherBucket<\/td>\n<td>No<\/td>\n<td><code>\/media\/someOtherBucket\/count<\/code><\/td>\n<td><code>\/media\/someOtherBucket\/sign<\/code><\/td>\n<td><code>\/media\/someOtherBucket\/upload<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p class=\"7xtjw4dqwy5mz7w3j\">To override the name of the default media bucket, add a configuration property for <code>defaultBucket<\/code>:<\/p>\n<pre><code class=\"lang-json\"><span class=\"hljs-string\">\"media\"<\/span>: {\n  <span class=\"hljs-string\">\"defaultBucket\"<\/span>: <span class=\"hljs-string\">\"mediaStore\"<\/span>\n}\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\">To add additional media collections, add a <code>buckets<\/code> property:<\/p>\n<pre><code class=\"lang-json\"><span class=\"hljs-string\">\"media\"<\/span>: {\n  <span class=\"hljs-string\">\"buckets\"<\/span>: [<span class=\"hljs-string\">\"otherBucket\"<\/span>, <span class=\"hljs-string\">\"someOtherBucket\"<\/span>]\n}\n<\/code><\/pre>\n<h3><a href=\"#storage-types\" id=\"storage-types\" name=\"storage-types\" class=\"anchor\">Anchor link<\/a> <a href=\"#storage-types\">Storage types<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">API ships with two file storage handlers, one for storing files on the local filesystem and the other for storing files in an S3-compatible service such as Amazon S3 or Digital Ocean Spaces. If you need access to the files from another application, for example DADI CDN, we recommend using the S3 option.<\/p>\n<h4><a href=\"#file-storage\" id=\"file-storage\" name=\"file-storage\" class=\"anchor\">Anchor link<\/a> <a href=\"#file-storage\">File storage<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">The file storage handler saves uploaded files to the local filesystem, in the location specified by the <code>basePath<\/code> configuration property. <code>basePath<\/code> can be a path relative to the installation location of API or an absolute path. <\/p>\n<pre><code class=\"lang-json\"><span class=\"hljs-string\">\"media\"<\/span>: {\n  <span class=\"hljs-string\">\"storage\"<\/span>: <span class=\"hljs-string\">\"disk\"<\/span>,\n  <span class=\"hljs-string\">\"basePath\"<\/span>: <span class=\"hljs-string\">\"workspace\/media\"<\/span>\n}\n<\/code><\/pre>\n<h4><a href=\"#s3-compatible-storage\" id=\"s3-compatible-storage\" name=\"s3-compatible-storage\" class=\"anchor\">Anchor link<\/a> <a href=\"#s3-compatible-storage\">S3-compatible storage<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">The S3-compatible storage handler allows API to interact with services such as Amazon S3 and Digital Ocean Spaces.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">If the S3 storage handler is used, an additional set of configuration properties are required as seen in the <code>s3<\/code> block below:<\/p>\n<pre><code class=\"lang-json\"><span class=\"hljs-comment\">\"media\"<\/span>: {\n  <span class=\"hljs-comment\">\"storage\"<\/span>: <span class=\"hljs-comment\">\"s3\"<\/span>,\n  <span class=\"hljs-comment\">\"basePath\"<\/span>: <span class=\"hljs-comment\">\"uploads\"<\/span>,\n  <span class=\"hljs-comment\">\"pathFormat\"<\/span>: <span class=\"hljs-comment\">\"date\"<\/span>,\n  <span class=\"hljs-comment\">\"s3\"<\/span>: {\n    <span class=\"hljs-comment\">\"accessKey\"<\/span>: <span class=\"hljs-comment\">\"&lt;your-access-key&gt;\"<\/span>,\n    <span class=\"hljs-comment\">\"secretKey\"<\/span>: <span class=\"hljs-comment\">\"&lt;your-secret-key&gt;\"<\/span>,\n    <span class=\"hljs-comment\">\"bucketName\"<\/span>: <span class=\"hljs-comment\">\"&lt;your-bucket&gt;\"<\/span>,\n    <span class=\"hljs-comment\">\"region\"<\/span>: <span class=\"hljs-comment\">\"eu-west-1\"<\/span>\n  }\n}\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\">If using Digital Ocean Spaces, you&#39;ll require an additonal &quot;s3.endpoint&quot; property which should be set to something like &quot;nyc3.digitaloceanspaces.com&quot;<\/p>\n<blockquote class=\"warning\">\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Security Note<\/strong><\/p>\n<p>We don&apos;t recommend storing your S3 credentials in the configuration file. The <code>accessKey<\/code> and <code>secretKey<\/code> properties should instead be set as the environment variables <code>AWS_S3_ACCESS_KEY<\/code> and <code>AWS_S3_SECRET_KEY<\/code>.\n<\/p><\/blockquote>\n<h3><a href=\"#querying-media-buckets\" id=\"querying-media-buckets\" name=\"querying-media-buckets\" class=\"anchor\">Anchor link<\/a> <a href=\"#querying-media-buckets\">Querying media buckets<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">Media buckets can be queried in the same way as regular data collections. Send a GET request to a media endpoint with a <code>filter<\/code> parameter:<\/p>\n<pre><code class=\"lang-http\">GET \/media\/mediaStore?filter={<span class=\"hljs-string\">\"width\"<\/span>: <span class=\"hljs-number\">150<\/span>}\nHTTP\/<span class=\"hljs-number\">1.1<\/span> <span class=\"hljs-number\">200<\/span> OK\nContent-Type: application\/json\nConnection: keep-alive\n{\n  <span class=\"hljs-string\">\"results\"<\/span>: [\n    {\n      <span class=\"hljs-string\">\"_createdAt\"<\/span>: <span class=\"hljs-number\">1525677293872<\/span>,\n      <span class=\"hljs-string\">\"_id\"<\/span>: <span class=\"hljs-string\">\"5aeffceda32a4d53f24c8bd5\"<\/span>,\n      <span class=\"hljs-string\">\"_version\"<\/span>: <span class=\"hljs-number\">1<\/span>,\n      <span class=\"hljs-string\">\"contentLength\"<\/span>: <span class=\"hljs-number\">47237<\/span>,\n      <span class=\"hljs-string\">\"fileName\"<\/span>: <span class=\"hljs-string\">\"10687215_10154599861380077_4088877300129205613_n.jpg\"<\/span>,\n      <span class=\"hljs-string\">\"height\"<\/span>: <span class=\"hljs-number\">720<\/span>,\n      <span class=\"hljs-string\">\"mimeType\"<\/span>: <span class=\"hljs-string\">\"image\/jpeg\"<\/span>,\n      <span class=\"hljs-string\">\"path\"<\/span>: <span class=\"hljs-string\">\"\/media\/2018\/05\/07\/10687215_10154599861380077_4088877300129205613_n.jpg\"<\/span>,\n      <span class=\"hljs-string\">\"width\"<\/span>: <span class=\"hljs-number\">960<\/span>\n    }\n  ],\n  <span class=\"hljs-string\">\"metadata\"<\/span>: {\n    <span class=\"hljs-string\">\"limit\"<\/span>: <span class=\"hljs-number\">40<\/span>,\n    <span class=\"hljs-string\">\"page\"<\/span>: <span class=\"hljs-number\">1<\/span>,\n    <span class=\"hljs-string\">\"fields\"<\/span>: {},\n    <span class=\"hljs-string\">\"offset\"<\/span>: <span class=\"hljs-number\">0<\/span>,\n    <span class=\"hljs-string\">\"totalCount\"<\/span>: <span class=\"hljs-number\">1<\/span>,\n    <span class=\"hljs-string\">\"totalPages\"<\/span>: <span class=\"hljs-number\">1<\/span>\n  }\n}\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\">To include only certain properties in the returned response, supply a <code>fields<\/code> parameter:<\/p>\n<pre><code class=\"lang-http\">GET \/media\/mediaStore?filter={<span class=\"hljs-string\">\"width\"<\/span>: <span class=\"hljs-number\">150<\/span>}&fields={<span class=\"hljs-string\">\"fileName\"<\/span>: <span class=\"hljs-number\">1<\/span>}\nHTTP\/<span class=\"hljs-number\">1.1<\/span> <span class=\"hljs-number\">200<\/span> OK\nContent-Type: application\/json\nConnection: keep-alive\n{\n  <span class=\"hljs-string\">\"results\"<\/span>: [\n    {\n      <span class=\"hljs-string\">\"_id\"<\/span>: <span class=\"hljs-string\">\"5aeffceda32a4d53f24c8bd5\"<\/span>,\n      <span class=\"hljs-string\">\"fileName\"<\/span>: <span class=\"hljs-string\">\"10687215_10154599861380077_4088877300129205613_n.jpg\"<\/span>\n    }\n  ],\n  <span class=\"hljs-string\">\"metadata\"<\/span>: {\n    <span class=\"hljs-string\">\"limit\"<\/span>: <span class=\"hljs-number\">40<\/span>,\n    <span class=\"hljs-string\">\"page\"<\/span>: <span class=\"hljs-number\">1<\/span>,\n    <span class=\"hljs-string\">\"fields\"<\/span>: {\n      <span class=\"hljs-string\">\"fileName\"<\/span>: <span class=\"hljs-number\">1<\/span>\n    },\n    <span class=\"hljs-string\">\"offset\"<\/span>: <span class=\"hljs-number\">0<\/span>,\n    <span class=\"hljs-string\">\"totalCount\"<\/span>: <span class=\"hljs-number\">1<\/span>,\n    <span class=\"hljs-string\">\"totalPages\"<\/span>: <span class=\"hljs-number\">1<\/span>\n  }\n}\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\">The file itself can be downloaded by sending a GET request for the value of the <code>path<\/code> property. For example, given the following media document, a GET request can be made to <code>http:\/\/your-api-domain.com\/media\/2018\/05\/07\/10687215_10154599861380077_4088877300129205613_n.jpg<\/code><\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"_createdAt\"<\/span>: <span class=\"hljs-number\">1525677293872<\/span>,\n  <span class=\"hljs-attr\">\"_id\"<\/span>: <span class=\"hljs-string\">\"5aeffceda32a4d53f24c8bd5\"<\/span>,\n  <span class=\"hljs-attr\">\"_version\"<\/span>: <span class=\"hljs-number\">1<\/span>,\n  <span class=\"hljs-attr\">\"contentLength\"<\/span>: <span class=\"hljs-number\">47237<\/span>,\n  <span class=\"hljs-attr\">\"fileName\"<\/span>: <span class=\"hljs-string\">\"10687215_10154599861380077_4088877300129205613_n.jpg\"<\/span>,\n  <span class=\"hljs-attr\">\"height\"<\/span>: <span class=\"hljs-number\">720<\/span>,\n  <span class=\"hljs-attr\">\"mimetype\"<\/span>: <span class=\"hljs-string\">\"image\/jpeg\"<\/span>,\n  <span class=\"hljs-attr\">\"path\"<\/span>: <span class=\"hljs-string\">\"\/media\/2018\/05\/07\/10687215_10154599861380077_4088877300129205613_n.jpg\"<\/span>,\n  <span class=\"hljs-attr\">\"width\"<\/span>: <span class=\"hljs-number\">960<\/span>\n}\n<\/code><\/pre>\n<h3><a href=\"#uploading-files\" id=\"uploading-files\" name=\"uploading-files\" class=\"anchor\">Anchor link<\/a> <a href=\"#uploading-files\">Uploading files<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">As most commands, uploading a file to API requires an authenticated request. In the case of file uploads, this can be done using a typical <a href=\"#obtaining-an-access-token\">oAuth bearer token<\/a> or a <a href=\"#pre-signed-urls\">pre-signed URL<\/a>.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">To upload, send a <code>POST<\/code> request with a <code>Content-Type<\/code> or <code>multipart\/form-data<\/code> to the <code>\/upload<\/code> endpoint of the media bucket you wish to upload to, along with one or multiple files. On successful upload, the metadata for the uploaded files is returned as JSON, including an identifier for each file that can be used to create a reference to it from another collection.<\/p>\n<h4><a href=\"#uploading-a-file-with-curl\" id=\"uploading-a-file-with-curl\" name=\"uploading-a-file-with-curl\" class=\"anchor\">Anchor link<\/a> <a href=\"#uploading-a-file-with-curl\">Uploading a file with cURL<\/a><\/h4>\n<pre><code class=\"lang-bash\">curl -X POST\n  -<span class=\"ruby\">H <span class=\"hljs-string\">\"Content-Type: multipart\/form-data\"<\/span>\n<\/span>  -<span class=\"ruby\">H <span class=\"hljs-string\">\"Authorization: Bearer 8df4a823-1e1e-4bc4-800c-97bb480ccbbe\"<\/span>\n<\/span>  -<span class=\"ruby\">F <span class=\"hljs-string\">\"data=@\/Users\/userName\/images\/my-image.jpg\"<\/span> <span class=\"hljs-string\">\"http:\/\/api.somedomain.tech\/media\/upload\"<\/span><\/span>\n<\/code><\/pre>\n<h4><a href=\"#uploading-a-file-with-nodejs\" id=\"uploading-a-file-with-nodejs\" name=\"uploading-a-file-with-nodejs\" class=\"anchor\">Anchor link<\/a> <a href=\"#uploading-a-file-with-nodejs\">Uploading a file with Node.js<\/a><\/h4>\n<pre><code class=\"lang-javascript\"><span class=\"hljs-keyword\">const<\/span> API_HOST = <span class=\"hljs-string\">'https:\/\/my-api.somedomain.tech'<\/span>\n<span class=\"hljs-keyword\">const<\/span> API_PORT = <span class=\"hljs-number\">80<\/span>\n<span class=\"hljs-keyword\">const<\/span> FormData = <span class=\"hljs-built_in\">require<\/span>(<span class=\"hljs-string\">'form-data'<\/span>)\n<span class=\"hljs-keyword\">const<\/span> config = <span class=\"hljs-built_in\">require<\/span>(<span class=\"hljs-string\">'@dadi\/web'<\/span>).Config\n<span class=\"hljs-keyword\">let<\/span> options = {\n  host: API_HOST,\n  port: API_PORT,\n  path: <span class=\"hljs-string\">'\/media\/upload'<\/span>,\n  headers: {\n    <span class=\"hljs-string\">'Authorization'<\/span>: <span class=\"hljs-string\">'Bearer 8df4a823-1e1e-4bc4-800c-97bb480ccbbe'<\/span>, <span class=\"hljs-comment\">\/\/ Can be generated using '@dadi\/passport'.<\/span>\n    <span class=\"hljs-string\">'Accept'<\/span>: <span class=\"hljs-string\">'application\/json'<\/span>\n  }\n}\n<span class=\"hljs-keyword\">let<\/span> uploadResult = <span class=\"hljs-string\">''<\/span>\n<span class=\"hljs-keyword\">let<\/span> filePath = <span class=\"hljs-string\">'\/Users\/userName\/images\/my-image.jpg'<\/span>\n<span class=\"hljs-keyword\">let<\/span> form = <span class=\"hljs-keyword\">new<\/span> FormData()\nform.append(<span class=\"hljs-string\">'file'<\/span>, fs.createReadStream(filePath))\nform.submit(options, <span class=\"hljs-function\">(<span class=\"hljs-params\">err, response, body<\/span>) =&gt;<\/span> {\n  <span class=\"hljs-keyword\">if<\/span> (err) <span class=\"hljs-keyword\">throw<\/span> err\n  response.on(<span class=\"hljs-string\">'data'<\/span>, <span class=\"hljs-function\"><span class=\"hljs-params\">chunk<\/span> =&gt;<\/span> {\n    <span class=\"hljs-keyword\">if<\/span> (chunk) {\n      uploadResult += chunk\n    }\n  })\n  response.on(<span class=\"hljs-string\">'end'<\/span>, <span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n    processResult(uploadResult) <span class=\"hljs-comment\">\/\/ Your custom method here.<\/span>\n  })\n})\n<\/code><\/pre>\n<blockquote class=\"advice\">\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Uploading multiple files<\/strong><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">It is possible to upload multiple files as part of the same request. DADI API will process all fields in a <code>multipart\/form-data<\/code> request and treat each one as a separate file.<\/p>\n<\/blockquote>\n<h4><a href=\"#custom-metadata\" id=\"custom-metadata\" name=\"custom-metadata\" class=\"anchor\">Anchor link<\/a> <a href=\"#custom-metadata\">Custom metadata<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">When uploading a file, you can send additional metadata properties of your choice, such as caption, <em>alt text<\/em> or copyright information. To do so, add a field with any name of your choice with a JSON-stringified object as its value. Please note that the name of the field is irrelevant in this case, it&#39;s the JSON payload that will be appended to the media object.<\/p>\n<pre><code class=\"lang-bash\">curl -X POST\n  -<span class=\"ruby\">H <span class=\"hljs-string\">'Content-Type: multipart\/form-data'<\/span>\n<\/span>  -<span class=\"ruby\">H <span class=\"hljs-string\">'Authorization: Bearer 8df4a823-1e1e-4bc4-800c-97bb480ccbbe'<\/span>\n<\/span>  -<span class=\"ruby\">F <span class=\"hljs-string\">'metadata={\"caption\":\"My image\",\"copyright\":\"John Doe, 2018\"}'<\/span>\n<\/span>  -<span class=\"ruby\">F <span class=\"hljs-string\">'data=@\/Users\/userName\/images\/my-image.jpg'<\/span> <span class=\"hljs-string\">'http:\/\/api.somedomain.tech\/media\/upload'<\/span><\/span>\n<\/code><\/pre>\n<h4><a href=\"#response-3\" id=\"response-3\" name=\"response-3\" class=\"anchor\">Anchor link<\/a> <a href=\"#response-3\">Response<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">If successful, expect a response containing the following properties, as well as any custom metadata properties sent in the request:<\/p>\n<ul>\n<li><code>_id<\/code>: A hexidecimal string that uniquely identifies the newly-created media object<\/li>\n<li><code>_createdAt<\/code>: The date and time of creation (UNIX timestamp)<\/li>\n<li><code>_createdBy<\/code>: The name of the API client that uploaded the file<\/li>\n<li><code>_version<\/code>: The version of the file uploaded (defaults to <code>1<\/code>)<\/li>\n<li><code>contentLength<\/code>: The size of the file, in bytes<\/li>\n<li><code>fileName<\/code>: The name of the file as it was uploaded<\/li>\n<li><code>mimeType<\/code>: The MIME type of the file uploaded (e.g. <code>image\/jpeg<\/code>)<\/li>\n<li><code>path<\/code>: The path where the file was stored<\/li>\n<li><code>url<\/code>: The full URL to the uploaded file<\/li>\n<\/ul>\n<p class=\"7xtjw4dqwy5mz7w3j\">Depending on the type of file, additional metadata properties may be added. Currently, API adds <code>width<\/code> and <code>height<\/code> properties indicating the dimensions of the uploaded file if it&#39;s an image.<\/p>\n<h5><a href=\"#disk-storage\" id=\"disk-storage\" name=\"disk-storage\" class=\"anchor\">Anchor link<\/a> <a href=\"#disk-storage\">Disk storage<\/a><\/h5>\n<pre><code class=\"lang-http\">HTTP\/1.1 <span class=\"hljs-number\">201<\/span> Created\n<span class=\"hljs-attribute\">Content-Type<\/span>: application\/json\n<span class=\"hljs-attribute\">content-length<\/span>: 305\n<span class=\"hljs-attribute\">Connection<\/span>: keep-alive\n<span class=\"json\">{\n  <span class=\"hljs-attr\">\"results\"<\/span>:[\n    {\n      <span class=\"hljs-attr\">\"fileName\"<\/span>: <span class=\"hljs-string\">\"my-image.jpg\"<\/span>,\n      <span class=\"hljs-attr\">\"mimeType\"<\/span>: <span class=\"hljs-string\">\"image\/jpeg\"<\/span>,\n      <span class=\"hljs-attr\">\"width\"<\/span>: <span class=\"hljs-number\">1920<\/span>,\n      <span class=\"hljs-attr\">\"height\"<\/span>: <span class=\"hljs-number\">1080<\/span>,\n      <span class=\"hljs-attr\">\"path\"<\/span>: <span class=\"hljs-string\">\"\/media\/2018\/06\/12\/dog.jpg\"<\/span>,\n      <span class=\"hljs-attr\">\"url\"<\/span>: <span class=\"hljs-string\">\"https:\/\/my-api.somedomain.tech\/media\/2018\/06\/12\/dog.jpg\"<\/span>,\n      <span class=\"hljs-attr\">\"contentLength\"<\/span>: <span class=\"hljs-number\">173685<\/span>,\n      <span class=\"hljs-attr\">\"_createdAt\"<\/span>: <span class=\"hljs-number\">1482124829485<\/span>,\n      <span class=\"hljs-attr\">\"_createdBy\"<\/span>: <span class=\"hljs-string\">\"your-client-key\"<\/span>,\n      <span class=\"hljs-attr\">\"_version\"<\/span>: <span class=\"hljs-number\">1<\/span>,\n      <span class=\"hljs-attr\">\"_id\"<\/span>: <span class=\"hljs-string\">\"58576e1d5dd9975624b0d92c\"<\/span>\n    }\n  ]\n}<\/span>\n<\/code><\/pre>\n<h5><a href=\"#s3-storage\" id=\"s3-storage\" name=\"s3-storage\" class=\"anchor\">Anchor link<\/a> <a href=\"#s3-storage\">S3 storage<\/a><\/h5>\n<pre><code class=\"lang-http\">HTTP\/1.1 <span class=\"hljs-number\">201<\/span> Created\n<span class=\"hljs-attribute\">Content-Type<\/span>: application\/json\n<span class=\"hljs-attribute\">Content-Length<\/span>: 305\n<span class=\"hljs-attribute\">Connection<\/span>: keep-alive\n<span class=\"json\">{\n  <span class=\"hljs-attr\">\"results\"<\/span>:[\n    {\n      <span class=\"hljs-attr\">\"fileName\"<\/span>: <span class=\"hljs-string\">\"my-image.jpg\"<\/span>,\n      <span class=\"hljs-attr\">\"mimetype\"<\/span>: <span class=\"hljs-string\">\"image\/jpeg\"<\/span>,\n      <span class=\"hljs-attr\">\"width\"<\/span>: <span class=\"hljs-number\">1920<\/span>,\n      <span class=\"hljs-attr\">\"height\"<\/span>: <span class=\"hljs-number\">1080<\/span>,\n      <span class=\"hljs-attr\">\"path\"<\/span>: <span class=\"hljs-string\">\"2018\/06\/12\/dog.jpg\"<\/span>,\n      <span class=\"hljs-attr\">\"url\"<\/span>: <span class=\"hljs-string\">\"https:\/\/my-api.somedomain.tech\/media\/2018\/06\/12\/dog.jpg\"<\/span>,\n      <span class=\"hljs-attr\">\"contentLength\"<\/span>: <span class=\"hljs-number\">173685<\/span>,\n      <span class=\"hljs-attr\">\"_createdAt\"<\/span>: <span class=\"hljs-number\">1482124902978<\/span>,\n      <span class=\"hljs-attr\">\"_createdBy\"<\/span>: <span class=\"hljs-string\">\"your-client-key\"<\/span>,\n      <span class=\"hljs-attr\">\"_version\"<\/span>: <span class=\"hljs-number\">1<\/span>,\n      <span class=\"hljs-attr\">\"_id\"<\/span>: <span class=\"hljs-string\">\"58576e72bafa53b625aebd4f\"<\/span>\n    }\n  ]\n}<\/span>\n<\/code><\/pre>\n<h4><a href=\"#filename-transformations\" id=\"filename-transformations\" name=\"filename-transformations\" class=\"anchor\">Anchor link<\/a> <a href=\"#filename-transformations\">Filename transformations<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">To avoid compatibility issues across different operating systems, DADI API will transform the filenames of uploaded assets so that any spaces will be replaced with an underscore.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>Example:<\/em><\/p>\n<ul>\n<li>Original filename: <code>my trip to Portugal.jpg<\/code><\/li>\n<li>New filename: <code>my_trip_to_Portugal.jpg<\/code><\/li>\n<\/ul>\n<h4><a href=\"#filename-clashes\" id=\"filename-clashes\" name=\"filename-clashes\" class=\"anchor\">Anchor link<\/a> <a href=\"#filename-clashes\">Filename clashes<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">If using the filesystem storage and the filename of a file being uploaded is the same as an existing file, the new file will have its name changed by adding the current timestamp:<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>Example:<\/em><\/p>\n<ul>\n<li>Existing filename: <code>my-image.jpg<\/code><\/li>\n<li>New filename: <code>my-image-1480482847099.jpg<\/code><\/li>\n<\/ul>\n<h3><a href=\"#pre-signed-urls\" id=\"pre-signed-urls\" name=\"pre-signed-urls\" class=\"anchor\">Anchor link<\/a> <a href=\"#pre-signed-urls\">Pre-signed URLs<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">Pre-signed URLs are useful to allow your users or applications to be able to upload a file without requiring an access token. When you request a pre-signed URL, you must provide an access token (see <a href=\"#authentication\">Authentication<\/a>) and specify an expected filename and MIME type for the file to be uploaded. The pre-signed URLs are valid only for the duration specified in the <code>media.tokenExpiresIn<\/code> configuration property (which can be <a href=\"#override-the-expiry-when-requesting-a-signed-url\">overrridden on a per-request basis<\/a>).<\/p>\n<blockquote class=\"warning\">\n<p class=\"7xtjw4dqwy5mz7w3j\">It&apos;s currently not possible to upload multiple files simultaneously using a pre-signed URL. If you wish to upload multiple files, you can re-use the signed URL multiple times or you can bulk upload using an <a href=\"#obtaining-an-access-token\">access token<\/a>.<\/p>\n<\/blockquote>\n<h4><a href=\"#configuration-3\" id=\"configuration-3\" name=\"configuration-3\" class=\"anchor\">Anchor link<\/a> <a href=\"#configuration-3\">Configuration<\/a><\/h4>\n<pre><code class=\"lang-json\"><span class=\"hljs-string\">\"media\"<\/span>: {\n  <span class=\"hljs-string\">\"enabled\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n  <span class=\"hljs-string\">\"tokenSecret\"<\/span>: <span class=\"hljs-string\">\"catbus-goat-omelette\"<\/span>,\n  <span class=\"hljs-string\">\"tokenExpiresIn\"<\/span>: <span class=\"hljs-string\">\"10h\"<\/span>\n}\n<\/code><\/pre>\n<h4><a href=\"#request-a-signed-url\" id=\"request-a-signed-url\" name=\"request-a-signed-url\" class=\"anchor\">Anchor link<\/a> <a href=\"#request-a-signed-url\">Request a signed URL<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">To obtain a signed URL, send a <code>POST<\/code> request to the <code>\/sign<\/code> endpoint of a media bucket. The body of the request should contain the filename and MIME type of the file to be uploaded:<\/p>\n<pre><code class=\"lang-http\"><span class=\"hljs-keyword\">POST<\/span> <span class=\"hljs-string\">\/media\/sign<\/span> HTTP\/1.1\n<span class=\"hljs-attribute\">Host<\/span>: api.somedomain.tech\n<span class=\"hljs-attribute\">Content-Type<\/span>: application\/json\n<span class=\"hljs-attribute\">Authorization<\/span>: Bearer 8df4a823-1e1e-4bc4-800c-97bb480ccbbe\n<span class=\"json\">{\n  <span class=\"hljs-attr\">\"fileName\"<\/span>: <span class=\"hljs-string\">\"my-image.jpg\"<\/span>,\n  <span class=\"hljs-attr\">\"mimeType\"<\/span>: <span class=\"hljs-string\">\"image\/jpeg\"<\/span>\n}<\/span>\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\">API returns a response with a <code>url<\/code> property that contains the signed URL for uploading the specified file:<\/p>\n<pre><code class=\"lang-http\">HTTP\/1.1 <span class=\"hljs-number\">200<\/span> OK\n<span class=\"hljs-attribute\">Content-Type<\/span>: application\/json\n<span class=\"hljs-attribute\">content-length<\/span>: 305\n<span class=\"hljs-attribute\">Connection<\/span>: keep-alive\n<span class=\"json\">{\n  <span class=\"hljs-attr\">\"url\"<\/span>: <span class=\"hljs-string\">\"\/media\/eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmaWxlTmFtZSI6ImltYWdlLmpwZyIsImlhdCI6MTUyNzU3MzMzMiwiZXhwIjoxNTI3NTc2OTMyfQ.9d9HI3gCOSeuNgkeepISvs2QSvfcpXSSRBeHa6qVsXA\"<\/span>\n}<\/span>\n<\/code><\/pre>\n<h5><a href=\"#override-the-expiry-when-requesting-a-signed-url\" id=\"override-the-expiry-when-requesting-a-signed-url\" name=\"override-the-expiry-when-requesting-a-signed-url\" class=\"anchor\">Anchor link<\/a> <a href=\"#override-the-expiry-when-requesting-a-signed-url\">Override the expiry when requesting a signed URL<\/a><\/h5>\n<p class=\"7xtjw4dqwy5mz7w3j\">The globally-configured token expiry value can be overridden when requesting a signed URL by specifying a new expiry in the request to obtain the signed URL:<\/p>\n<pre><code class=\"lang-http\"><span class=\"hljs-keyword\">POST<\/span> <span class=\"hljs-string\">\/media\/sign<\/span> HTTP\/1.1\n<span class=\"json\">{\n  <span class=\"hljs-attr\">\"fileName\"<\/span>: <span class=\"hljs-string\">\"my-image.jpg\"<\/span>,\n  <span class=\"hljs-attr\">\"mimetype\"<\/span>: <span class=\"hljs-string\">\"image\/jpeg\"<\/span>,\n  <span class=\"hljs-attr\">\"expiresIn\"<\/span>: <span class=\"hljs-string\">\"15000\"<\/span> \/\/ value in seconds\n}<\/span>\n<\/code><\/pre>\n<h4><a href=\"#upload-the-file\" id=\"upload-the-file\" name=\"upload-the-file\" class=\"anchor\">Anchor link<\/a> <a href=\"#upload-the-file\">Upload the file<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">With the signed URL obtained in the above step, a <code>POST<\/code> request can be sent to that URL with the file. See <a href=\"#uploading-a-file\">Uploading a file<\/a> for information regarding the upload process.<\/p>\n<pre><code class=\"lang-http\"><span class=\"hljs-keyword\">POST<\/span> <span class=\"hljs-string\">\/media\/eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmaWxlTmFtZSI6ImltYWdlLmpwZyIsImlhdCI6MTUyNzU3MzMzMiwiZXhwIjoxNTI3NTc2OTMyfQ.9d9HI3gCOSeuNgkeepISvs2QSvfcpXSSRBeHa6qVsXA<\/span> HTTP\/1.1\n<span class=\"hljs-attribute\">Host<\/span>: api.somedomain.tech\n<span class=\"hljs-attribute\">Content-Type<\/span>: multipart\/form-data\n<\/code><\/pre>\n<h3><a href=\"#referencing-media-from-another-collection\" id=\"referencing-media-from-another-collection\" name=\"referencing-media-from-another-collection\" class=\"anchor\">Anchor link<\/a> <a href=\"#referencing-media-from-another-collection\">Referencing media from another collection<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">Once a file is uploaded, its identifier can be used to create a reference from another collection. For this example we have a collection called <code>books<\/code> with the following schema:<\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"fields\"<\/span>: {\n    <span class=\"hljs-attr\">\"title\"<\/span>: {\n      <span class=\"hljs-attr\">\"type\"<\/span>: <span class=\"hljs-string\">\"String\"<\/span>,\n      <span class=\"hljs-attr\">\"required\"<\/span>: <span class=\"hljs-literal\">true<\/span>\n    },\n    <span class=\"hljs-attr\">\"content\"<\/span>: {\n      <span class=\"hljs-attr\">\"type\"<\/span>: <span class=\"hljs-string\">\"String\"<\/span>,\n      <span class=\"hljs-attr\">\"required\"<\/span>: <span class=\"hljs-literal\">true<\/span>\n    },\n    <span class=\"hljs-attr\">\"image\"<\/span>: {\n      <span class=\"hljs-attr\">\"type\"<\/span>: <span class=\"hljs-string\">\"Media\"<\/span>,\n      <span class=\"hljs-attr\">\"settings\"<\/span>: {\n        <span class=\"hljs-attr\">\"mediaBucket\"<\/span>: <span class=\"hljs-string\">\"mediaStore\"<\/span>\n      }\n    }\n  }\n}\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\">The <code>image<\/code> field is a reference to the media bucket defined in the <code>settings.mediaBucket<\/code> property (when this property is omitted, the default media bucket is inferred). When the ID of a media object is set as the value of a field of type <code>Media<\/code>, a lookup will be made on the referenced media bucket and the resolved object will be retrieved.<\/p>\n<pre><code class=\"lang-http\"><span class=\"hljs-keyword\">POST<\/span> <span class=\"hljs-string\">\/1.0\/library\/books<\/span> HTTP\/1.1\n<span class=\"hljs-attribute\">Host<\/span>: api.somedomain.tech\n<span class=\"hljs-attribute\">Content-Type<\/span>: application\/json\n<span class=\"hljs-attribute\">Authorization<\/span>: Bearer 8df4a823-1e1e-4bc4-800c-97bb480ccbbe\n<span class=\"json\">{\n  <span class=\"hljs-attr\">\"title\"<\/span>: <span class=\"hljs-string\">\"Harry Potter and the Philosopher's Stone\"<\/span>,\n  <span class=\"hljs-attr\">\"content\"<\/span>: <span class=\"hljs-string\">\"Harry Potter and the Philosopher's Stone is the first novel in the Harry Potter series and J. K. Rowling's debut novel, first published in 1997 by Bloomsbury.\"<\/span>,\n  <span class=\"hljs-attr\">\"image\"<\/span>: <span class=\"hljs-string\">\"58576e72bafa53b625aebd4f\"<\/span>\n}<\/span>\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\">A subsequent GET request for this book would return a response such as:<\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"title\"<\/span>: <span class=\"hljs-string\">\"Harry Potter and the Philosopher's Stone\"<\/span>,\n  <span class=\"hljs-attr\">\"content\"<\/span>: <span class=\"hljs-string\">\"Harry Potter and the Philosopher's Stone is the first novel in the Harry Potter series and J. K. Rowling's debut novel, first published in 1997 by Bloomsbury.\"<\/span>,\n  <span class=\"hljs-attr\">\"image\"<\/span>: {\n    <span class=\"hljs-attr\">\"_createdAt\"<\/span>: <span class=\"hljs-number\">1482124902978<\/span>,\n    <span class=\"hljs-attr\">\"_createdBy\"<\/span>: <span class=\"hljs-string\">\"your-client-key\"<\/span>,\n    <span class=\"hljs-attr\">\"_version\"<\/span>: <span class=\"hljs-number\">1<\/span>,\n    <span class=\"hljs-attr\">\"_id\"<\/span>: <span class=\"hljs-string\">\"58576e72bafa53b625aebd4f\"<\/span>,\n    <span class=\"hljs-attr\">\"fileName\"<\/span>: <span class=\"hljs-string\">\"harry.jpg\"<\/span>,\n    <span class=\"hljs-attr\">\"mimetype\"<\/span>: <span class=\"hljs-string\">\"image\/jpeg\"<\/span>,\n    <span class=\"hljs-attr\">\"width\"<\/span>: <span class=\"hljs-number\">1920<\/span>,\n    <span class=\"hljs-attr\">\"height\"<\/span>: <span class=\"hljs-number\">1080<\/span>,\n    <span class=\"hljs-attr\">\"path\"<\/span>: <span class=\"hljs-string\">\"workspace\/media\/2016\/12\/19\/harry.jpg\"<\/span>,\n    <span class=\"hljs-attr\">\"contentLength\"<\/span>: <span class=\"hljs-number\">173685<\/span>,\n    <span class=\"hljs-attr\">\"url\"<\/span>: <span class=\"hljs-string\">\"https:\/\/api.somedomain.tech\/media\/2016\/12\/19\/harry.jpg\"<\/span>\n  }\n}\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\">It&#39;s also possible for a <code>Media<\/code> field to reference multiple media objects (think of an image gallery, for example). To do this, set the value of the field to an array of IDs instead of a single one. When retrieving the parent document, all the media objects in the array will be retrieved and resolved in the response.<\/p>\n<pre><code class=\"lang-http\"><span class=\"hljs-keyword\">POST<\/span> <span class=\"hljs-string\">\/1.0\/library\/books<\/span> HTTP\/1.1\n<span class=\"hljs-attribute\">Host<\/span>: api.somedomain.tech\n<span class=\"hljs-attribute\">Content-Type<\/span>: application\/json\n<span class=\"hljs-attribute\">Authorization<\/span>: Bearer 8df4a823-1e1e-4bc4-800c-97bb480ccbbe\n<span class=\"json\">{\n  <span class=\"hljs-attr\">\"title\"<\/span>: <span class=\"hljs-string\">\"Harry Potter and the Philosopher's Stone\"<\/span>,\n  <span class=\"hljs-attr\">\"content\"<\/span>: <span class=\"hljs-string\">\"Harry Potter and the Philosopher's Stone is the first novel in the Harry Potter series and J. K. Rowling's debut novel, first published in 1997 by Bloomsbury.\"<\/span>,\n  <span class=\"hljs-attr\">\"image\"<\/span>: [\n    <span class=\"hljs-string\">\"58576e72bafa53b625aebd4a\"<\/span>,\n    <span class=\"hljs-string\">\"58576e72bafa53b625aebd4b\"<\/span>,\n    <span class=\"hljs-string\">\"58576e72bafa53b625aebd4c\"<\/span>\n  ]\n}<\/span>\n<\/code><\/pre>\n<h4><a href=\"#document-level-metadata\" id=\"document-level-metadata\" name=\"document-level-metadata\" class=\"anchor\">Anchor link<\/a> <a href=\"#document-level-metadata\">Document-level metadata<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">It&#39;s possible to reference the same media object countless times in different documents. The metadata properties that API adds to any uploaded media objects, such as <code>mimeType<\/code> or <code>fileName<\/code>, will be relevant anywhere the media object is referenced, but you might need to add others that are specific to where and how the media file is being used.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">For example, the image of the Harry Potter movie we uploaded above could be used as the poster image in a document representing the movie as well as in a document representing Emma Watson. Whilst the former could contain more generic metadata properties, the latter might require specific specific caption and crop coordinates to highlight Hermione.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">To cater for this, API lets you extend the metadata block of a media object with additional properties that are specific to the document you&#39;re referencing it from. To do that, you must set the value of a <code>Media<\/code> field to be an object instead of an ID string, containing an <code>_id<\/code> property as well as the metadata properties you wish to add.<\/p>\n<pre><code class=\"lang-http\"><span class=\"hljs-keyword\">POST<\/span> <span class=\"hljs-string\">\/1.0\/library\/books<\/span> HTTP\/1.1\n<span class=\"hljs-attribute\">Host<\/span>: api.somedomain.tech\n<span class=\"hljs-attribute\">Content-Type<\/span>: application\/json\n<span class=\"hljs-attribute\">Authorization<\/span>: Bearer 8df4a823-1e1e-4bc4-800c-97bb480ccbbe\n<span class=\"json\">{\n  <span class=\"hljs-attr\">\"title\"<\/span>: <span class=\"hljs-string\">\"Harry Potter and the Philosopher's Stone\"<\/span>,\n  <span class=\"hljs-attr\">\"content\"<\/span>: <span class=\"hljs-string\">\"Harry Potter and the Philosopher's Stone is the first novel in the Harry Potter series and J. K. Rowling's debut novel, first published in 1997 by Bloomsbury.\"<\/span>,\n  <span class=\"hljs-attr\">\"image\"<\/span>: {\n    <span class=\"hljs-attr\">\"_id\"<\/span>: <span class=\"hljs-string\">\"58576e72bafa53b625aebd4f\"<\/span>,\n    <span class=\"hljs-attr\">\"caption\"<\/span>: <span class=\"hljs-string\">\"Harry and Hermione sitting in the Gryffindor common room\"<\/span>,\n    <span class=\"hljs-attr\">\"crop\"<\/span>: [<span class=\"hljs-number\">16<\/span>, <span class=\"hljs-number\">32<\/span>, <span class=\"hljs-number\">64<\/span>, <span class=\"hljs-number\">128<\/span>]\n  }\n}<\/span>\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\">When retrieving the parent document, the document-level metadata properties will be merged with the ones from the raw media object.<\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"title\"<\/span>: <span class=\"hljs-string\">\"Harry Potter and the Philosopher's Stone\"<\/span>,\n  <span class=\"hljs-attr\">\"content\"<\/span>: <span class=\"hljs-string\">\"Harry Potter and the Philosopher's Stone is the first novel in the Harry Potter series and J. K. Rowling's debut novel, first published in 1997 by Bloomsbury.\"<\/span>,\n  <span class=\"hljs-attr\">\"image\"<\/span>: {\n    <span class=\"hljs-attr\">\"_createdAt\"<\/span>: <span class=\"hljs-number\">1482124902978<\/span>,\n    <span class=\"hljs-attr\">\"_createdBy\"<\/span>: <span class=\"hljs-string\">\"your-client-key\"<\/span>,\n    <span class=\"hljs-attr\">\"_version\"<\/span>:<span class=\"hljs-number\">1<\/span>,\n    <span class=\"hljs-attr\">\"_id\"<\/span>:<span class=\"hljs-string\">\"58576e72bafa53b625aebd4f\"<\/span>,\n    <span class=\"hljs-attr\">\"fileName\"<\/span>: <span class=\"hljs-string\">\"harry.jpg\"<\/span>,\n    <span class=\"hljs-attr\">\"mimetype\"<\/span>: <span class=\"hljs-string\">\"image\/jpeg\"<\/span>,\n    <span class=\"hljs-attr\">\"width\"<\/span>: <span class=\"hljs-number\">1920<\/span>,\n    <span class=\"hljs-attr\">\"height\"<\/span>: <span class=\"hljs-number\">1080<\/span>,\n    <span class=\"hljs-attr\">\"path\"<\/span>: <span class=\"hljs-string\">\"workspace\/media\/2016\/12\/19\/harry.jpg\"<\/span>,\n    <span class=\"hljs-attr\">\"contentLength\"<\/span>:<span class=\"hljs-number\">173685<\/span>,\n    <span class=\"hljs-attr\">\"url\"<\/span>: <span class=\"hljs-string\">\"https:\/\/api.somedomain.tech\/media\/2016\/12\/19\/harry.jpg\"<\/span>,\n    <span class=\"hljs-attr\">\"caption\"<\/span>: <span class=\"hljs-string\">\"Harry and Hermione sitting in the Gryffindor common room\"<\/span>,\n    <span class=\"hljs-attr\">\"crop\"<\/span>: [<span class=\"hljs-number\">16<\/span>, <span class=\"hljs-number\">32<\/span>, <span class=\"hljs-number\">64<\/span>, <span class=\"hljs-number\">128<\/span>]\n  }\n}\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\">The same logic applies when referencing multiple media objects: each item in the array may contain its own set of metadata properties.<\/p>\n<pre><code class=\"lang-http\"><span class=\"hljs-keyword\">POST<\/span> <span class=\"hljs-string\">\/1.0\/library\/books<\/span> HTTP\/1.1\n<span class=\"hljs-attribute\">Host<\/span>: api.somedomain.tech\n<span class=\"hljs-attribute\">Content-Type<\/span>: application\/json\n<span class=\"hljs-attribute\">Authorization<\/span>: Bearer 8df4a823-1e1e-4bc4-800c-97bb480ccbbe\n<span class=\"json\">{\n  <span class=\"hljs-attr\">\"title\"<\/span>: <span class=\"hljs-string\">\"Harry Potter and the Philosopher's Stone\"<\/span>,\n  <span class=\"hljs-attr\">\"content\"<\/span>: <span class=\"hljs-string\">\"Harry Potter and the Philosopher's Stone is the first novel in the Harry Potter series and J. K. Rowling's debut novel, first published in 1997 by Bloomsbury.\"<\/span>,\n  <span class=\"hljs-attr\">\"image\"<\/span>: [\n    {\n      <span class=\"hljs-attr\">\"_id\"<\/span>: <span class=\"hljs-string\">\"58576e72bafa53b625aebd4a\"<\/span>,\n      <span class=\"hljs-attr\">\"caption\"<\/span>: <span class=\"hljs-string\">\"Harry and Hermione sitting in the Gryffindor common room\"<\/span>,\n      <span class=\"hljs-attr\">\"crop\"<\/span>: [<span class=\"hljs-number\">16<\/span>, <span class=\"hljs-number\">32<\/span>, <span class=\"hljs-number\">64<\/span>, <span class=\"hljs-number\">128<\/span>]\n    },\n    {\n      <span class=\"hljs-attr\">\"_id\"<\/span>: <span class=\"hljs-string\">\"58576e72bafa53b625aebd4b\"<\/span>,\n      <span class=\"hljs-attr\">\"caption\"<\/span>: <span class=\"hljs-string\">\"Hermione Granger telling Ron Weasley about RESTful APIs\"<\/span>,\n      <span class=\"hljs-attr\">\"crop\"<\/span>: [<span class=\"hljs-number\">32<\/span>, <span class=\"hljs-number\">64<\/span>, <span class=\"hljs-number\">128<\/span>, <span class=\"hljs-number\">256<\/span>]\n    },\n    {\n      <span class=\"hljs-attr\">\"_id\"<\/span>: <span class=\"hljs-string\">\"58576e72bafa53b625aebd4c\"<\/span>,\n      <span class=\"hljs-attr\">\"caption\"<\/span>: <span class=\"hljs-string\">\"Lord Voldemort using DADI API\"<\/span>,\n      <span class=\"hljs-attr\">\"crop\"<\/span>: [<span class=\"hljs-number\">64<\/span>, <span class=\"hljs-number\">128<\/span>, <span class=\"hljs-number\">256<\/span>, <span class=\"hljs-number\">512<\/span>]\n    }\n  ]\n}<\/span>\n<\/code><\/pre>\n<h3><a href=\"#updating-media\" id=\"updating-media\" name=\"updating-media\" class=\"anchor\">Anchor link<\/a> <a href=\"#updating-media\">Updating media<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">Updates to a media object can be used to change the referenced file, by uploading a new one, to update any of the associated metadata properties, or both.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">When updating metadata properties only, it is possible to send a JSON payload with a <code>application\/json<\/code> content type, just like normal collections.<\/p>\n<pre><code class=\"lang-http\"><span class=\"hljs-keyword\">PUT<\/span> <span class=\"hljs-string\">\/media\/58576e72bafa53b625aebd1a<\/span> HTTP\/1.1\n<span class=\"hljs-attribute\">Host<\/span>: api.somedomain.tech\n<span class=\"hljs-attribute\">Content-Type<\/span>: application\/json\n<span class=\"hljs-attribute\">Authorization<\/span>: Bearer 8df4a823-1e1e-4bc4-800c-97bb480ccbbe\n<span class=\"json\">{\n  <span class=\"hljs-attr\">\"caption\"<\/span>: <span class=\"hljs-string\">\"Harry and Hermione sitting in the Gryffindor common room\"<\/span>,\n  <span class=\"hljs-attr\">\"crop\"<\/span>: [<span class=\"hljs-number\">16<\/span>, <span class=\"hljs-number\">32<\/span>, <span class=\"hljs-number\">64<\/span>, <span class=\"hljs-number\">128<\/span>]\n}<\/span>\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\">To update the referenced file, the request should have a content type of <code>multipart\/form-data<\/code> and contain a file to replace the existing one.<\/p>\n<pre><code class=\"lang-console\">$ curl \\\n  -<span class=\"ruby\">X PUT\n<\/span>  -<span class=\"ruby\">H <span class=\"hljs-string\">'Authorization: Bearer 8df4a823-1e1e-4bc4-800c-97bb480ccbbe'<\/span>\n<\/span>  -<span class=\"ruby\">F <span class=\"hljs-string\">'image=@\/home\/user\/Desktop\/test.jpg'<\/span> \\\n<\/span>  https:\/\/api.somedomain.tech\/media\/58576e72bafa53b625aebd1a\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\">To do both, additional fields can be added to the <code>multipart\/form-data<\/code> request. The content of the field should be a JSON string containing the update object \u2013 the name of the field is irrelevant.<\/p>\n<pre><code class=\"lang-console\">$ curl \\\n  -<span class=\"ruby\">X PUT\n<\/span>  -<span class=\"ruby\">H <span class=\"hljs-string\">'Authorization: Bearer 8df4a823-1e1e-4bc4-800c-97bb480ccbbe'<\/span>\n<\/span>  -<span class=\"ruby\">F <span class=\"hljs-string\">'image=@\/home\/user\/Desktop\/test.jpg'<\/span> \\\n<\/span>  -<span class=\"ruby\">F <span class=\"hljs-string\">'anything={\"caption\":\"A new caption\",\"alt\":\"New alt text\"}'<\/span> \\\n<\/span>  https:\/\/api.somedomain.tech\/media\/58576e72bafa53b625aebd1a\n<\/code><\/pre>\n<h3><a href=\"#deleting-media\" id=\"deleting-media\" name=\"deleting-media\" class=\"anchor\">Anchor link<\/a> <a href=\"#deleting-media\">Deleting media<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">To delete a single media object, send a DELETE request to a media bucket specifying the object&#39;s <code>_id<\/code> property in the URL. Alternatively, you can provide a <code>query<\/code> property in the request body that will determine the documents (potentially more than one) to be deleted.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">If successful, a 200 response is returned (or a 204 if <code>feedback: false<\/code> is set in configuration):<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>Deleting by ID:<\/em><\/p>\n<pre><code class=\"lang-http\"><span class=\"hljs-keyword\">DELETE<\/span> <span class=\"hljs-regexp\">\/media\/<\/span><span class=\"hljs-number\">5<\/span>b10e5b76b600c760dc1cb93\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>Deleting by query:<\/em><\/p>\n<pre><code class=\"lang-http\">DELETE \/media\n{\n  <span class=\"hljs-string\">\"query\"<\/span>: {\n    <span class=\"hljs-string\">\"mimeType\"<\/span>: <span class=\"hljs-string\">\"image\/jpeg\"<\/span>\n  }\n}\n<\/code><\/pre>\n<h3><a href=\"#error-messages\" id=\"error-messages\" name=\"error-messages\" class=\"anchor\">Anchor link<\/a> <a href=\"#error-messages\">Error messages<\/a><\/h3>\n<h4><a href=\"#signed-url-token-expired\" id=\"signed-url-token-expired\" name=\"signed-url-token-expired\" class=\"anchor\">Anchor link<\/a> <a href=\"#signed-url-token-expired\">Signed URL token expired<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">If the token for a signed URL has expired, the following response will be returned:<\/p>\n<pre><code class=\"lang-http\">HTTP\/1.1 <span class=\"hljs-number\">400<\/span> Bad Request\n<span class=\"hljs-attribute\">Content-Type<\/span>: application\/json\n<span class=\"hljs-attribute\">Content-Length<\/span>: 305\n<span class=\"hljs-attribute\">Connection<\/span>: keep-alive\n<span class=\"json\">{\n  <span class=\"hljs-attr\">\"statusCode\"<\/span>: <span class=\"hljs-number\">400<\/span>,\n  <span class=\"hljs-attr\">\"name\"<\/span>: <span class=\"hljs-string\">\"TokenExpiredError\"<\/span>,\n  <span class=\"hljs-attr\">\"message\"<\/span>: <span class=\"hljs-string\">\"jwt expired\"<\/span>,\n  <span class=\"hljs-attr\">\"expiredAt\"<\/span>: <span class=\"hljs-string\">\"2018-05-29T05:59:17.000Z\"<\/span>\n}<\/span>\n<\/code><\/pre>\n<h4><a href=\"#invalid-filename\" id=\"invalid-filename\" name=\"invalid-filename\" class=\"anchor\">Anchor link<\/a> <a href=\"#invalid-filename\">Invalid filename<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">If the filename of the uploaded file doesn&#39;t match that sent in the request to obtain the signed URL, API returns a 400 error:<\/p>\n<pre><code class=\"lang-http\">HTTP\/1.1 <span class=\"hljs-number\">400<\/span> Bad Request\n<span class=\"hljs-attribute\">Content-Type<\/span>: application\/json\n<span class=\"hljs-attribute\">Content-Length<\/span>: 305\n<span class=\"hljs-attribute\">Connection<\/span>: keep-alive\n<span class=\"json\">{\n  <span class=\"hljs-attr\">\"statusCode\"<\/span>: <span class=\"hljs-number\">400<\/span>,\n  <span class=\"hljs-attr\">\"name\"<\/span>: <span class=\"hljs-string\">\"Unexpected filename\"<\/span>,\n  <span class=\"hljs-attr\">\"message\"<\/span>: <span class=\"hljs-string\">\"Expected a file named 'my-image.jpg'\"<\/span>\n}<\/span>\n<\/code><\/pre>\n<h4><a href=\"#invalid-mime-type\" id=\"invalid-mime-type\" name=\"invalid-mime-type\" class=\"anchor\">Anchor link<\/a> <a href=\"#invalid-mime-type\">Invalid MIME type<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">If the MIME type of the uploaded file doesn&#39;t match that sent in the request sent to obtain the signed URL, API returns a 400 error:<\/p>\n<pre><code class=\"lang-http\">HTTP\/1.1 <span class=\"hljs-number\">400<\/span> Bad Request\n<span class=\"hljs-attribute\">Content-Type<\/span>: application\/json\n<span class=\"hljs-attribute\">Content-Length<\/span>: 305\n<span class=\"hljs-attribute\">Connection<\/span>: keep-alive\n<span class=\"json\">{\n  <span class=\"hljs-attr\">\"statusCode\"<\/span>: <span class=\"hljs-number\">400<\/span>,\n  <span class=\"hljs-attr\">\"name\"<\/span>: <span class=\"hljs-string\">\"Unexpected mimetype\"<\/span>,\n  <span class=\"hljs-attr\">\"message\"<\/span>: <span class=\"hljs-string\">\"Expected a mimetype of 'image\/jpeg'\"<\/span>\n}<\/span>\n<\/code><\/pre>\n<h2><a href=\"#multiple-languages\" id=\"multiple-languages\" name=\"multiple-languages\" class=\"anchor\">Anchor link<\/a> <a href=\"#multiple-languages\">Multiple languages<\/a><\/h2>\n<p class=\"7xtjw4dqwy5mz7w3j\">API supports multiple languages for documents with translations at a field level. Currently, fields of type <code>String<\/code> can be translatable.<\/p>\n<h3><a href=\"#configuration-4\" id=\"configuration-4\" name=\"configuration-4\" class=\"anchor\">Anchor link<\/a> <a href=\"#configuration-4\">Configuration<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">By default, a single language is used by API. It can be configured via the <code>i18n.defaultLanguage<\/code> property, which takes an <a href=\"https:\/\/en.wikipedia.org\/wiki\/List_of_ISO_639-1_codes\">ISO-639-1 code<\/a>, defaulting to <code>en<\/code> (English).<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">To support additional languages, add the ISO codes for the languages you wish to support to the <code>i18n.languages<\/code> configuration property, as an array. For example, to support French in Portuguese in addition to the default language, set <code>i18n.languages<\/code> to <code>[&#39;fr&#39;, &#39;pt&#39;]<\/code>.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>Example:<\/em><\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"i18n\"<\/span>: {\n    <span class=\"hljs-attr\">\"defaultLanguage\"<\/span>: <span class=\"hljs-string\">\"en\"<\/span>,\n    <span class=\"hljs-attr\">\"languages\"<\/span>: [<span class=\"hljs-string\">\"fr\"<\/span>, <span class=\"hljs-string\">\"pt\"<\/span>]\n  }\n}\n<\/code><\/pre>\n<h3><a href=\"#creating-multi-language-documents\" id=\"creating-multi-language-documents\" name=\"creating-multi-language-documents\" class=\"anchor\">Anchor link<\/a> <a href=\"#creating-multi-language-documents\">Creating multi-language documents<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">The name of a translated field is formed by concatenating the name of the raw field with the ISO code of the language, with a special character in the middle: <code>{NAME}:{LANGUAGE CODE}<\/code>. For example, <code>title:pt<\/code> is the Portuguese translation of the <code>title<\/code> field.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">Note that the special character that glues the name of the field with the language code is configurable via the <code>i18n.fieldCharacter<\/code> property. The default is a colon (<code>:<\/code>).<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">To create a multi-language document, use the normal <a href=\"#inserting-data\">collection endpoints<\/a> and specify a value for each of the fields you wish to translate.<\/p>\n<pre><code class=\"lang-http\"><span class=\"hljs-keyword\">POST<\/span> <span class=\"hljs-string\">\/1.0\/library\/books<\/span> HTTP\/1.1\n<span class=\"hljs-attribute\">Authorization<\/span>: Bearer afd4368e-f312-4b14-bd93-30f35a4b4814\n<span class=\"hljs-attribute\">Content-Type<\/span>: application\/json\n<span class=\"hljs-attribute\">Host<\/span>: api.somedomain.tech\n<span class=\"json\">{\n  <span class=\"hljs-attr\">\"title\"<\/span>: <span class=\"hljs-string\">\"The Little Prince\"<\/span>,\n  <span class=\"hljs-attr\">\"title:pt\"<\/span>: <span class=\"hljs-string\">\"O Principezinho\"<\/span>,\n  <span class=\"hljs-attr\">\"title:fr\"<\/span>: <span class=\"hljs-string\">\"Le Petit Prince\"<\/span>,\n  <span class=\"hljs-attr\">\"author\"<\/span>: <span class=\"hljs-string\">\"Antoine de Saint-Exup\u00e9ry\"<\/span>\n}<\/span>\n<\/code><\/pre>\n<blockquote class=\"advice\">\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Unconfigured languages<\/strong><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">Inserting a document with a translated field for a language that is not configured in <code>i18n.languages<\/code> will be accepted and will not throw a validation error, but those values will not be returned in queries. This allows languages to be worked on before they are ready for public consumption.<\/p>\n<\/blockquote>\n<h3><a href=\"#querying-multi-language-documents\" id=\"querying-multi-language-documents\" name=\"querying-multi-language-documents\" class=\"anchor\">Anchor link<\/a> <a href=\"#querying-multi-language-documents\">Querying multi-language documents<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">Clients may request the version of one or multiple documents for a specific language using the <code>lang<\/code> URL parameter, which must contain an ISO-639-1 code. When present, API will attempt to find a translation to that language for each field in the documents collected by the query. When one is found, the translation is used as the field value, otherwise the original value is picked.<\/p>\n<pre><code class=\"lang-http\"><span class=\"hljs-keyword\">GET<\/span> <span class=\"hljs-string\">\/1.0\/library\/books\/58176e72bafa53b625aebd4f?lang=fr<\/span> HTTP\/1.1\n<span class=\"hljs-attribute\">Authorization<\/span>: Bearer afd4368e-f312-4b14-bd93-30f35a4b4814\n<span class=\"hljs-attribute\">Content-Type<\/span>: application\/json\n<span class=\"hljs-attribute\">Host<\/span>: api.somedomain.tech\n<span class=\"json\">{\n  <span class=\"hljs-attr\">\"_id\"<\/span>: <span class=\"hljs-string\">\"58176e72bafa53b625aebd4f\"<\/span>,\n  <span class=\"hljs-attr\">\"_i18n\"<\/span>: {\n    <span class=\"hljs-attr\">\"title\"<\/span>: <span class=\"hljs-string\">\"fr\"<\/span>,\n    <span class=\"hljs-attr\">\"author\"<\/span>: <span class=\"hljs-string\">\"en\"<\/span>\n  },\n  <span class=\"hljs-attr\">\"title\"<\/span>: <span class=\"hljs-string\">\"Le Petit Prince\"<\/span>,\n  <span class=\"hljs-attr\">\"author\"<\/span>: <span class=\"hljs-string\">\"Antoine de Saint-Exup\u00e9ry\"<\/span>\n}<\/span>\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\">When requesting a specific language, an <code>_i18n<\/code> object is added to the response, indicating which language was used for each of the translatable fields. In the example above, we requested the French version of a document and the <code>title<\/code> field had a French translation, so that was used and reflected on <code>_i18n.title<\/code>. The <code>author<\/code> field had no French version, so the original value was used and <code>_i18n.author<\/code> contains the ISO code of the default language.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">When a <code>lang<\/code> parameter is not present, the raw content of documents is returned, containing the original value and all the language variations of each translatable field. In this case, no <code>_i18n<\/code> field is added to the documents.<\/p>\n<pre><code class=\"lang-http\"><span class=\"hljs-keyword\">GET<\/span> <span class=\"hljs-string\">\/1.0\/library\/books\/58176e72bafa53b625aebd4f<\/span> HTTP\/1.1\n<span class=\"hljs-attribute\">Authorization<\/span>: Bearer afd4368e-f312-4b14-bd93-30f35a4b4814\n<span class=\"hljs-attribute\">Content-Type<\/span>: application\/json\n<span class=\"hljs-attribute\">Host<\/span>: api.somedomain.tech\n<span class=\"json\">{\n  <span class=\"hljs-attr\">\"_id\"<\/span>: <span class=\"hljs-string\">\"58176e72bafa53b625aebd4f\"<\/span>,\n  <span class=\"hljs-attr\">\"title\"<\/span>: <span class=\"hljs-string\">\"The Little Prince\"<\/span>,\n  <span class=\"hljs-attr\">\"title:pt\"<\/span>: <span class=\"hljs-string\">\"O Principezinho\"<\/span>,\n  <span class=\"hljs-attr\">\"title:fr\"<\/span>: <span class=\"hljs-string\">\"Le Petit Prince\"<\/span>,\n  <span class=\"hljs-attr\">\"author\"<\/span>: <span class=\"hljs-string\">\"Antoine de Saint-Exup\u00e9ry\"<\/span>\n}<\/span>\n<\/code><\/pre>\n<h3><a href=\"#languages-endpoint\" id=\"languages-endpoint\" name=\"languages-endpoint\" class=\"anchor\">Anchor link<\/a> <a href=\"#languages-endpoint\">Languages endpoint<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">The languages endpoint allows authenticated users to obtain a list of all the languages supported by the API instance.<\/p>\n<details class=\"oar-method oar-method--get\">\n<summary class=\"oar-method__preview\">\n        <span class=\"oar-method-label\">GET<\/span><br \/>\n        <code class=\"oar-method__path\">\/api\/languages<\/code><br \/>\n        <span class=\"7xtjw4dqwy5mz7w3j\">List all languages<\/span><br \/>\n      <\/summary>\n<div class=\"oar-method__body\">\n<p class=\"oar-method__description\">Returns a list of all the supported languages<\/p>\n<section class=\"oar-method-section\">\n<h4>Parameters<\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">No parameters<\/p>\n<\/section>\n<section class=\"oar-method-section\">\n<h4>Responses<\/h4>\n<table>\n<thead>\n<tr>\n<th>Code<\/th>\n<th>Description<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><strong>200<\/strong><\/td>\n<td class=\"td-main\">Successful operation<br \/>\n              <br class=\"7xtjw4dqwy5mz7w3j\"><br class=\"7xtjw4dqwy5mz7w3j\"><br \/>\n              <em>Example:<\/em><br \/>\n              <br class=\"7xtjw4dqwy5mz7w3j\"><\/p>\n<pre>\n                <code>{\n  <span class=\"hljs-attr\">\"results\"<\/span>: [\n    {\n      <span class=\"hljs-attr\">\"code\"<\/span>: <span class=\"hljs-string\">\"pt\"<\/span>,\n      <span class=\"hljs-attr\">\"name\"<\/span>: <span class=\"hljs-string\">\"Portuguese\"<\/span>,\n      <span class=\"hljs-attr\">\"local\"<\/span>: <span class=\"hljs-string\">\"Portugu\u00eas\"<\/span>\n    }\n  ],\n  <span class=\"hljs-attr\">\"metadata\"<\/span>: {\n    <span class=\"hljs-attr\">\"defaultLanguage\"<\/span>: {\n      <span class=\"hljs-attr\">\"code\"<\/span>: <span class=\"hljs-string\">\"pt\"<\/span>,\n      <span class=\"hljs-attr\">\"name\"<\/span>: <span class=\"hljs-string\">\"Portuguese\"<\/span>,\n      <span class=\"hljs-attr\">\"local\"<\/span>: <span class=\"hljs-string\">\"Portugu\u00eas\"<\/span>\n    },\n    <span class=\"hljs-attr\">\"totalCount\"<\/span>: <span class=\"hljs-number\">1<\/span>\n  }\n}<\/code>\n              <\/pre>\n<\/td>\n<\/td>\n<tr>\n<td><strong>401<\/strong><\/td>\n<td class=\"td-main\">Access token is missing or invalid<\/td>\n<\/td>\n<\/tbody>\n<\/table>\n<\/section><\/div>\n<\/details>\n<h2><a href=\"#creating-database-indexes\" id=\"creating-database-indexes\" name=\"creating-database-indexes\" class=\"anchor\">Anchor link<\/a> <a href=\"#creating-database-indexes\">Creating database indexes<\/a><\/h2>\n<p class=\"7xtjw4dqwy5mz7w3j\">Indexes provide high performance read operations for frequently used queries and are fundamental in ensuring performance under load and at scale.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">Database indexes can be automatically created for a collection by specifying the fields to be indexed in the <code>settings<\/code> block.<br \/>\nAn index will be created on the collection using the fields specified in the <code>keys<\/code> property.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">An index block such as <code>{ &quot;keys&quot;: { &quot;fieldName&quot;: 1 } }<\/code> will create an index for the field <code>fieldName<\/code> using an ascending order.<br \/>\nThe order will be reversed if the <code>1<\/code> is replaced with <code>-1<\/code>. Specifying multiple fields will create a compound index.<\/p>\n<pre><code class=\"lang-json\"><span class=\"hljs-string\">\"settings\"<\/span>: {\n  <span class=\"hljs-string\">\"cache\"<\/span>: true,\n  <span class=\"hljs-string\">\"index\"<\/span>: [\n    {\n      <span class=\"hljs-string\">\"keys\"<\/span>: {\n        <span class=\"hljs-string\">\"title\"<\/span>: <span class=\"hljs-number\">1<\/span>\n      }\n    }\n  ]\n}\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\">Multiple indexes can be created for each collection, simply by adding more index blocks to the array for the <code>index<\/code> property.<\/p>\n<h3><a href=\"#index-options\" id=\"index-options\" name=\"index-options\" class=\"anchor\">Anchor link<\/a> <a href=\"#index-options\">Index Options<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">Each index also accepts an <code>options<\/code> property. The options available for an index depend on the underlying data connector being used, so it&#39;s essential that you check the documentation for the data connector to determine what is possible. For example, the MongoDB data connector is capable of creating indexes with any of the options available in the MongoDB driver, such as specifying that an index be a unique index:<\/p>\n<pre><code class=\"lang-json\"><span class=\"hljs-string\">\"index\"<\/span>: [\n  {\n    <span class=\"hljs-string\">\"keys\"<\/span>: {\n      <span class=\"hljs-string\">\"email\"<\/span>: <span class=\"hljs-number\">1<\/span>\n    },\n    <span class=\"hljs-string\">\"options\"<\/span>: {\n      <span class=\"hljs-string\">\"unique\"<\/span>: true\n    }\n  }\n]\n<\/code><\/pre>\n<h2><a href=\"#document-versioning\" id=\"document-versioning\" name=\"document-versioning\" class=\"anchor\">Anchor link<\/a> <a href=\"#document-versioning\">Document versioning<\/a><\/h2>\n<p class=\"7xtjw4dqwy5mz7w3j\">When document versioning is enabled for a collection, the state of a document will be copied prior to any update or delete operations. In practice, this means that it&#39;s possible to roll back the state of a document to any previous point in time, making operations non-destructive.<\/p>\n<h3><a href=\"#disabling-versioning\" id=\"disabling-versioning\" name=\"disabling-versioning\" class=\"anchor\">Anchor link<\/a> <a href=\"#disabling-versioning\">Disabling versioning<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">By default, versioning will be enabled on all collections. To disable it, set the <code>enableVersioning<\/code> property to <code>false<\/code> in the <a href=\"#collection-settings\">collection settings block<\/a>.<\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"settings\"<\/span>: {\n    <span class=\"hljs-attr\">\"enableVersioning\"<\/span>: <span class=\"hljs-literal\">false<\/span>\n  }\n}\n<\/code><\/pre>\n<h3><a href=\"#specifying-the-versions-collection\" id=\"specifying-the-versions-collection\" name=\"specifying-the-versions-collection\" class=\"anchor\">Anchor link<\/a> <a href=\"#specifying-the-versions-collection\">Specifying the versions collection<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">API creates an internal versioning collection for each document collection. By default, the name of this internal collection is derived from the name of the original collection and the <em>Versions<\/em> suffix. For example, a <code>products<\/code> collection would generate a versioning collection called <code>productsVersions<\/code>.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">You can customise this name by setting the <code>versioningCollection<\/code> property in the <a href=\"#collection-settings\">collection settings block<\/a>.<\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"settings\"<\/span>: {\n    <span class=\"hljs-attr\">\"versioningCollection\"<\/span>: <span class=\"hljs-string\">\"productHistory\"<\/span>\n  }\n}\n<\/code><\/pre>\n<blockquote class=\"advice\">\n<p class=\"7xtjw4dqwy5mz7w3j\">The ability to change the names of internal collections exists as a measure to avoid any potential naming clashes. Unless you fall into this edge case, there&apos;s no reason to override the default nomenclature.<\/p>\n<\/blockquote>\n<h3><a href=\"#listing-versions\" id=\"listing-versions\" name=\"listing-versions\" class=\"anchor\">Anchor link<\/a> <a href=\"#listing-versions\">Listing versions<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">The <code>versions<\/code> endpoint allows you to list all the available versions for a particular document. The response is an array containing the following properties:<\/p>\n<ul>\n<li><code>_id<\/code>: the ID of the document version<\/li>\n<li><code>_document<\/code>: the original document ID<\/li>\n<li><code>_changeDescription<\/code>: an optional message describing the operation that generated the version<\/li>\n<\/ul>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Request<\/strong><\/p>\n<pre><code class=\"lang-http\"><span class=\"hljs-keyword\">GET<\/span> <span class=\"hljs-string\">\/1.0\/library\/books\/5c54610dd10f781ca6fff603\/versions<\/span> HTTP\/1.1\n<span class=\"hljs-attribute\">Host<\/span>: api.somedomain.tech\n<span class=\"hljs-attribute\">Authorization<\/span>: Bearer 4172bbf1-0890-41c7-b0db-477095a288b6\n<span class=\"hljs-attribute\">Content-Type<\/span>: application\/json\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Response<\/strong><\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"results\"<\/span>: [\n    {\n      <span class=\"hljs-attr\">\"_id\"<\/span>: <span class=\"hljs-string\">\"5c54612ed10f781ca6fff604\"<\/span>,\n      <span class=\"hljs-attr\">\"_document\"<\/span>: <span class=\"hljs-string\">\"5c54610dd10f781ca6fff603\"<\/span>,\n      <span class=\"hljs-attr\">\"_changeDescription\"<\/span>: <span class=\"hljs-string\">\"Update author\"<\/span>\n    },\n    {\n      <span class=\"hljs-attr\">\"_id\"<\/span>: <span class=\"hljs-string\">\"5c546151d10f781ca6fff605\"<\/span>,\n      <span class=\"hljs-attr\">\"_document\"<\/span>: <span class=\"hljs-string\">\"5c54610dd10f781ca6fff603\"<\/span>\n    },\n    {\n      <span class=\"hljs-attr\">\"_id\"<\/span>: <span class=\"hljs-string\">\"5c546151d10f781ca6fff606\"<\/span>,\n      <span class=\"hljs-attr\">\"_document\"<\/span>: <span class=\"hljs-string\">\"5c54610dd10f781ca6fff603\"<\/span>,\n      <span class=\"hljs-attr\">\"_changeDescription\"<\/span>: <span class=\"hljs-string\">\"Delete book\"<\/span>\n    }        \n  ]\n}\n<\/code><\/pre>\n<h3><a href=\"#retrieving-a-specific-version\" id=\"retrieving-a-specific-version\" name=\"retrieving-a-specific-version\" class=\"anchor\">Anchor link<\/a> <a href=\"#retrieving-a-specific-version\">Retrieving a specific version<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">When querying a collection by document ID, it&#39;s possible to specify the exact version to be retrieved using the <code>version<\/code> query URL parameter.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">The result will be a snapshot of the document at that particular version, augmented with a <code>_changeDescription<\/code> property if there is a description message for the specified version.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">When retrieving a past version of a document, the <code>metadata<\/code> block will contain a <code>version<\/code> property indicating the ID of the version being accessed.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Request<\/strong><\/p>\n<pre><code class=\"lang-http\"><span class=\"hljs-keyword\">GET<\/span> <span class=\"hljs-string\">\/1.0\/library\/books\/5c54610dd10f781ca6fff603?version=5c54612ed10f781ca6fff604<\/span> HTTP\/1.1\n<span class=\"hljs-attribute\">Host<\/span>: api.somedomain.tech\n<span class=\"hljs-attribute\">Authorization<\/span>: Bearer 4172bbf1-0890-41c7-b0db-477095a288b6\n<span class=\"hljs-attribute\">Content-Type<\/span>: application\/json\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Response<\/strong><\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"results\"<\/span>: [\n    {\n      <span class=\"hljs-attr\">\"_apiVersion\"<\/span>: <span class=\"hljs-string\">\"1.0\"<\/span>,\n      <span class=\"hljs-attr\">\"_changeDescription\"<\/span>: <span class=\"hljs-string\">\"Update author\"<\/span>,\n      <span class=\"hljs-attr\">\"_createdAt\"<\/span>: <span class=\"hljs-number\">1549033741796<\/span>,\n      <span class=\"hljs-attr\">\"_createdBy\"<\/span>: <span class=\"hljs-string\">\"testClient\"<\/span>,\n      <span class=\"hljs-attr\">\"_id\"<\/span>: <span class=\"hljs-string\">\"5c54610dd10f781ca6fff603\"<\/span>,\n      <span class=\"hljs-attr\">\"title\"<\/span>: <span class=\"hljs-string\">\"Working with document versioning\"<\/span>,\n      <span class=\"hljs-attr\">\"author\"<\/span>: <span class=\"hljs-string\">\"Joe Bloggs\"<\/span>\n    }\n  ],\n  <span class=\"hljs-attr\">\"metadata\"<\/span>: {\n    <span class=\"hljs-attr\">\"limit\"<\/span>: <span class=\"hljs-number\">40<\/span>,\n    <span class=\"hljs-attr\">\"page\"<\/span>: <span class=\"hljs-number\">1<\/span>,\n    <span class=\"hljs-attr\">\"fields\"<\/span>: {},\n    <span class=\"hljs-attr\">\"sort\"<\/span>: {\n        <span class=\"hljs-attr\">\"name\"<\/span>: <span class=\"hljs-number\">1<\/span>\n    },\n    <span class=\"hljs-attr\">\"offset\"<\/span>: <span class=\"hljs-number\">0<\/span>,\n    <span class=\"hljs-attr\">\"totalCount\"<\/span>: <span class=\"hljs-number\">1<\/span>,\n    <span class=\"hljs-attr\">\"totalPages\"<\/span>: <span class=\"hljs-number\">1<\/span>,\n    <span class=\"hljs-attr\">\"version\"<\/span>: <span class=\"hljs-string\">\"5c54612ed10f781ca6fff604\"<\/span>\n  }\n}\n<\/code><\/pre>\n<h2><a href=\"#document-composition\" id=\"document-composition\" name=\"document-composition\" class=\"anchor\">Anchor link<\/a> <a href=\"#document-composition\">Document composition<\/a><\/h2>\n<p class=\"7xtjw4dqwy5mz7w3j\">To reduce data duplication caused by embedding sub-documents, DADI API allows the use of <em>Reference<\/em> fields which can best be described as pointers to other documents, which could be in the same collection, another collection in the same database or a collection in a different database.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Reference Field Settings<\/strong><\/p>\n<table>\n<thead>\n<tr>\n<th style=\"text-align:left\">Property<\/th>\n<th style=\"text-align:left\">Description<\/th>\n<th style=\"text-align:left\">Example<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td style=\"text-align:left\">collection<\/td>\n<td style=\"text-align:left\">The name of the collection that holds the reference data. Can be omitted if the field references data in the same collection as the referring document, or if the field references documents from multiple collections.<\/td>\n<td style=\"text-align:left\"><code>&quot;people&quot;<\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\">fields<\/td>\n<td style=\"text-align:left\">An array of fields to return for each referenced document.<\/td>\n<td style=\"text-align:left\"><code>[&quot;firstName&quot;, &quot;lastName&quot;]<\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\">strictCompose<\/td>\n<td style=\"text-align:left\">Whether to enable <a href=\"#strict-composition\">strict composition<\/a>. Defaults to <code>false<\/code>.<\/td>\n<td style=\"text-align:left\"><code>true<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3><a href=\"#a-simple-example\" id=\"a-simple-example\" name=\"a-simple-example\" class=\"anchor\">Anchor link<\/a> <a href=\"#a-simple-example\">A simple example<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">Consider the following two collections: <code>books<\/code> and <code>people<\/code>. <code>books<\/code> contains a <em>Reference<\/em> field <code>author<\/code> which is capable of loading documents from the <code>people<\/code> collection. By creating a <code>book<\/code> document and setting the <code>author<\/code> field to the <code>_id<\/code> value of a document from the <code>people<\/code> collection, API is able to resolve the reference and return the <code>author<\/code> as a subdocument within the response for a <code>books<\/code> query.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Books <code>(collection.books.json)<\/code><\/strong><\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"fields\"<\/span>: {\n    <span class=\"hljs-attr\">\"title\"<\/span>: {\n      <span class=\"hljs-attr\">\"type\"<\/span>: <span class=\"hljs-string\">\"String\"<\/span>\n    },\n    <span class=\"hljs-attr\">\"author\"<\/span>: {\n      <span class=\"hljs-attr\">\"type\"<\/span>: <span class=\"hljs-string\">\"Reference\"<\/span>,\n      <span class=\"hljs-attr\">\"settings\"<\/span>: {\n        <span class=\"hljs-attr\">\"collection\"<\/span>: <span class=\"hljs-string\">\"people\"<\/span>\n      }\n    }\n  }\n}\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>People <code>(collection.people.json)<\/code><\/strong><\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"fields\"<\/span>: {\n    <span class=\"hljs-attr\">\"name\"<\/span>: {\n      <span class=\"hljs-attr\">\"type\"<\/span>: <span class=\"hljs-string\">\"String\"<\/span>\n    }\n  }\n}\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Request<\/strong><\/p>\n<pre><code class=\"lang-http\"><span class=\"hljs-keyword\">POST<\/span> <span class=\"hljs-string\">\/1.0\/library\/books<\/span> HTTP\/1.1\n<span class=\"hljs-attribute\">Host<\/span>: api.somedomain.tech\n<span class=\"hljs-attribute\">Authorization<\/span>: Bearer 4172bbf1-0890-41c7-b0db-477095a288b6\n<span class=\"hljs-attribute\">Content-Type<\/span>: application\/json\n<span class=\"json\">{ <span class=\"hljs-attr\">\"title\"<\/span>: <span class=\"hljs-string\">\"For Whom The Bell Tolls\"<\/span>, <span class=\"hljs-attr\">\"author\"<\/span>: <span class=\"hljs-string\">\"560a5baf320039f7d6a78d4a\"<\/span> }<\/span>\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Response<\/strong><\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"results\"<\/span>: [\n    {\n      <span class=\"hljs-attr\">\"_id\"<\/span>: <span class=\"hljs-string\">\"560a5baf320039f1a3b68d4c\"<\/span>,\n      <span class=\"hljs-attr\">\"_composed\"<\/span>: {\n        <span class=\"hljs-attr\">\"author\"<\/span>: <span class=\"hljs-string\">\"560a5baf320039f7d6a78d4a\"<\/span>\n      },\n      <span class=\"hljs-attr\">\"author\"<\/span>: {\n        <span class=\"hljs-attr\">\"_id\"<\/span>: <span class=\"hljs-string\">\"560a5baf320039f7d6a78d4a\"<\/span>,\n        <span class=\"hljs-attr\">\"name\"<\/span>: <span class=\"hljs-string\">\"Ernest Hemingway\"<\/span>\n      }\n    }\n  ]\n}\n<\/code><\/pre>\n<h3><a href=\"#enabling-composition\" id=\"enabling-composition\" name=\"enabling-composition\" class=\"anchor\">Anchor link<\/a> <a href=\"#enabling-composition\">Enabling composition<\/a><\/h3>\n<blockquote class=\"warning\">\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Note<\/strong><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">By default, referenced documents will <strong>not<\/strong> be resolved and the raw document IDs will be shown in the response. This is by design, since resolving documents adds additional load to the processing of a request and therefore it&apos;s important that developers actively enable it only when necessary.<\/p>\n<\/blockquote>\n<p class=\"7xtjw4dqwy5mz7w3j\">Composition is the feature that allows API to resolve referenced documents before the response is delivered to the consumer. It means transforming document IDs into the actual content of the documents being referenced, and it can take place recursively for any number of levels \u2013 e.g. <code>{&quot;author&quot;: &quot;X&quot;}<\/code> resolves to a document from the <code>people<\/code> collection, which in its turn may resolve <code>{&quot;country&quot;: &quot;Y&quot;}<\/code> to a document from the <code>countries<\/code> collection, and so on.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">API will resolve a referenced document for a particular level if the referenced collection has <code>settings.compose: true<\/code> in its schema file <em>or<\/em> if there is a <code>compose<\/code> URL parameter that overrides that behaviour.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">The value of <code>compose<\/code> can be:<\/p>\n<ul>\n<li><code>false<\/code>: Stops any referenced documents from being resolved<\/li>\n<li><code>true<\/code>: Resolves all referenced documents for the current level; behaviour for nested levels depends on the value of <code>settings.compose<\/code> of the respective collections<\/li>\n<li>a number (e.g. <code>compose=N<\/code>): Resolves all referenced documents for <code>N<\/code> number of levels, including the current one<\/li>\n<li><code>all<\/code>: Resolves all referenced documents for all levels<\/li>\n<\/ul>\n<h3><a href=\"#the-_composed-property\" id=\"the-_composed-property\" name=\"the-_composed-property\" class=\"anchor\">Anchor link<\/a> <a href=\"#the-_composed-property\">The <code>_composed<\/code> property<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">When a document ID is resolved into a referenced document, the raw value of the <em>Reference<\/em> field is added to a <code>_composed<\/code> internal property. This allows consumers to determine that the result of a given field differs from its actual internal representation, which can still be accessed via the <code>_composed<\/code> property, if needed.<\/p>\n<h3><a href=\"#referencing-one-or-multiple-documents\" id=\"referencing-one-or-multiple-documents\" name=\"referencing-one-or-multiple-documents\" class=\"anchor\">Anchor link<\/a> <a href=\"#referencing-one-or-multiple-documents\">Referencing one or multiple documents<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">Reference fields can link to one or multiple documents, depending on whether the input data is an ID or an array of IDs. The input format is respected in the composed response.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Request<\/strong><\/p>\n<pre><code class=\"lang-http\"><span class=\"hljs-keyword\">POST<\/span> <span class=\"hljs-string\">\/1.0\/library\/books<\/span> HTTP\/1.1\n<span class=\"hljs-attribute\">Host<\/span>: api.somedomain.tech\n<span class=\"hljs-attribute\">Authorization<\/span>: Bearer 4172bbf1-0890-41c7-b0db-477095a288b6\n<span class=\"hljs-attribute\">Content-Type<\/span>: application\/json\n<span class=\"json\">[\n  { <span class=\"hljs-attr\">\"title\"<\/span>: <span class=\"hljs-string\">\"For Whom The Bell Tolls\"<\/span>, <span class=\"hljs-attr\">\"author\"<\/span>: <span class=\"hljs-string\">\"560a5baf320039f7d6a78d4a\"<\/span> },\n  { <span class=\"hljs-attr\">\"title\"<\/span>: <span class=\"hljs-string\">\"Nightfall\"<\/span>, <span class=\"hljs-attr\">\"author\"<\/span>: [ <span class=\"hljs-string\">\"560a5baf320039f7d6a78d1a\"<\/span>, <span class=\"hljs-string\">\"560a5baf320039f7d6a78d1a\"<\/span> ] }\n]<\/span>\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Response<\/strong><\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"results\"<\/span>: [\n    {\n      <span class=\"hljs-attr\">\"_id\"<\/span>: <span class=\"hljs-string\">\"560a5baf320039f1a3b68d4c\"<\/span>,\n      <span class=\"hljs-attr\">\"_composed\"<\/span>: {\n        <span class=\"hljs-attr\">\"author\"<\/span>: <span class=\"hljs-string\">\"560a5baf320039f7d6a78d4a\"<\/span>\n      },\n      <span class=\"hljs-attr\">\"title\"<\/span>: <span class=\"hljs-string\">\"For Whom The Bell Tolls\"<\/span>,\n      <span class=\"hljs-attr\">\"author\"<\/span>: {\n        <span class=\"hljs-attr\">\"_id\"<\/span>: <span class=\"hljs-string\">\"560a5baf320039f7d6a78d4a\"<\/span>,\n        <span class=\"hljs-attr\">\"name\"<\/span>: <span class=\"hljs-string\">\"Ernest Hemingway\"<\/span>\n      }\n    },\n    {\n      <span class=\"hljs-attr\">\"_id\"<\/span>: <span class=\"hljs-string\">\"560a5baf320039f1a3b68d4d\"<\/span>,\n      <span class=\"hljs-attr\">\"_composed\"<\/span>: {\n        <span class=\"hljs-attr\">\"author\"<\/span>: [\n          <span class=\"hljs-string\">\"560a5baf320039f7d6a78d1a\"<\/span>,\n          <span class=\"hljs-string\">\"560a5baf320039f7d6a78d1a\"<\/span> \n        ]\n      }\n      <span class=\"hljs-string\">\"title\"<\/span>: <span class=\"hljs-string\">\"Nightfall\"<\/span>,\n      <span class=\"hljs-attr\">\"author\"<\/span>: [\n        {\n          <span class=\"hljs-attr\">\"_id\"<\/span>: <span class=\"hljs-string\">\"560a5baf320039f7d6a78d1a\"<\/span>,\n          <span class=\"hljs-attr\">\"name\"<\/span>: <span class=\"hljs-string\">\"Jake Halpern\"<\/span>\n        },\n        {\n          <span class=\"hljs-attr\">\"_id\"<\/span>: <span class=\"hljs-string\">\"560a5baf320039f7d6a78d1b\"<\/span>,\n          <span class=\"hljs-attr\">\"name\"<\/span>: <span class=\"hljs-string\">\"Peter Kujawinski\"<\/span>\n        }\n      ]\n    }\n  ]\n}\n<\/code><\/pre>\n<h3><a href=\"#multi-collection-references\" id=\"multi-collection-references\" name=\"multi-collection-references\" class=\"anchor\">Anchor link<\/a> <a href=\"#multi-collection-references\">Multi-collection references<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">Rather than referencing documents from a collection that is pre-defined in the <code>settings.collection<\/code> property of the field schema, a single field can reference documents from multiple collections. If the input data is an object (or array of objects) with a <code>_collection<\/code> and <code>_data<\/code> properties, then the corresponding values will be used to determine the collection and ID of each referenced document.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Movies <code>(collection.movies.json)<\/code><\/strong><\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"fields\"<\/span>: {\n    <span class=\"hljs-attr\">\"title\"<\/span>: {\n      <span class=\"hljs-attr\">\"type\"<\/span>: <span class=\"hljs-string\">\"String\"<\/span>\n    },\n    <span class=\"hljs-attr\">\"crew\"<\/span>: {\n      <span class=\"hljs-attr\">\"type\"<\/span>: <span class=\"hljs-string\">\"Reference\"<\/span>\n    }\n  }\n}\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Directors <code>(collection.directors.json)<\/code><\/strong>, <strong>Producers <code>(collection.producers.json)<\/code><\/strong> and <strong>Writers <code>(collection.writers.json)<\/code><\/strong>:<\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"fields\"<\/span>: {\n    <span class=\"hljs-attr\">\"name\"<\/span>: {\n      <span class=\"hljs-attr\">\"type\"<\/span>: <span class=\"hljs-string\">\"String\"<\/span>\n    }\n  }\n}\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Request<\/strong><\/p>\n<pre><code class=\"lang-http\"><span class=\"hljs-keyword\">POST<\/span> <span class=\"hljs-string\">\/1.0\/library\/movies<\/span> HTTP\/1.1\n<span class=\"hljs-attribute\">Host<\/span>: api.somedomain.tech\n<span class=\"hljs-attribute\">Authorization<\/span>: Bearer 4172bbf1-0890-41c7-b0db-477095a288b6\n<span class=\"hljs-attribute\">Content-Type<\/span>: application\/json\n<span class=\"json\">{\n  <span class=\"hljs-attr\">\"title\"<\/span>: <span class=\"hljs-string\">\"Casablanca\"<\/span>,\n  <span class=\"hljs-attr\">\"crew\"<\/span>: [\n    {\n      <span class=\"hljs-attr\">\"_collection\"<\/span>: <span class=\"hljs-string\">\"writers\"<\/span>,\n      <span class=\"hljs-attr\">\"_data\"<\/span>: <span class=\"hljs-string\">\"5ac16b70bd0d9b7724b24a41\"<\/span>\n    },\n    {\n      <span class=\"hljs-attr\">\"_collection\"<\/span>: <span class=\"hljs-string\">\"directors\"<\/span>,\n      <span class=\"hljs-attr\">\"_data\"<\/span>: <span class=\"hljs-string\">\"5ac16b70bd0d9b7724b24a42\"<\/span>\n    },\n    {\n      <span class=\"hljs-attr\">\"_collection\"<\/span>: <span class=\"hljs-string\">\"producers\"<\/span>,\n      <span class=\"hljs-attr\">\"_data\"<\/span>: <span class=\"hljs-string\">\"5ac16b70bd0d9b7724b24a43\"<\/span>\n    }\n  ]\n}<\/span>\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Response<\/strong><\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"results\"<\/span>: [\n    {\n      <span class=\"hljs-attr\">\"_id\"<\/span>: <span class=\"hljs-string\">\"560a5baf320039f1a1b68d4c\"<\/span>,\n      <span class=\"hljs-attr\">\"_composed\"<\/span>: {\n        <span class=\"hljs-attr\">\"crew\"<\/span>: [\n          <span class=\"hljs-string\">\"5ac16b70bd0d9b7724b24a41\"<\/span>,\n          <span class=\"hljs-string\">\"5ac16b70bd0d9b7724b24a42\"<\/span>,\n          <span class=\"hljs-string\">\"5ac16b70bd0d9b7724b24a43\"<\/span>\n        ]\n      },\n      <span class=\"hljs-attr\">\"_refCrew\"<\/span>: {\n        <span class=\"hljs-attr\">\"5ac16b70bd0d9b7724b24a41\"<\/span>: <span class=\"hljs-string\">\"writers\"<\/span>,\n        <span class=\"hljs-attr\">\"5ac16b70bd0d9b7724b24a42\"<\/span>: <span class=\"hljs-string\">\"directors\"<\/span>,\n        <span class=\"hljs-attr\">\"5ac16b70bd0d9b7724b24a43\"<\/span>: <span class=\"hljs-string\">\"producers\"<\/span>\n      },\n      <span class=\"hljs-attr\">\"title\"<\/span>: <span class=\"hljs-string\">\"Casablanca\"<\/span>,\n      <span class=\"hljs-attr\">\"crew\"<\/span>: [\n        {\n          <span class=\"hljs-attr\">\"_id\"<\/span>: <span class=\"hljs-string\">\"5ac16b70bd0d9b7724b24a41\"<\/span>,\n          <span class=\"hljs-attr\">\"name\"<\/span>: <span class=\"hljs-string\">\"Julius J. Epstein\"<\/span>\n        },\n        {\n          <span class=\"hljs-attr\">\"_id\"<\/span>: <span class=\"hljs-string\">\"5ac16b70bd0d9b7724b24a42\"<\/span>,\n          <span class=\"hljs-attr\">\"name\"<\/span>: <span class=\"hljs-string\">\"Michael Curtiz\"<\/span>\n        },\n        {\n          <span class=\"hljs-attr\">\"_id\"<\/span>: <span class=\"hljs-string\">\"5ac16b70bd0d9b7724b24a43\"<\/span>,\n          <span class=\"hljs-attr\">\"name\"<\/span>: <span class=\"hljs-string\">\"Hal B. Wallis\"<\/span>\n        }\n      ]\n    }\n}\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\">Note the presence of <code>_refCrew<\/code> in the response. This is an internal field that maps document IDs to the names of the collections they belong to, as that information is not possible to extract from the resolved documents.<\/p>\n<h3><a href=\"#strict-composition\" id=\"strict-composition\" name=\"strict-composition\" class=\"anchor\">Anchor link<\/a> <a href=\"#strict-composition\">Strict composition<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">When API composes a set of documents, it ignores any IDs that do not match a valid document and also removes duplicate IDs from the response, returning a single instance of the repeated document. For example:<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Request<\/strong><\/p>\n<pre><code class=\"lang-http\"><span class=\"hljs-keyword\">POST<\/span> <span class=\"hljs-string\">\/1.0\/library\/movies<\/span> HTTP\/1.1\n<span class=\"hljs-attribute\">Host<\/span>: api.somedomain.tech\n<span class=\"hljs-attribute\">Authorization<\/span>: Bearer 4172bbf1-0890-41c7-b0db-477095a288b6\n<span class=\"hljs-attribute\">Content-Type<\/span>: application\/json\n<span class=\"json\">{\n  <span class=\"hljs-attr\">\"title\"<\/span>: <span class=\"hljs-string\">\"Inception\"<\/span>,\n  <span class=\"hljs-attr\">\"cast\"<\/span>: [\n    <span class=\"hljs-string\">\"5ac16b70bd0d9b7724b24a41\"<\/span>, \/\/ ID does not exist\n    <span class=\"hljs-string\">\"5ac16b70bd0d9b7724b24a42\"<\/span>,\n    <span class=\"hljs-string\">\"5ac16b70bd0d9b7724b24a42\"<\/span>, \/\/ Duplicate ID\n    <span class=\"hljs-string\">\"5ac16b70bd0d9b7724b24a43\"<\/span>\n  ]\n}<\/span>\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Response<\/strong><\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"results\"<\/span>: [\n    {\n      <span class=\"hljs-attr\">\"_id\"<\/span>: <span class=\"hljs-string\">\"560a5baf320039f1a1b68d4c\"<\/span>,\n      <span class=\"hljs-attr\">\"_composed\"<\/span>: {\n        <span class=\"hljs-attr\">\"cast\"<\/span>: [\n          <span class=\"hljs-string\">\"5ac16b70bd0d9b7724b24a41\"<\/span>,\n          <span class=\"hljs-string\">\"5ac16b70bd0d9b7724b24a42\"<\/span>,\n          <span class=\"hljs-string\">\"5ac16b70bd0d9b7724b24a42\"<\/span>,\n          <span class=\"hljs-string\">\"5ac16b70bd0d9b7724b24a43\"<\/span>\n        ]\n      },\n      <span class=\"hljs-attr\">\"title\"<\/span>: <span class=\"hljs-string\">\"Inception\"<\/span>,\n      <span class=\"hljs-attr\">\"cast\"<\/span>: [\n        {\n          <span class=\"hljs-attr\">\"_id\"<\/span>: <span class=\"hljs-string\">\"5ac16b70bd0d9b7724b24a42\"<\/span>,\n          <span class=\"hljs-attr\">\"name\"<\/span>: <span class=\"hljs-string\">\"Leonardo DiCaprio\"<\/span>\n        },\n        {\n          <span class=\"hljs-attr\">\"_id\"<\/span>: <span class=\"hljs-string\">\"5ac16b70bd0d9b7724b24a43\"<\/span>,\n          <span class=\"hljs-attr\">\"name\"<\/span>: <span class=\"hljs-string\">\"Ellen Page\"<\/span>\n        }\n      ]\n    }\n}\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\">This behaviour can be changed by setting <code>{&quot;strictCompose&quot;: true}<\/code> in the <code>settings<\/code> block of the Reference field. This tells API to produce an exact mapping of the input object, leaving <code>null<\/code> in the place of document IDs that do not match any documents, and resolving duplicate IDs multiple times. Here&#39;s how the response for the request above would look like if <code>cast<\/code> had strict composition enabled.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Response<\/strong><\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"results\"<\/span>: [\n    {\n      <span class=\"hljs-attr\">\"_id\"<\/span>: <span class=\"hljs-string\">\"560a5baf320039f1a1b68d4c\"<\/span>,\n      <span class=\"hljs-attr\">\"_composed\"<\/span>: {\n        <span class=\"hljs-attr\">\"cast\"<\/span>: [\n          <span class=\"hljs-string\">\"5ac16b70bd0d9b7724b24a41\"<\/span>,\n          <span class=\"hljs-string\">\"5ac16b70bd0d9b7724b24a42\"<\/span>,\n          <span class=\"hljs-string\">\"5ac16b70bd0d9b7724b24a42\"<\/span>,\n          <span class=\"hljs-string\">\"5ac16b70bd0d9b7724b24a43\"<\/span>\n        ]\n      },\n      <span class=\"hljs-attr\">\"title\"<\/span>: <span class=\"hljs-string\">\"Inception\"<\/span>,\n      <span class=\"hljs-attr\">\"cast\"<\/span>: [\n        <span class=\"hljs-literal\">null<\/span>,\n        {\n          <span class=\"hljs-attr\">\"_id\"<\/span>: <span class=\"hljs-string\">\"5ac16b70bd0d9b7724b24a42\"<\/span>,\n          <span class=\"hljs-attr\">\"name\"<\/span>: <span class=\"hljs-string\">\"Leonardo DiCaprio\"<\/span>\n        },\n        {\n          <span class=\"hljs-attr\">\"_id\"<\/span>: <span class=\"hljs-string\">\"5ac16b70bd0d9b7724b24a42\"<\/span>,\n          <span class=\"hljs-attr\">\"name\"<\/span>: <span class=\"hljs-string\">\"Leonardo DiCaprio\"<\/span>\n        },\n        {\n          <span class=\"hljs-attr\">\"_id\"<\/span>: <span class=\"hljs-string\">\"5ac16b70bd0d9b7724b24a43\"<\/span>,\n          <span class=\"hljs-attr\">\"name\"<\/span>: <span class=\"hljs-string\">\"Ellen Page\"<\/span>\n        }\n      ]\n    }\n}\n<\/code><\/pre>\n<h3><a href=\"#pre-composed-documents\" id=\"pre-composed-documents\" name=\"pre-composed-documents\" class=\"anchor\">Anchor link<\/a> <a href=\"#pre-composed-documents\">Pre-composed documents<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">Setting the content of a Reference field to one or multiple document IDs is the simplest way of referencing documents, but it creates some complexity for consumer apps that wish to insert multiple levels of referenced documents.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">For example, imagine that you want to create a book <em>and<\/em> its author. You would:<\/p>\n<ol>\n<li>Create the author document<\/li>\n<li>Grab the document ID from step 1 and add it to the <code>author<\/code> property of a new book<\/li>\n<li>Create the book document<\/li>\n<\/ol>\n<p class=\"7xtjw4dqwy5mz7w3j\">You can see how this would get increasingly complex if you wanted to insert more levels. To address that, and as an alternative to receiving just document IDs, API is capable of processing a pre-composed set of documents and figure out what to do with the data, including creating and updating documents, as well as populating Reference fields with the right document IDs.<\/p>\n<h4><a href=\"#creating-documents\" id=\"creating-documents\" name=\"creating-documents\" class=\"anchor\">Anchor link<\/a> <a href=\"#creating-documents\">Creating documents<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">When the content of a Reference field is an object <em>without<\/em> an ID, a corresponding document is created in the collection defined by the <code>settings.collection<\/code> property of the field schema. If an array is sent, multiple documents will be created.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Request<\/strong><\/p>\n<pre><code class=\"lang-http\"><span class=\"hljs-keyword\">POST<\/span> <span class=\"hljs-string\">\/1.0\/library\/books<\/span> HTTP\/1.1\n<span class=\"hljs-attribute\">Host<\/span>: api.somedomain.tech\n<span class=\"hljs-attribute\">Authorization<\/span>: Bearer 4172bbf1-0890-41c7-b0db-477095a288b6\n<span class=\"hljs-attribute\">Content-Type<\/span>: application\/json\n<span class=\"json\">[\n  {\n    <span class=\"hljs-attr\">\"title\"<\/span>: <span class=\"hljs-string\">\"For Whom The Bell Tolls\"<\/span>,\n    <span class=\"hljs-attr\">\"author\"<\/span>: { <span class=\"hljs-attr\">\"name\"<\/span>: <span class=\"hljs-string\">\"Ernest Hemingway\"<\/span> }\n  },\n  {\n    <span class=\"hljs-attr\">\"title\"<\/span>: <span class=\"hljs-string\">\"Nightfall\"<\/span>,\n    <span class=\"hljs-attr\">\"author\"<\/span>: [\n      { <span class=\"hljs-attr\">\"name\"<\/span>: <span class=\"hljs-string\">\"Jake Halpern\"<\/span> },\n      { <span class=\"hljs-attr\">\"name\"<\/span>: <span class=\"hljs-string\">\"Peter Kujawinski\"<\/span> }\n    ]\n  }\n]<\/span>\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Response<\/strong><\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"results\"<\/span>: [\n    {\n      <span class=\"hljs-attr\">\"_id\"<\/span>: <span class=\"hljs-string\">\"560a5baf320039f1a3b68d4c\"<\/span>,\n      <span class=\"hljs-attr\">\"_composed\"<\/span>: {\n        <span class=\"hljs-attr\">\"author\"<\/span>: <span class=\"hljs-string\">\"560a5baf320039f7d6a78d4a\"<\/span>\n      },\n      <span class=\"hljs-attr\">\"title\"<\/span>: <span class=\"hljs-string\">\"For Whom The Bell Tolls\"<\/span>,\n      <span class=\"hljs-attr\">\"author\"<\/span>: {\n        <span class=\"hljs-attr\">\"_id\"<\/span>: <span class=\"hljs-string\">\"560a5baf320039f7d6a78d4a\"<\/span>,\n        <span class=\"hljs-attr\">\"name\"<\/span>: <span class=\"hljs-string\">\"Ernest Hemingway\"<\/span>\n      }\n    },\n    {\n      <span class=\"hljs-attr\">\"_id\"<\/span>: <span class=\"hljs-string\">\"560a5baf320039f1a3b68d4d\"<\/span>,\n      <span class=\"hljs-attr\">\"_composed\"<\/span>: {\n        <span class=\"hljs-attr\">\"author\"<\/span>: [\n          <span class=\"hljs-string\">\"560a5baf320039f7d6a78d1a\"<\/span>,\n          <span class=\"hljs-string\">\"560a5baf320039f7d6a78d1b\"<\/span>\n        ]\n      },\n      <span class=\"hljs-attr\">\"title\"<\/span>: <span class=\"hljs-string\">\"Nightfall\"<\/span>,\n      <span class=\"hljs-attr\">\"author\"<\/span>: [\n        {\n          <span class=\"hljs-attr\">\"_id\"<\/span>: <span class=\"hljs-string\">\"560a5baf320039f7d6a78d1a\"<\/span>,\n          <span class=\"hljs-attr\">\"name\"<\/span>: <span class=\"hljs-string\">\"Jake Halpern\"<\/span>\n        },\n        {\n          <span class=\"hljs-attr\">\"_id\"<\/span>: <span class=\"hljs-string\">\"560a5baf320039f7d6a78d1b\"<\/span>,\n          <span class=\"hljs-attr\">\"name\"<\/span>: <span class=\"hljs-string\">\"Peter Kujawinski\"<\/span>\n        }\n      ]\n    }\n  ]\n}\n<\/code><\/pre>\n<h4><a href=\"#updating-documents\" id=\"updating-documents\" name=\"updating-documents\" class=\"anchor\">Anchor link<\/a> <a href=\"#updating-documents\">Updating documents<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">When the content of a Reference field is an object <em>with<\/em> an ID, API updates the document referenced by that ID with the new sub-document.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">The example below creates a new book and sets an existing document (<code>560a5baf320039f7d6a78d4a<\/code>) as its author, but it also makes an update to the referenced document \u2013 in this case, <code>name<\/code> is changed to <code>&quot;Ernest Miller Hemingway&quot;<\/code>.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Request<\/strong><\/p>\n<pre><code class=\"lang-http\"><span class=\"hljs-keyword\">POST<\/span> <span class=\"hljs-string\">\/1.0\/library\/books<\/span> HTTP\/1.1\n<span class=\"hljs-attribute\">Host<\/span>: api.somedomain.tech\n<span class=\"hljs-attribute\">Authorization<\/span>: Bearer 4172bbf1-0890-41c7-b0db-477095a288b6\n<span class=\"hljs-attribute\">Content-Type<\/span>: application\/json\n<span class=\"json\">[\n  {\n    <span class=\"hljs-attr\">\"title\"<\/span>: <span class=\"hljs-string\">\"For Whom The Bell Tolls\"<\/span>,\n    <span class=\"hljs-attr\">\"author\"<\/span>: {\n      <span class=\"hljs-attr\">\"_id\"<\/span>: <span class=\"hljs-string\">\"560a5baf320039f7d6a78d4a\"<\/span>,\n      <span class=\"hljs-attr\">\"name\"<\/span>: <span class=\"hljs-string\">\"Ernest Miller Hemingway\"<\/span>\n    }\n  }\n]<\/span>\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Response<\/strong><\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"results\"<\/span>: [\n    {\n      <span class=\"hljs-attr\">\"_id\"<\/span>: <span class=\"hljs-string\">\"560a5baf320039f1a3b68d4c\"<\/span>,\n      <span class=\"hljs-attr\">\"_composed\"<\/span>: {\n        <span class=\"hljs-attr\">\"author\"<\/span>: <span class=\"hljs-string\">\"560a5baf320039f7d6a78d4a\"<\/span>\n      },\n      <span class=\"hljs-attr\">\"title\"<\/span>: <span class=\"hljs-string\">\"For Whom The Bell Tolls\"<\/span>,\n      <span class=\"hljs-attr\">\"author\"<\/span>: {\n        <span class=\"hljs-attr\">\"_id\"<\/span>: <span class=\"hljs-string\">\"560a5baf320039f7d6a78d4a\"<\/span>,\n        <span class=\"hljs-attr\">\"name\"<\/span>: <span class=\"hljs-string\">\"Ernest Miller Hemingway\"<\/span>\n      }\n    }\n  ]\n}\n<\/code><\/pre>\n<h4><a href=\"#multi-collection-references-1\" id=\"multi-collection-references-1\" name=\"multi-collection-references-1\" class=\"anchor\">Anchor link<\/a> <a href=\"#multi-collection-references-1\">Multi-collection references<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">It&#39;s possible to insert pre-composed documents that use the multi-collection reference syntax, as long as the pre-composed documents are inside the <code>_data<\/code> property of the outermost object in the Reference field value.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">The example below shows how the various scenarios can be mixed and matched: the first element of <code>crew<\/code> is a new document to be created in the <code>writers<\/code> collection (no ID); the second item is a document ID, which will be stored as is in the <code>directors<\/code> collection; the third item references an existing document from the <code>producers<\/code> collection, whose <code>name<\/code> will be updated to a new value.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Request<\/strong><\/p>\n<pre><code class=\"lang-http\"><span class=\"hljs-keyword\">POST<\/span> <span class=\"hljs-string\">\/1.0\/library\/movies<\/span> HTTP\/1.1\n<span class=\"hljs-attribute\">Host<\/span>: api.somedomain.tech\n<span class=\"hljs-attribute\">Authorization<\/span>: Bearer 4172bbf1-0890-41c7-b0db-477095a288b6\n<span class=\"hljs-attribute\">Content-Type<\/span>: application\/json\n<span class=\"json\">{\n  <span class=\"hljs-attr\">\"title\"<\/span>: <span class=\"hljs-string\">\"Casablanca\"<\/span>,\n  <span class=\"hljs-attr\">\"crew\"<\/span>: [\n    {\n      <span class=\"hljs-attr\">\"_collection\"<\/span>: <span class=\"hljs-string\">\"writers\"<\/span>,\n      <span class=\"hljs-attr\">\"_data\"<\/span>: {\n        <span class=\"hljs-attr\">\"name\"<\/span>: <span class=\"hljs-string\">\"Julius J. Epstein\"<\/span>\n      }\n    },\n    {\n      <span class=\"hljs-attr\">\"_collection\"<\/span>: <span class=\"hljs-string\">\"directors\"<\/span>,\n      <span class=\"hljs-attr\">\"_data\"<\/span>: <span class=\"hljs-string\">\"5ac16b70bd0d9b7724b24a42\"<\/span>\n    },\n    {\n      <span class=\"hljs-attr\">\"_collection\"<\/span>: <span class=\"hljs-string\">\"producers\"<\/span>,\n      <span class=\"hljs-attr\">\"_data\"<\/span>: {\n        <span class=\"hljs-attr\">\"_id\"<\/span>: <span class=\"hljs-string\">\"5ac16b70bd0d9b7724b24a43\"<\/span>,\n        <span class=\"hljs-attr\">\"name\"<\/span>: <span class=\"hljs-string\">\"Hal Brent Wallis\"<\/span>\n      }\n    }\n  ]\n}<\/span>\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Response<\/strong><\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"results\"<\/span>: [\n    {\n      <span class=\"hljs-attr\">\"_id\"<\/span>: <span class=\"hljs-string\">\"560a5baf320039f1a1b68d4c\"<\/span>,\n      <span class=\"hljs-attr\">\"_composed\"<\/span>: {\n        <span class=\"hljs-attr\">\"crew\"<\/span>: [\n          <span class=\"hljs-string\">\"5ac16b70bd0d9b7724b24a41\"<\/span>,\n          <span class=\"hljs-string\">\"5ac16b70bd0d9b7724b24a42\"<\/span>,\n          <span class=\"hljs-string\">\"5ac16b70bd0d9b7724b24a43\"<\/span>\n        ]\n      },\n      <span class=\"hljs-attr\">\"_refCrew\"<\/span>: {\n        <span class=\"hljs-attr\">\"5ac16b70bd0d9b7724b24a41\"<\/span>: <span class=\"hljs-string\">\"writers\"<\/span>,\n        <span class=\"hljs-attr\">\"5ac16b70bd0d9b7724b24a42\"<\/span>: <span class=\"hljs-string\">\"directors\"<\/span>,\n        <span class=\"hljs-attr\">\"5ac16b70bd0d9b7724b24a43\"<\/span>: <span class=\"hljs-string\">\"producers\"<\/span>\n      },\n      <span class=\"hljs-attr\">\"title\"<\/span>: <span class=\"hljs-string\">\"Casablanca\"<\/span>,\n      <span class=\"hljs-attr\">\"crew\"<\/span>: [\n        {\n          <span class=\"hljs-attr\">\"_id\"<\/span>: <span class=\"hljs-string\">\"5ac16b70bd0d9b7724b24a41\"<\/span>,\n          <span class=\"hljs-attr\">\"name\"<\/span>: <span class=\"hljs-string\">\"Julius J. Epstein\"<\/span>\n        },\n        {\n          <span class=\"hljs-attr\">\"_id\"<\/span>: <span class=\"hljs-string\">\"5ac16b70bd0d9b7724b24a42\"<\/span>,\n          <span class=\"hljs-attr\">\"name\"<\/span>: <span class=\"hljs-string\">\"Michael Curtiz\"<\/span>\n        },\n        {\n          <span class=\"hljs-attr\">\"_id\"<\/span>: <span class=\"hljs-string\">\"5ac16b70bd0d9b7724b24a43\"<\/span>,\n          <span class=\"hljs-attr\">\"name\"<\/span>: <span class=\"hljs-string\">\"Hal Brent Wallis\"<\/span>\n        }\n      ]\n    }\n  ]\n}\n<\/code><\/pre>\n<h3><a href=\"#limiting-fields-of-referenced-documents\" id=\"limiting-fields-of-referenced-documents\" name=\"limiting-fields-of-referenced-documents\" class=\"anchor\">Anchor link<\/a> <a href=\"#limiting-fields-of-referenced-documents\">Limiting fields of referenced documents<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">When a reference is resolved, the entire referenced document will be included by default, but it&#39;s possible to limit the fields that will be included in the composed response. You can do this by specifying a <code>fields<\/code> array within the <code>settings<\/code> block of the <em>Reference<\/em> field&#39;s schema.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Books <code>(collection.books.json)<\/code><\/strong><\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"fields\"<\/span>: {\n    <span class=\"hljs-attr\">\"title\"<\/span>: {\n      <span class=\"hljs-attr\">\"type\"<\/span>: <span class=\"hljs-string\">\"String\"<\/span>\n    },\n    <span class=\"hljs-attr\">\"author\"<\/span>: {\n      <span class=\"hljs-attr\">\"type\"<\/span>: <span class=\"hljs-string\">\"Reference\"<\/span>,\n      <span class=\"hljs-attr\">\"settings\"<\/span>: {\n        <span class=\"hljs-attr\">\"collection\"<\/span>: <span class=\"hljs-string\">\"people\"<\/span>,\n        <span class=\"hljs-attr\">\"fields\"<\/span>: [<span class=\"hljs-string\">\"firstName\"<\/span>, <span class=\"hljs-string\">\"lastName\"<\/span>]\n      }\n    }\n  }\n}\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\">Alternatively, you can specify the fields to be retrieved for each <em>Reference<\/em> field using the <code>fields<\/code> URL parameter with dot-notation. The following request instructs API to get all books, limiting the fields returned to <code>title<\/code> and <code>author<\/code>, with the latter only showing the fields <code>name<\/code> and <code>occupation<\/code> from the referenced collection.<\/p>\n<pre><code class=\"lang-http\"><span class=\"hljs-keyword\">GET<\/span> <span class=\"hljs-string\">\/1.0\/library\/books?fields={\"title\":1,\"author.name\":1,\"author.occupation\":1}<\/span> HTTP\/1.1\n<span class=\"hljs-attribute\">Host<\/span>: api.somedomain.tech\n<span class=\"hljs-attribute\">Authorization<\/span>: Bearer 4172bbf1-0890-41c7-b0db-477095a288b6\n<span class=\"hljs-attribute\">Content-Type<\/span>: application\/json\n<\/code><\/pre>\n<h2><a href=\"#collection-statistics\" id=\"collection-statistics\" name=\"collection-statistics\" class=\"anchor\">Anchor link<\/a> <a href=\"#collection-statistics\">Collection statistics<\/a><\/h2>\n<p class=\"7xtjw4dqwy5mz7w3j\">Collection statistics can be retrieved by sending a GET request to a collection&#39;s <code>\/stats<\/code> endpoint:<\/p>\n<pre><code class=\"lang-http\"><span class=\"hljs-keyword\">GET<\/span> <span class=\"hljs-string\">\/1.0\/library\/books\/stats<\/span> HTTP\/1.1\n<span class=\"hljs-attribute\">Host<\/span>: api.somedomain.tech\n<span class=\"hljs-attribute\">Content-Type<\/span>: application\/json\n<span class=\"hljs-attribute\">Cache-Control<\/span>: no-cache\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\">An example response when using the MongoDB data connector:<\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"count\"<\/span>: <span class=\"hljs-number\">2<\/span>,\n  <span class=\"hljs-attr\">\"size\"<\/span>: <span class=\"hljs-number\">480<\/span>,\n  <span class=\"hljs-attr\">\"averageObjectSize\"<\/span>: <span class=\"hljs-number\">240<\/span>,\n  <span class=\"hljs-attr\">\"storageSize\"<\/span>: <span class=\"hljs-number\">8192<\/span>,\n  <span class=\"hljs-attr\">\"indexes\"<\/span>: <span class=\"hljs-number\">1<\/span>,\n  <span class=\"hljs-attr\">\"totalIndexSize\"<\/span>: <span class=\"hljs-number\">8176<\/span>,\n  <span class=\"hljs-attr\">\"indexSizes\"<\/span>: { <span class=\"hljs-attr\">\"_id_\"<\/span>: <span class=\"hljs-number\">8176<\/span> }\n}\n<\/code><\/pre>\n<h2><a href=\"#adding-application-logic\" id=\"adding-application-logic\" name=\"adding-application-logic\" class=\"anchor\">Anchor link<\/a> <a href=\"#adding-application-logic\">Adding application logic<\/a><\/h2>\n<h3><a href=\"#endpoints\" id=\"endpoints\" name=\"endpoints\" class=\"anchor\">Anchor link<\/a> <a href=\"#endpoints\">Endpoints<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">DADI API custom endpoints give you the ability to modify, enrich and massage your data before it is returned to the user making the request. Collection endpoints return raw data in response to requests, whereas custom endpoints give you more control over what you return.<\/p>\n<h4><a href=\"#endpoint-specification\" id=\"endpoint-specification\" name=\"endpoint-specification\" class=\"anchor\">Anchor link<\/a> <a href=\"#endpoint-specification\">Endpoint Specification<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">Endpoint specifications are simply JavaScript files stored in your application&#39;s <code>\/workspace\/endpoints<\/code> folder. It is important to understand how the folder hierarchy in the endpoints folder affects the behaviour of your API.<\/p>\n<pre><code><span class=\"hljs-keyword\">my<\/span>-api\/\n  workspace\/\n    collections\/                    <span class=\"hljs-comment\"># MongoDB collection specifications<\/span>\n      <span class=\"hljs-number\">1.0<\/span>\/                          <span class=\"hljs-comment\"># API version label<\/span>\n    endpoints\/                      <span class=\"hljs-comment\"># Custom Javascript endpoints<\/span>\n      <span class=\"hljs-number\">1.0<\/span>\/                          <span class=\"hljs-comment\"># API version label<\/span>\n<\/code><\/pre>\n<h4><a href=\"#endpoint\" id=\"endpoint\" name=\"endpoint\" class=\"anchor\">Anchor link<\/a> <a href=\"#endpoint\">Endpoint<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">Endpoint specifications exist as JavaScript files within a <code>version<\/code> folder as mentioned above. The naming convention for the collection specifications is <code>endpoint.&lt;endpoint name&gt;.js<\/code><\/p>\n<h4><a href=\"#endpoint-url\" id=\"endpoint-url\" name=\"endpoint-url\" class=\"anchor\">Anchor link<\/a> <a href=\"#endpoint-url\">Endpoint URL<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">With the above folder and file hierarchy an endpoint&#39;s URL uses the following format:<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><code>https:\/\/api.somedomain.tech\/{version}\/{endpoint name}<\/code><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">In actual use this might look like the following:<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><code>https:\/\/api.somedomain.tech\/1.0\/booksByAuthor<\/code><\/p>\n<h4><a href=\"#the-endpoint-file\" id=\"the-endpoint-file\" name=\"the-endpoint-file\" class=\"anchor\">Anchor link<\/a> <a href=\"#the-endpoint-file\">The Endpoint file<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">Endpoint specification files should export functions with lowercase names that correspond to the HTTP method that the function is designed to handle.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">For example:<\/p>\n<pre><code class=\"lang-js\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">module<\/span>.<span class=\"hljs-title\">exports<\/span>.<span class=\"hljs-title\">get<\/span> =<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-params\">(req, res, next)<\/span> {<\/span>\n}\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">module<\/span>.<span class=\"hljs-title\">exports<\/span>.<span class=\"hljs-title\">post<\/span> =<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-params\">(req, res, next)<\/span> {<\/span>\n}\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\">Each function receives the following three arguments:<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><code>(request, response, next)<\/code><\/p>\n<ol>\n<li><code>request<\/code> is an instance of Node&#39;s <a href=\"https:\/\/nodejs.org\/api\/http.html#http_class_http_incomingmessage\">http.IncomingMessage<\/a><\/li>\n<li><code>response<\/code> is an instance of Node&#39;s <a href=\"https:\/\/nodejs.org\/api\/http.html#http_class_http_serverresponse\">http.ServerResponse<\/a><\/li>\n<li><code>next<\/code> is a function that can be passed an error or called if this endpoint has nothing to do.  Passing an error, e.g. <code>next(err)<\/code> will result in an HTTP 500 response. Calling <code>next()<\/code> will respond with an HTTP 404.<\/li>\n<\/ol>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Example, HTTP 200 response<\/strong><\/p>\n<pre><code class=\"lang-js\">module.exports.<span class=\"hljs-built_in\">get<\/span> = <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-params\">(req, res, next)<\/span> {<\/span>\n  <span class=\"hljs-keyword\">let<\/span> data = {\n    result<span class=\"hljs-variable\">s:<\/span> [\n      {\n        title: <span class=\"hljs-string\">'Book One'<\/span>,\n        author: <span class=\"hljs-string\">'Benjamin Franklin'<\/span>\n      }\n    ]\n  }\n  <span class=\"hljs-keyword\">res<\/span>.setHeader(<span class=\"hljs-string\">'content-type'<\/span>, <span class=\"hljs-string\">'application\/json'<\/span>)\n  <span class=\"hljs-keyword\">res<\/span>.statusCode = <span class=\"hljs-number\">200<\/span>\n  <span class=\"hljs-keyword\">res<\/span>.end(JSON.stringify(data))\n}\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Example, HTTP 404 response<\/strong><\/p>\n<pre><code class=\"lang-js\">module.exports.<span class=\"hljs-built_in\">get<\/span> = <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-params\">(req, res, next)<\/span> {<\/span>\n  <span class=\"hljs-keyword\">res<\/span>.setHeader(<span class=\"hljs-string\">'content-type'<\/span>, <span class=\"hljs-string\">'application\/json'<\/span>)\n  <span class=\"hljs-keyword\">res<\/span>.statusCode = <span class=\"hljs-number\">404<\/span>\n  <span class=\"hljs-keyword\">res<\/span>.end()\n}\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Example, HTTP 500 response<\/strong><\/p>\n<pre><code class=\"lang-js\">module.exports.<span class=\"hljs-built_in\">get<\/span> = <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-params\">(req, res, next)<\/span> {<\/span>\n  <span class=\"hljs-keyword\">let<\/span> error = {\n    error<span class=\"hljs-variable\">s:<\/span> [\n      <span class=\"hljs-string\">'An error occured while processing your request'<\/span>\n    ]\n  }\n  <span class=\"hljs-keyword\">res<\/span>.setHeader(<span class=\"hljs-string\">'content-type'<\/span>, <span class=\"hljs-string\">'application\/json'<\/span>)\n  <span class=\"hljs-keyword\">res<\/span>.statusCode = <span class=\"hljs-number\">500<\/span>\n  <span class=\"hljs-keyword\">res<\/span>.end(JSON.stringify(error))\n}\n<\/code><\/pre>\n<h5><a href=\"#custom-endpoint-routing\" id=\"custom-endpoint-routing\" name=\"custom-endpoint-routing\" class=\"anchor\">Anchor link<\/a> <a href=\"#custom-endpoint-routing\">Custom Endpoint Routing<\/a><\/h5>\n<p class=\"7xtjw4dqwy5mz7w3j\">It is possible to override the default endpoint route by including a <code>config<\/code> function in the endpoint file. The function should return a <code>config<\/code> object with a <code>route<\/code> property. The value of this property will be used for the endpoint&#39;s route.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">The following example returns a config object with a route that specifies an optional request parameter, <code>id<\/code>.<\/p>\n<pre><code class=\"lang-js\"><span class=\"hljs-built_in\">module<\/span>.exports.config = <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> (<span class=\"hljs-params\">&nbsp;<\/span>) <\/span>{\n  <span class=\"hljs-keyword\">return<\/span> {\n    <span class=\"hljs-attr\">route<\/span>: <span class=\"hljs-string\">'\/1.0\/books\/:id([a-fA-F0-9]{24})?'<\/span>\n  }\n}\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\">This route will now respond to requests such as<\/p>\n<pre><code>https:<span class=\"hljs-regexp\">\/\/<\/span>api.somedomain.tech<span class=\"hljs-regexp\">\/1.0\/<\/span>books<span class=\"hljs-regexp\">\/55bb8f688d76f74b1303a137<\/span>\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\">Without this custom route, the same could be achieved by requesting the default route with a querystring parameter.<\/p>\n<pre><code>https:<span class=\"hljs-regexp\">\/\/<\/span>api.somedomain.tech<span class=\"hljs-regexp\">\/1.0\/<\/span>books?id=<span class=\"hljs-number\">55<\/span>bb8f688d76f74b1303a137\n<\/code><\/pre>\n<h4><a href=\"#authentication-1\" id=\"authentication-1\" name=\"authentication-1\" class=\"anchor\">Anchor link<\/a> <a href=\"#authentication-1\">Authentication<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">Authentication can be bypassed for your custom endpoint by adding the following to your endpoint file:<\/p>\n<pre><code class=\"lang-js\">module<span class=\"hljs-selector-class\">.exports<\/span><span class=\"hljs-selector-class\">.model<\/span> = {}\nmodule<span class=\"hljs-selector-class\">.exports<\/span><span class=\"hljs-selector-class\">.model<\/span><span class=\"hljs-selector-class\">.settings<\/span> = { authenticate : false }\n<\/code><\/pre>\n<h3><a href=\"#hooks\" id=\"hooks\" name=\"hooks\" class=\"anchor\">Anchor link<\/a> <a href=\"#hooks\">Hooks<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">Hooks perform operations on data before\/after GET, UPDATE and DELETE requests. In essence, a hook is simply a function that intercepts a document\/query before it&#39;s executed, having the option to modify it before returning it back to the model.<\/p>\n<h4><a href=\"#use-cases\" id=\"use-cases\" name=\"use-cases\" class=\"anchor\">Anchor link<\/a> <a href=\"#use-cases\">Use cases<\/a><\/h4>\n<ul>\n<li>Creating variations of a field, such as creating a slug (example above);<\/li>\n<li>Validating fields with complex conditions, when a regular expression might not be enough;<\/li>\n<li>Triggering an action, notification or external command when a record is modified.<\/li>\n<\/ul>\n<h4><a href=\"#anatomy-of-a-hook\" id=\"anatomy-of-a-hook\" name=\"anatomy-of-a-hook\" class=\"anchor\">Anchor link<\/a> <a href=\"#anatomy-of-a-hook\">Anatomy of a hook<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">A hook is stored as an individual file in a <code>hooks<\/code> directory (defaulting to <code>\/workspace\/hooks<\/code>) and can be used by being attached to <code>create<\/code>, <code>update<\/code> or <code>delete<\/code> operations in the <code>settings<\/code> section of a collection schema specification.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>collections.user.json<\/em>:<\/p>\n<pre><code><span class=\"hljs-string\">\"settings\"<\/span>: {\n  <span class=\"hljs-string\">\"hooks\"<\/span>: {\n    <span class=\"hljs-string\">\"create\"<\/span>: [<span class=\"hljs-string\">\"myhook1\"<\/span>, <span class=\"hljs-string\">\"myhook2\"<\/span>]\n  }\n}\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\">This means that whenever a new user is created, the document that is about to be inserted will be passed to <code>myhook1<\/code>, its return value will then be passed on to <code>myhook2<\/code> and so on. After all the hooks finish executing, the final document will be returned to the model to be inserted in the database.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">The order in which hooks are executed is defined by the order of the items in the array.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">The following example defines a very simple hook, which will change the <code>name<\/code> field of a document before returning it.<\/p>\n<pre><code class=\"lang-js\"><span class=\"hljs-keyword\">module<\/span>.exports = <span class=\"hljs-keyword\">function<\/span> (<span class=\"hljs-meta\">doc<\/span>, type, data) {\n  <span class=\"hljs-meta\">doc<\/span>.name = <span class=\"hljs-string\">'Modified by the hook'<\/span>\n  <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-meta\">doc<\/span>\n}\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\">This particular hook will receive a document, change a property (<code>name<\/code>) and return it back. So if attached to the <code>create<\/code> event, it will make all the created documents have <code>name<\/code> set to <code>Modified by the hook<\/code>.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">However, this logic ties the hook to the schema \u2014 what happens if we want to modify a property other than <code>name<\/code>? Hooks are supposed to be able to add functionality to a document, and should be approached as interchangeable building blocks rather than pieces of functionality tightly coupled with a schema.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">For that reason, developers might have the need to pass extra information to the hook \u2014 e.g. inform the hook the name of the properties that should be modified. As such, in addition to the syntax shown above for declaring a hook (an array of strings), an alternative one allows data to be passed through a <code>options<\/code> object.<\/p>\n<pre><code class=\"lang-json\"><span class=\"hljs-string\">\"settings\"<\/span>: {\n  <span class=\"hljs-string\">\"hooks\"<\/span>: {\n    <span class=\"hljs-string\">\"beforeCreate\"<\/span>: [\n      {\n        <span class=\"hljs-string\">\"hook\"<\/span>: <span class=\"hljs-string\">\"slugify\"<\/span>,\n        <span class=\"hljs-string\">\"options\"<\/span>: {\n          <span class=\"hljs-string\">\"from\"<\/span>: <span class=\"hljs-string\">\"title\"<\/span>,\n          <span class=\"hljs-string\">\"to\"<\/span>: <span class=\"hljs-string\">\"slug\"<\/span>\n        }\n      }\n    ]\n  }\n}\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\">In this example we implement a hook that populates a field (<code>slug<\/code>) with a URL-friendly version of another field (<code>title<\/code>). The hook is created in such a way that the properties it reads from and writes to are dynamic, passed through as <code>from<\/code> and <code>to<\/code> from the <code>options<\/code> block. The <code>slugify<\/code> hook can then be written as follows:<\/p>\n<pre><code class=\"lang-js\">\/\/ Example hook: Creates <span class=\"hljs-keyword\">a<\/span> <span class=\"hljs-built_in\">URL<\/span>-friendly <span class=\"hljs-built_in\">version<\/span> (slug) <span class=\"hljs-keyword\">of<\/span> <span class=\"hljs-keyword\">a<\/span> field\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">slugify<\/span>(<span class=\"hljs-title\">text<\/span>) {<\/span>\n  <span class=\"hljs-literal\">return<\/span> <span class=\"hljs-keyword\">text<\/span>.toString().toLowerCase()\n    .<span class=\"hljs-built_in\">replace<\/span>(\/\\s+\/g, <span class=\"hljs-string\">'-'<\/span>)\n    .<span class=\"hljs-built_in\">replace<\/span>(\/[^\\w\\-]+\/g, <span class=\"hljs-string\">''<\/span>)\n    .<span class=\"hljs-built_in\">replace<\/span>(\/\\-\\-+\/g, <span class=\"hljs-string\">'-'<\/span>)\n    .<span class=\"hljs-built_in\">replace<\/span>(\/^-+\/, <span class=\"hljs-string\">''<\/span>)\n    .<span class=\"hljs-built_in\">replace<\/span>(\/-+$\/, <span class=\"hljs-string\">''<\/span>)\n}\nmodule.exports = <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> (<span class=\"hljs-title\">obj<\/span>, <span class=\"hljs-title\">type<\/span>, <span class=\"hljs-title\">data<\/span>) {<\/span>\n <span class=\"hljs-comment\"> \/\/ We use the options object to know what field to use as the source<\/span>\n <span class=\"hljs-comment\"> \/\/ and what field to populate with the slug<\/span>\n  obj[data.options.<span class=\"hljs-built_in\">to<\/span>] = slugify(obj[data.options.<span class=\"hljs-built_in\">from<\/span>])\n  <span class=\"hljs-literal\">return<\/span> obj\n}\n<\/code><\/pre>\n<h4><a href=\"#before-and-after-hooks\" id=\"before-and-after-hooks\" name=\"before-and-after-hooks\" class=\"anchor\">Anchor link<\/a> <a href=\"#before-and-after-hooks\"><em>Before<\/em> and <em>After<\/em> Hooks<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">Different types of hooks are executed at different points in the lifecycle of a request. There are two main types of hooks:<\/p>\n<ul>\n<li><em>Before<\/em> hooks: are always executed, fired just before the model processes the request and grabs the documents from the database. These hooks have the power to modify the query parameters, and therefore modify the set of documents that will be retrieved, as well as to abort an operation completely, if they choose to throw an error;<\/li>\n<li><em>After<\/em> hooks: are executed only if the operation has been successful (i.e. no errors resulting from either <em>before<\/em> hooks or from the communication with the database). They are fired after the result set has been formed and delivered to the consumer. <em>Before<\/em> hooks cannot affect the result of a request. Typically used to trigger operations that must take place after a set of documents has been successfully created, updated or deleted.<\/li>\n<\/ul>\n<p class=\"7xtjw4dqwy5mz7w3j\">These hook types are then applied to each of the CRUD operations (e.g. <code>beforeCreate<\/code>, <code>afterCreate<\/code>, etc.). If you think of API as an assembly line that processes requests and documents, this is where hooks would sit:<\/p>\n<pre>\n         ______________          __________            _____________ \nRequest |              |        |          | Response |             |\n------&gt; | beforeCreate | -----&gt; | Database | -------&gt; | afterCreate |\n        |______________|        |__________|          |_____________|\n<\/pre>\n<h4><a href=\"#types-and-signatures\" id=\"types-and-signatures\" name=\"types-and-signatures\" class=\"anchor\">Anchor link<\/a> <a href=\"#types-and-signatures\">Types and signatures<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">Hooks are expected to export a function that receives three parameters:<\/p>\n<ol>\n<li>The document or query being processed (type: <code>Object<\/code>)<\/li>\n<li>The name of the hook type (type: <code>String<\/code>, example: <code>&quot;beforeCreate&quot;<\/code>)<\/li>\n<li>An object with additional data that varies with each hook type (type: <code>Object<\/code>)<\/li>\n<\/ol>\n<h5><a href=\"#beforecreate\" id=\"beforecreate\" name=\"beforecreate\" class=\"anchor\">Anchor link<\/a> <a href=\"#beforecreate\">beforeCreate<\/a><\/h5>\n<p class=\"7xtjw4dqwy5mz7w3j\">Fires for <code>POST<\/code> requests, before documents are inserted into the database.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>Parameters:<\/em><\/p>\n<ol>\n<li><code>documents<\/code>: An object or array of objects representing the documents about to be created<\/li>\n<li><code>type<\/code>: A string containing <code>&quot;beforeCreate&quot;<\/code><\/li>\n<li><code>options<\/code>: An options object containing:\n<ul>\n<li><code>collection<\/code>: name of the current collection<\/li>\n<li><code>options<\/code>: options block from the hook definition in the collection schema<\/li>\n<li><code>req<\/code>: the instance of Node&#39;s <a href=\"https:\/\/nodejs.org\/api\/http.html#http_class_http_incomingmessage\">http.IncomingMessage<\/a><\/li>\n<li><code>schema<\/code>: the schema of the current collection<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>Returns:<\/em><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">The new set of documents to be inserted. An error can be thrown to abort the operation.<\/p>\n<h5><a href=\"#aftercreate\" id=\"aftercreate\" name=\"aftercreate\" class=\"anchor\">Anchor link<\/a> <a href=\"#aftercreate\">afterCreate<\/a><\/h5>\n<p class=\"7xtjw4dqwy5mz7w3j\">Fires for <code>POST<\/code> requests, if and after the documents have been successfully inserted.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>Parameters:<\/em><\/p>\n<ol>\n<li><code>documents<\/code>: An object or array of objects representing the documents created<\/li>\n<li><code>type<\/code>: A string containing <code>&quot;afterCreate&quot;<\/code><\/li>\n<li><code>options<\/code>: An options object containing:\n<ul>\n<li><code>collection<\/code>: name of the current collection<\/li>\n<li><code>options<\/code>: options block from the hook definition in the collection schema<\/li>\n<li><code>schema<\/code>: the schema of the current collection<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>Returns:<\/em><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">N\/A<\/p>\n<h5><a href=\"#beforedelete\" id=\"beforedelete\" name=\"beforedelete\" class=\"anchor\">Anchor link<\/a> <a href=\"#beforedelete\">beforeDelete<\/a><\/h5>\n<p class=\"7xtjw4dqwy5mz7w3j\">Fires for <code>DELETE<\/code> requests, before data is deleted from the database.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>Parameters:<\/em><\/p>\n<ol>\n<li><code>query<\/code>: A query that will be used to filter documents for deletion<\/li>\n<li><code>type<\/code>: A string containing <code>&quot;beforeDelete&quot;<\/code><\/li>\n<li><code>options<\/code>: An options object containing:\n<ul>\n<li><code>collection<\/code>: name of the current collection<\/li>\n<li><code>options<\/code>: options block from the hook definition in the collection schema<\/li>\n<li><code>req<\/code>: the instance of Node&#39;s <a href=\"https:\/\/nodejs.org\/api\/http.html#http_class_http_incomingmessage\">http.IncomingMessage<\/a><\/li>\n<li><code>schema<\/code>: the schema of the current collection<\/li>\n<li><code>deletedDocs<\/code>: an array containing the documents that are about to be deleted<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>Returns:<\/em><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">The new query to filter documents with. An error can be thrown to abort the operation.<\/p>\n<h5><a href=\"#afterdelete\" id=\"afterdelete\" name=\"afterdelete\" class=\"anchor\">Anchor link<\/a> <a href=\"#afterdelete\">afterDelete<\/a><\/h5>\n<p class=\"7xtjw4dqwy5mz7w3j\">Fires for <code>DELETE<\/code> requests, if and after the documents have been successfully deleted.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>Parameters:<\/em><\/p>\n<ol>\n<li><code>query<\/code>: A query that was used to filter documents for deletion<\/li>\n<li><code>type<\/code>: A string containing <code>&quot;afterDelete&quot;<\/code><\/li>\n<li><code>options<\/code>: An options object containing:\n<ul>\n<li><code>collection<\/code>: name of the current collection<\/li>\n<li><code>options<\/code>: options block from the hook definition in the collection schema<\/li>\n<li><code>schema<\/code>: the schema of the current collection<\/li>\n<li><code>deletedDocs<\/code>: an array containing the documents that are about to be deleted<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>Returns:<\/em><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">N\/A<\/p>\n<h5><a href=\"#beforeget\" id=\"beforeget\" name=\"beforeget\" class=\"anchor\">Anchor link<\/a> <a href=\"#beforeget\">beforeGet<\/a><\/h5>\n<p class=\"7xtjw4dqwy5mz7w3j\">Fires for <code>GET<\/code> requests, before documents are retrieved from the database.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>Parameters:<\/em><\/p>\n<ol>\n<li><code>query<\/code>: A query that will be used to filter documents<\/li>\n<li><code>type<\/code>: A string containing <code>&quot;beforeGet&quot;<\/code><\/li>\n<li><code>options<\/code>: An options object containing:\n<ul>\n<li><code>collection<\/code>: name of the current collection<\/li>\n<li><code>options<\/code>: options block from the hook definition in the collection schema<\/li>\n<li><code>req<\/code>: the instance of Node&#39;s <a href=\"https:\/\/nodejs.org\/api\/http.html#http_class_http_incomingmessage\">http.IncomingMessage<\/a><\/li>\n<li><code>schema<\/code>: the schema of the current collection<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>Returns:<\/em><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">The new query to filter documents with. An error can be thrown to abort the operation.<\/p>\n<h5><a href=\"#afterget\" id=\"afterget\" name=\"afterget\" class=\"anchor\">Anchor link<\/a> <a href=\"#afterget\">afterGet<\/a><\/h5>\n<p class=\"7xtjw4dqwy5mz7w3j\">Fires for <code>GET<\/code> requests. Unlike other <em>after<\/em> hooks, <em>afterGet<\/em> happens after the data has been retrieved but before the response is sent to the consumer. As a consequence, <em>afterGet<\/em> hooks have the ability to massage the data before it&#39;s delivered.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>Parameters:<\/em><\/p>\n<ol>\n<li><code>documents<\/code>: An object or array of objects representing the documents retrieved<\/li>\n<li><code>type<\/code>: A string containing <code>&quot;afterGet&quot;<\/code><\/li>\n<li><code>options<\/code>: An options object containing:\n<ul>\n<li><code>collection<\/code>: name of the current collection<\/li>\n<li><code>options<\/code>: options block from the hook definition in the collection schema<\/li>\n<li><code>req<\/code>: the instance of Node&#39;s <a href=\"https:\/\/nodejs.org\/api\/http.html#http_class_http_incomingmessage\">http.IncomingMessage<\/a><\/li>\n<li><code>schema<\/code>: the schema of the current collection<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>Returns:<\/em><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">The result set formatted for output. An error can be thrown to abort the operation.<\/p>\n<h5><a href=\"#beforeupdate\" id=\"beforeupdate\" name=\"beforeupdate\" class=\"anchor\">Anchor link<\/a> <a href=\"#beforeupdate\">beforeUpdate<\/a><\/h5>\n<p class=\"7xtjw4dqwy5mz7w3j\">Fires for <code>PUT<\/code> requests, before documents are updated on the database.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>Parameters:<\/em><\/p>\n<ol>\n<li><code>update<\/code>: An object with the set of fields to be updated and their respective new values<\/li>\n<li><code>type<\/code>: A string containing <code>&quot;beforeUpdate&quot;<\/code><\/li>\n<li><code>options<\/code>: An options object containing:\n<ul>\n<li><code>collection<\/code>: name of the current collection<\/li>\n<li><code>options<\/code>: options block from the hook definition in the collection schema<\/li>\n<li><code>req<\/code>: the instance of Node&#39;s <a href=\"https:\/\/nodejs.org\/api\/http.html#http_class_http_incomingmessage\">http.IncomingMessage<\/a><\/li>\n<li><code>schema<\/code>: the schema of the current collection<\/li>\n<li><code>updatedDocs<\/code>: the documents about to be updated<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>Returns:<\/em><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">The new update object. An error can be thrown to abort the operation.<\/p>\n<h5><a href=\"#afterupdate\" id=\"afterupdate\" name=\"afterupdate\" class=\"anchor\">Anchor link<\/a> <a href=\"#afterupdate\">afterUpdate<\/a><\/h5>\n<p class=\"7xtjw4dqwy5mz7w3j\">Fires for <code>PUT<\/code> requests, if and after the documents have been successfully updated.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>Parameters:<\/em><\/p>\n<ol>\n<li><code>documents<\/code>: An object or array of objects representing the documents updated<\/li>\n<li><code>type<\/code>: A string containing <code>&quot;afterUpdate&quot;<\/code><\/li>\n<li><code>options<\/code>: An options object containing:\n<ul>\n<li><code>collection<\/code>: name of the current collection<\/li>\n<li><code>options<\/code>: options block from the hook definition in the collection schema<\/li>\n<li><code>schema<\/code>: the schema of the current collection<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>Returns:<\/em><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">N\/A<\/p>\n<h4><a href=\"#testing\" id=\"testing\" name=\"testing\" class=\"anchor\">Anchor link<\/a> <a href=\"#testing\">Testing<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">The following hook may be useful to get a better idea of when exactly each hook type is fired and what data it receives, as it logs to the console its internals every time it gets called:<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>workspace\/hooks\/showInfo.js<\/em><\/p>\n<pre><code class=\"lang-js\"><span class=\"hljs-built_in\">module<\/span>.exports = <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> (<span class=\"hljs-params\">obj, <span class=\"hljs-keyword\">type<\/span>, data<\/span>) <\/span>{\n  <span class=\"hljs-built_in\">console<\/span>.log(<span class=\"hljs-string\">''<\/span>)\n  <span class=\"hljs-built_in\">console<\/span>.log(<span class=\"hljs-string\">'Hook type:'<\/span>, <span class=\"hljs-keyword\">type<\/span>)\n  <span class=\"hljs-built_in\">console<\/span>.log(<span class=\"hljs-string\">'Payload:'<\/span>, obj)\n  <span class=\"hljs-built_in\">console<\/span>.log(<span class=\"hljs-string\">'Additional data:'<\/span>, data)\n  <span class=\"hljs-built_in\">console<\/span>.log(<span class=\"hljs-string\">''<\/span>)\n  <span class=\"hljs-keyword\">return<\/span> obj\n}\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\">And then enable it in a model:<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><em>workspace\/collections\/vjoin\/testdb\/collection.users.json<\/em><\/p>\n<pre><code class=\"lang-js\"><span class=\"hljs-string\">\"hooks\"<\/span>: {\n  <span class=\"hljs-string\">\"beforeCreate\"<\/span>: [<span class=\"hljs-string\">\"showInfo\"<\/span>],\n  <span class=\"hljs-string\">\"afterCreate\"<\/span>: [<span class=\"hljs-string\">\"showInfo\"<\/span>],\n  <span class=\"hljs-string\">\"beforeUpdate\"<\/span>: [<span class=\"hljs-string\">\"showInfo\"<\/span>],\n  <span class=\"hljs-string\">\"afterUpdate\"<\/span>: [<span class=\"hljs-string\">\"showInfo\"<\/span>],\n  <span class=\"hljs-string\">\"beforeDelete\"<\/span>: [<span class=\"hljs-string\">\"showInfo\"<\/span>],\n  <span class=\"hljs-string\">\"afterDelete\"<\/span>: [<span class=\"hljs-string\">\"showInfo\"<\/span>]\n}\n<\/code><\/pre>\n<h2><a href=\"#internal-endpoints\" id=\"internal-endpoints\" name=\"internal-endpoints\" class=\"anchor\">Anchor link<\/a> <a href=\"#internal-endpoints\">Internal endpoints<\/a><\/h2>\n<h3><a href=\"#hello\" id=\"hello\" name=\"hello\" class=\"anchor\">Anchor link<\/a> <a href=\"#hello\">Hello<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">The <em>Hello<\/em> endpoint returns a plain text response with the string <em>Welcome to API<\/em> when a <code>GET<\/code> request is made to the <code>\/hello<\/code> endpoint. It can be used to verify that DADI API is successfully installed and running. You should expect a 200 status code to be returned when requesting this endpoint.<\/p>\n<h3><a href=\"#configuration-5\" id=\"configuration-5\" name=\"configuration-5\" class=\"anchor\">Anchor link<\/a> <a href=\"#configuration-5\">Configuration<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">The <code>\/api\/config<\/code> endpoint returns a JSON response with API&#39;s current configuration. This endpoint requires authentication by passing a Bearer token in the Authorization header. See the <a href=\"#authentication\">Authentication<\/a> section for more detail.<\/p>\n<pre><code class=\"lang-http\"><span class=\"hljs-builtin-name\">GET<\/span> \/api<span class=\"hljs-built_in\">\/config <\/span>HTTP\/1.1\nHost: api.somedomain.tech\nContent-Type: application\/json\nCache-Control: no-cache\n<\/code><\/pre>\n<h3><a href=\"#cache-flush\" id=\"cache-flush\" name=\"cache-flush\" class=\"anchor\">Anchor link<\/a> <a href=\"#cache-flush\">Cache flush<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">Cached files can be flushed by sending a <code>POST<\/code> request to API&#39;s <code>\/api\/flush<\/code> endpoint. The request body must contain a path that matches a collection resource. For example, the following will flush all cache files that match the collection path <code>\/1.0\/library\/books<\/code>.<\/p>\n<pre><code class=\"lang-http\"><span class=\"hljs-keyword\">POST<\/span> <span class=\"hljs-string\">\/api\/flush<\/span> HTTP\/1.1\n<span class=\"hljs-attribute\">Host<\/span>: api.somedomain.tech\n<span class=\"hljs-attribute\">Authorization<\/span>: Bearer 4172bbf1-0890-41c7-b0db-477095a288b6\n<span class=\"hljs-attribute\">Content-Type<\/span>: application\/json\n<span class=\"json\">{ <span class=\"hljs-attr\">\"path\"<\/span>: <span class=\"hljs-string\">\"\/1.0\/library\/books\"<\/span> }<\/span>\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\">A successful cache flush returns a JSON response with a 200 status code:<\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"result\"<\/span>: <span class=\"hljs-string\">\"success\"<\/span>,\n  <span class=\"hljs-attr\">\"message\"<\/span>: <span class=\"hljs-string\">\"Cache flush successful\"<\/span>\n}\n<\/code><\/pre>\n<h4><a href=\"#flush-all-files\" id=\"flush-all-files\" name=\"flush-all-files\" class=\"anchor\">Anchor link<\/a> <a href=\"#flush-all-files\">Flush all files<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">To flush all cache files from the API&#39;s caching layer, send <code>*<\/code> as the path in the request body:<\/p>\n<pre><code class=\"lang-http\"><span class=\"hljs-keyword\">POST<\/span> <span class=\"hljs-string\">\/api\/flush<\/span> HTTP\/1.1\n<span class=\"hljs-attribute\">Host<\/span>: api.somedomain.tech\n<span class=\"hljs-attribute\">Authorization<\/span>: Bearer 4172bbf1-0890-41c7-b0db-477095a288b6\n<span class=\"hljs-attribute\">Content-Type<\/span>: application\/json\n<span class=\"json\">{ <span class=\"hljs-attr\">\"path\"<\/span>: <span class=\"hljs-string\">\"*\"<\/span> }<\/span>\n<\/code><\/pre>\n<h3><a href=\"#all-collections\" id=\"all-collections\" name=\"all-collections\" class=\"anchor\">Anchor link<\/a> <a href=\"#all-collections\">All Collections<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">The <code>\/api\/collections<\/code> endpoint returns a JSON response containing information about the available collections that can be queried.<\/p>\n<pre><code class=\"lang-http\"><span class=\"hljs-keyword\">GET<\/span> <span class=\"hljs-string\">\/api\/collections<\/span> HTTP\/1.1\n<span class=\"hljs-attribute\">Host<\/span>: api.somedomain.tech\n<span class=\"hljs-attribute\">Content-Type<\/span>: application\/json\n<span class=\"hljs-attribute\">Cache-Control<\/span>: no-cache\n<\/code><\/pre>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"collections\"<\/span>: [\n    {\n      <span class=\"hljs-attr\">\"name\"<\/span>: <span class=\"hljs-string\">\"books\"<\/span>,\n      <span class=\"hljs-attr\">\"slug\"<\/span>: <span class=\"hljs-string\">\"books\"<\/span>,\n      <span class=\"hljs-attr\">\"version\"<\/span>: <span class=\"hljs-string\">\"1.0\"<\/span>,\n      <span class=\"hljs-attr\">\"database\"<\/span>: <span class=\"hljs-string\">\"library\"<\/span>,\n      <span class=\"hljs-attr\">\"path\"<\/span>: <span class=\"hljs-string\">\"\/1.0\/library\/books\"<\/span>\n    },\n    {\n      <span class=\"hljs-attr\">\"name\"<\/span>: <span class=\"hljs-string\">\"user\"<\/span>,\n      <span class=\"hljs-attr\">\"slug\"<\/span>: <span class=\"hljs-string\">\"user\"<\/span>,\n      <span class=\"hljs-attr\">\"version\"<\/span>: <span class=\"hljs-string\">\"1.0\"<\/span>,\n      <span class=\"hljs-attr\">\"database\"<\/span>: <span class=\"hljs-string\">\"library\"<\/span>,\n      <span class=\"hljs-attr\">\"path\"<\/span>: <span class=\"hljs-string\">\"\/1.0\/library\/users\"<\/span>\n    },\n    {\n      <span class=\"hljs-attr\">\"name\"<\/span>: <span class=\"hljs-string\">\"author\"<\/span>,\n      <span class=\"hljs-attr\">\"slug\"<\/span>: <span class=\"hljs-string\">\"author\"<\/span>,\n      <span class=\"hljs-attr\">\"version\"<\/span>: <span class=\"hljs-string\">\"1.0\"<\/span>,\n      <span class=\"hljs-attr\">\"database\"<\/span>: <span class=\"hljs-string\">\"library\"<\/span>,\n      <span class=\"hljs-attr\">\"path\"<\/span>: <span class=\"hljs-string\">\"\/1.0\/library\/authors\"<\/span>\n    }\n  ]\n}\n<\/code><\/pre>\n<h2><a href=\"#feature-queries\" id=\"feature-queries\" name=\"feature-queries\" class=\"anchor\">Anchor link<\/a> <a href=\"#feature-queries\">Feature queries<\/a><\/h2>\n<p class=\"7xtjw4dqwy5mz7w3j\">As the feature set of DADI API evolves, it\u2019s possible that two instances running different versions of the product have support for substantially different sets of functionality. Since consumer applications may require a specific feature in order to operate, it becomes essential that applications have a view on the capabilities of the API instance they communicate with. For security reasons, API does not expose its version number, but it does allow clients to inquire about whether a particular feature is supported.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">Since version 4.2.0, every new major feature added to the product will be identified by a unique alphanumeric key. Consumer applications can use these keys to query an API instance about whether it supports a particular feature.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">To use feature queries, add a <code>X-DADI-Requires<\/code> header to an API request and include a list of the features to query, separated by semicolons. The response will include a <code>X-DADI-Supports<\/code> header with the supported subset of the features requested. If none of the features are supported, the header will be omitted from the response.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">In practice, this means that consumer applications can adapt to the capabilities of the API instance. For example, let&#39;s imagine that your application requires the feature set labeled with the key <code>aclv1<\/code>. You can send <code>X-DADI-Requires: aclv1<\/code> to API and look for a <code>X-DADI-Supports<\/code> header in the response \u2013 if it exists and it contains the value <code>aclv1<\/code> somewhere in it, you know the feature is supported. If not, you can make your application gracefully handle the incompatibility problem.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Request<\/strong><\/p>\n<pre><code class=\"lang-http\"><span class=\"hljs-keyword\">GET<\/span> <span class=\"hljs-string\">\/1.0\/library\/movies<\/span> HTTP\/1.1\n<span class=\"hljs-attribute\">Host<\/span>: api.somedomain.tech\n<span class=\"hljs-attribute\">Authorization<\/span>: Bearer 4172bbf1-0890-41c7-b0db-477095a288b6\n<span class=\"hljs-attribute\">Content-Type<\/span>: application\/json\n<span class=\"hljs-attribute\">X-DADI-Requires<\/span>: aclv1\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>Response<\/strong><\/p>\n<pre><code class=\"lang-json\"><span class=\"hljs-attribute\">Content-Type<\/span>: application\/json\n<span class=\"hljs-attribute\">X-DADI-Supports<\/span>: aclv1\n<span class=\"json\">{\n  <span class=\"hljs-attr\">\"results\"<\/span>: [\n    {\n      <span class=\"hljs-attr\">\"_id\"<\/span>: <span class=\"hljs-string\">\"560a5baf320039f1a1b68d4c\"<\/span>,\n      <span class=\"hljs-attr\">\"title\"<\/span>: <span class=\"hljs-string\">\"Casablanca\"<\/span>\n    }\n  ]\n}<\/span>\n<\/code><\/pre>\n<h3><a href=\"#disabling-feature-queries\" id=\"disabling-feature-queries\" name=\"disabling-feature-queries\" class=\"anchor\">Anchor link<\/a> <a href=\"#disabling-feature-queries\">Disabling feature queries<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">API will respond to feature queries by default. This behaviour can be changed by setting the <code>featureQuery.enabled<\/code> configuration property to <code>false<\/code>, which makes API ignore the <code>X-DADI-Supports<\/code> header completely.<\/p>\n<blockquote class=\"warning\">\n<p class=\"7xtjw4dqwy5mz7w3j\">Note that consumer applications, such as <a href=\"https:\/\/dadi.cloud\/docs-sub\/publish\/\">Publish<\/a>, make use of API feature queries. Disabling them can cause these applications to stop working properly. Do not change this setting unless you know what you are doing!<\/p>\n<\/blockquote>\n<h3><a href=\"#feature-reference\" id=\"feature-reference\" name=\"feature-reference\" class=\"anchor\">Anchor link<\/a> <a href=\"#feature-reference\">Feature reference<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">The following table shows which features can be queried:<\/p>\n<table>\n<thead>\n<tr>\n<th style=\"text-align:left\">Key<\/th>\n<th style=\"text-align:left\">Description<\/th>\n<th style=\"text-align:left\">Version added<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td style=\"text-align:left\"><code>aclv1<\/code><\/td>\n<td style=\"text-align:left\">Access control list including Clients API, Roles API and Resources API<\/td>\n<td style=\"text-align:left\">4.2.0<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>i18nv1<\/code><\/td>\n<td style=\"text-align:left\">Multi-language support<\/td>\n<td style=\"text-align:left\">4.2.1<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>i18nv1<\/code><\/td>\n<td style=\"text-align:left\">Multi-language support (with field character present in collections endpoint)<\/td>\n<td style=\"text-align:left\">4.2.2<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>collectionsv1<\/code><\/td>\n<td style=\"text-align:left\">Collections endpoint with information about schemas and settings<\/td>\n<td style=\"text-align:left\">4.2.2<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>mediafieldv1<\/code><\/td>\n<td style=\"text-align:left\">Media field<\/td>\n<td style=\"text-align:left\">4.4.0<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2><a href=\"#data-connectors-reference\" id=\"data-connectors-reference\" name=\"data-connectors-reference\" class=\"anchor\">Anchor link<\/a> <a href=\"#data-connectors-reference\">Data connectors reference<\/a><\/h2>\n<h3><a href=\"#mongodb-connector\" id=\"mongodb-connector\" name=\"mongodb-connector\" class=\"anchor\">Anchor link<\/a> <a href=\"#mongodb-connector\">MongoDB Connector<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">The MongoDB connector allows you to use MongoDB as the backend for API. It was extracted from API core as part of the 3.0.0 release. The connector is available as an NPM package, with full source code available on GitHub. Help improve the package at <a href=\"https:\/\/github.com\/dadi\/api-mongodb\">https:\/\/github.com\/dadi\/api-mongodb<\/a>.<\/p>\n<h4><a href=\"#installing\" id=\"installing\" name=\"installing\" class=\"anchor\">Anchor link<\/a> <a href=\"#installing\">Installing<\/a><\/h4>\n<pre><code class=\"lang-console\">$ <span class=\"hljs-built_in\">npm<\/span> install --save @dadi\/api-mongodb\n<\/code><\/pre>\n<h4><a href=\"#configuring\" id=\"configuring\" name=\"configuring\" class=\"anchor\">Anchor link<\/a> <a href=\"#configuring\">Configuring<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">As with any of the API data connectors, you need two configuration files. Details regarding the main configuration file can be found <a href=\"#configuration\">elsewhere in this document<\/a>. Below are the configuration options for your MongoDB configuration file.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">These parameters are defined in JSON files placed inside the <code>config\/<\/code> directory, named as <code>mongodb.{ENVIRONMENT}.json<\/code>, where <code>{ENVIRONMENT}<\/code> is the value of the <code>NODE_ENV<\/code> environment variable. In practice, this allows you to have different configuration parameters for when API is running in development, production and any staging, QA or anything in between.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">Some configuration parameters also have corresponding environment variables, which will override whatever value is set in the configuration file.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">The following table shows a list of all the available configuration parameters.<\/p>\n<table>\n<thead>\n<tr>\n<th style=\"text-align:left\">Path<\/th>\n<th style=\"text-align:left\">Description<\/th>\n<th style=\"text-align:left\">Environment variable<\/th>\n<th style=\"text-align:left\">Default<\/th>\n<th style=\"text-align:left\">Format<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td style=\"text-align:left\"><code>env<\/code><\/td>\n<td style=\"text-align:left\">The applicaton environment<\/td>\n<td style=\"text-align:left\"><code>NODE_ENV<\/code><\/td>\n<td style=\"text-align:left\"><code>development<\/code><\/td>\n<td style=\"text-align:left\"><code>production<\/code> or <code>development<\/code> or <code>test<\/code> or <code>qa<\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>hosts<\/code><\/td>\n<td style=\"text-align:left\">An array of MongoDB hosts to connect to. Each host entry must include a <code>host<\/code> and <code>port<\/code> as detailed below.<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code><\/code><\/td>\n<td style=\"text-align:left\">Array<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>hosts.host<\/code><\/td>\n<td style=\"text-align:left\">The host address of the MongoDB instance<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code><\/code><\/td>\n<td style=\"text-align:left\">*<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>hosts.port<\/code><\/td>\n<td style=\"text-align:left\">The port of the MongoDB instance<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code><\/code><\/td>\n<td style=\"text-align:left\">Number<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>username<\/code><\/td>\n<td style=\"text-align:left\">The username used to connect to the database (optional)<\/td>\n<td style=\"text-align:left\"><code>DB_USERNAME<\/code><\/td>\n<td style=\"text-align:left\"><code><\/code><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>password<\/code><\/td>\n<td style=\"text-align:left\">The password used to connect to the database (optional)<\/td>\n<td style=\"text-align:left\"><code>DB_PASSWORD<\/code><\/td>\n<td style=\"text-align:left\"><code><\/code><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>authMechanism<\/code><\/td>\n<td style=\"text-align:left\">If no authentication mechanism is specified or the mechanism DEFAULT is specified, the driver will attempt to authenticate using the SCRAM-SHA-1 authentication method if it is available on the MongoDB server. If the server does not support SCRAM-SHA-1 the driver will authenticate using MONGODB-CR.<\/td>\n<td style=\"text-align:left\"><code>DB_AUTH_MECHANISM<\/code><\/td>\n<td style=\"text-align:left\"><code>DEFAULT<\/code><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>authDatabase<\/code><\/td>\n<td style=\"text-align:left\">The database to authenticate against when supplying a username and password<\/td>\n<td style=\"text-align:left\"><code>DB_AUTH_SOURCE<\/code><\/td>\n<td style=\"text-align:left\"><code>admin<\/code><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>database<\/code><\/td>\n<td style=\"text-align:left\">The name of the database to connect to<\/td>\n<td style=\"text-align:left\"><code>DB_NAME<\/code><\/td>\n<td style=\"text-align:left\"><code><\/code><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>ssl<\/code><\/td>\n<td style=\"text-align:left\">If true, initiates the connection with TLS\/SSL<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code><\/code><\/td>\n<td style=\"text-align:left\">Boolean<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>replicaSet<\/code><\/td>\n<td style=\"text-align:left\">Specifies the name of the replica set, if the mongod is a member of a replica set. When connecting to a replica set it is important to give a seed list of at least two mongod instances. If you only provide the connection point of a single mongod instance, and omit the replicaSet, the client will create a standalone connection.<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code><\/code><\/td>\n<td style=\"text-align:left\">String<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>readPreference<\/code><\/td>\n<td style=\"text-align:left\">Choose how MongoDB routes read operations to the members of a replica set &#8211; see <a href=\"https:\/\/docs.mongodb.com\/manual\/reference\/read-preference\/\">https:\/\/docs.mongodb.com\/manual\/reference\/read-preference\/<\/a><\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code>secondaryPreferred<\/code><\/td>\n<td style=\"text-align:left\"><code>primary<\/code> or <code>primaryPreferred<\/code> or <code>secondary<\/code> or <code>secondaryPreferred<\/code> or <code>nearest<\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align:left\"><code>enableCollectionDatabases<\/code><\/td>\n<td style=\"text-align:left\">\u2014<\/td>\n<td style=\"text-align:left\"><em>N\/A<\/em><\/td>\n<td style=\"text-align:left\"><code><\/code><\/td>\n<td style=\"text-align:left\">Boolean<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<pre><code class=\"lang-cson\">{\n  <span class=\"hljs-attr\">\"hosts\"<\/span>: [\n    {\n      <span class=\"hljs-attr\">\"host\"<\/span>: <span class=\"hljs-string\">\"127.0.0.1\"<\/span>,\n      <span class=\"hljs-attr\">\"port\"<\/span>: <span class=\"hljs-number\">27017<\/span>\n    }\n  ],\n  <span class=\"hljs-attr\">\"username\"<\/span>: <span class=\"hljs-string\">\"\"<\/span>,\n  <span class=\"hljs-attr\">\"password\"<\/span>: <span class=\"hljs-string\">\"\"<\/span>,\n  <span class=\"hljs-attr\">\"database\"<\/span>: <span class=\"hljs-string\">\"testdb\"<\/span>,\n  <span class=\"hljs-attr\">\"ssl\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n  <span class=\"hljs-attr\">\"replicaSet\"<\/span>: <span class=\"hljs-string\">\"\"<\/span>,\n  <span class=\"hljs-attr\">\"enableCollectionDatabases\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n  <span class=\"hljs-attr\">\"databases\"<\/span>: {\n    <span class=\"hljs-attr\">\"testdb\"<\/span>: {\n      <span class=\"hljs-attr\">\"hosts\"<\/span>: [\n        {\n          <span class=\"hljs-attr\">\"host\"<\/span>: <span class=\"hljs-string\">\"127.0.0.1\"<\/span>,\n          <span class=\"hljs-attr\">\"port\"<\/span>: <span class=\"hljs-number\">27017<\/span>\n        }\n      ]\n    }\n  }\n}\n<\/code><\/pre>\n<h4><a href=\"#using-mongolab\" id=\"using-mongolab\" name=\"using-mongolab\" class=\"anchor\">Anchor link<\/a> <a href=\"#using-mongolab\">Using MongoLab<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">If you&#39;re unable to install MongoDB yourself, MongoLab provides a variety of plans to get you running with a MongoDB backend for API. They have a free Sandbox tier that is ideal to get a prototype online. Create an account at https:\/\/mlab.com\/signup\/, verify your email address, and we&#39;ll begin configuring API.<\/p>\n<h5><a href=\"#create-new-deployment\" id=\"create-new-deployment\" name=\"create-new-deployment\" class=\"anchor\">Anchor link<\/a> <a href=\"#create-new-deployment\">Create new deployment<\/a><\/h5>\n<p class=\"7xtjw4dqwy5mz7w3j\">Once your account is created with MongoLab you&#39;ll need to create a new &quot;MongoDB Deployment&quot;. Follow the prompts to create a Sandbox deployment, then click Submit Order on the final screen to provision the service:<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><img decoding=\"async\" src=\"https:\/\/dadi.cloud\/files\/docs-sub\/assets\/api\/mlab\/2.png\" alt=\"\"><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><img decoding=\"async\" src=\"https:\/\/dadi.cloud\/files\/docs-sub\/assets\/api\/mlab\/6.png\" alt=\"\"><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><img decoding=\"async\" src=\"https:\/\/dadi.cloud\/files\/docs-sub\/assets\/api\/mlab\/7.png\" alt=\"\"><\/p>\n<h5><a href=\"#view-mongodb-details\" id=\"view-mongodb-details\" name=\"view-mongodb-details\" class=\"anchor\">Anchor link<\/a> <a href=\"#view-mongodb-details\">View MongoDB details<\/a><\/h5>\n<p class=\"7xtjw4dqwy5mz7w3j\">When the database is ready, click on its name to see the details required for connecting to it.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><img decoding=\"async\" src=\"https:\/\/dadi.cloud\/files\/docs-sub\/assets\/api\/mlab\/8.png\" alt=\"\"><\/p>\n<h5><a href=\"#creating-a-mongolab-database-user\" id=\"creating-a-mongolab-database-user\" name=\"creating-a-mongolab-database-user\" class=\"anchor\">Anchor link<\/a> <a href=\"#creating-a-mongolab-database-user\">Creating a MongoLab database user<\/a><\/h5>\n<p class=\"7xtjw4dqwy5mz7w3j\">MongoLab requires you to create a database user in order to connect:<\/p>\n<blockquote class=\"\">\n<p class=\"7xtjw4dqwy5mz7w3j\">A database user is required to connect to this database. To create one now, visit the &apos;Users&apos; tab and click the &apos;Add database user&apos; button.<\/p>\n<\/blockquote>\n<p class=\"7xtjw4dqwy5mz7w3j\">Complete the fields in the New User popup and keep a note of the username and password for the next step.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><img decoding=\"async\" src=\"https:\/\/dadi.cloud\/files\/docs-sub\/assets\/api\/mlab\/9.png\" alt=\"\"><\/p>\n<h5><a href=\"#connecting-from-api\" id=\"connecting-from-api\" name=\"connecting-from-api\" class=\"anchor\">Anchor link<\/a> <a href=\"#connecting-from-api\">Connecting from API<\/a><\/h5>\n<p class=\"7xtjw4dqwy5mz7w3j\">To connect to a MongoDB database you require two configuration files: the first is the main API configuration file (config.development.json) and the second is the configuration file for the MongoDB data connector (mongodb.development.json).<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>config.development.json<\/strong><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">The key settings in the main API configuration file are <code>datastore<\/code>, <code>auth.datastore<\/code> and <code>auth.database<\/code>. When using the MongoDB data connector, <code>datastore<\/code> must be set to <code>&quot;@dadi\/api-mongodb&quot;<\/code>. If using MongoDB for API&#39;s authentication data, <code>auth.datastore<\/code> must also be set to <code>&quot;@dadi\/api-mongodb&quot;<\/code>. The <code>auth<\/code> section also specifies the database to use for authentication data; in the example below it is set to the name of the database we created when setting up the MongoLab database.<\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"app\"<\/span>: {\n    <span class=\"hljs-attr\">\"name\"<\/span>: <span class=\"hljs-string\">\"MongoLab Test\"<\/span>\n  },\n  <span class=\"hljs-attr\">\"server\"<\/span>: {\n    <span class=\"hljs-attr\">\"host\"<\/span>: <span class=\"hljs-string\">\"127.0.0.1\"<\/span>,\n    <span class=\"hljs-attr\">\"port\"<\/span>: <span class=\"hljs-number\">3000<\/span>\n  },\n  <span class=\"hljs-attr\">\"publicUrl\"<\/span>: {\n    <span class=\"hljs-attr\">\"host\"<\/span>: <span class=\"hljs-string\">\"localhost\"<\/span>,\n    <span class=\"hljs-attr\">\"port\"<\/span>: <span class=\"hljs-number\">3000<\/span>\n  },\n  <span class=\"hljs-attr\">\"datastore\"<\/span>: <span class=\"hljs-string\">\"@dadi\/api-mongodb\"<\/span>,\n  <span class=\"hljs-attr\">\"auth\"<\/span>: {\n    <span class=\"hljs-attr\">\"tokenUrl\"<\/span>: <span class=\"hljs-string\">\"\/token\"<\/span>,\n    <span class=\"hljs-attr\">\"tokenTtl\"<\/span>: <span class=\"hljs-number\">18000<\/span>,\n    <span class=\"hljs-attr\">\"clientCollection\"<\/span>: <span class=\"hljs-string\">\"clientStore\"<\/span>,\n    <span class=\"hljs-attr\">\"tokenCollection\"<\/span>: <span class=\"hljs-string\">\"tokenStore\"<\/span>,\n    <span class=\"hljs-attr\">\"datastore\"<\/span>: <span class=\"hljs-string\">\"@dadi\/api-mongodb\"<\/span>,\n    <span class=\"hljs-attr\">\"database\"<\/span>: <span class=\"hljs-string\">\"dadiapisandbox\"<\/span>\n  },\n  <span class=\"hljs-attr\">\"paths\"<\/span>: {\n    <span class=\"hljs-attr\">\"collections\"<\/span>: <span class=\"hljs-string\">\"workspace\/collections\"<\/span>,\n    <span class=\"hljs-attr\">\"endpoints\"<\/span>: <span class=\"hljs-string\">\"workspace\/endpoints\"<\/span>,\n    <span class=\"hljs-attr\">\"hooks\"<\/span>: <span class=\"hljs-string\">\"workspace\/hooks\"<\/span>\n  }\n}\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong>mongodb.development.json<\/strong><\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">In addition to the main configuration file, API requires a configuration file specific to the data connector. The configuration file for the MongoDB connector must be located in the <code>config<\/code> directory along with the main configuration file. <code>mongodb.development.json<\/code> contains settings for connecting to a MongoDB database.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">The database detail page on MongoLab shows a couple of ways to connect to your MongoLab database. We&#39;ll take some parameters from the &quot;mongo shell&quot; option and use them in our configuration file:<\/p>\n<blockquote class=\"\">\n<p class=\"7xtjw4dqwy5mz7w3j\">To connect using the mongo shell:<br \/>\nmongo ds159509.mlab.com:59509\/dadiapisandbox -u <dbuser> -p <dbpassword\/><\/dbuser><\/p>\n<\/blockquote>\n<pre><code class=\"lang-cson\">{\n  <span class=\"hljs-string\">\"hosts\"<\/span>: [\n    {\n      <span class=\"hljs-string\">\"host\"<\/span>: <span class=\"hljs-string\">\"ds159509.mlab.com\"<\/span>,\n      <span class=\"hljs-string\">\"port\"<\/span>: <span class=\"hljs-number\">59509<\/span>\n    }\n  ],\n  <span class=\"hljs-string\">\"username\"<\/span>: <span class=\"hljs-string\">\"dadiapi\"<\/span>,  <span class=\"hljs-regexp\">\/\/<\/span> username <span class=\"hljs-keyword\">for<\/span> database user created <span class=\"hljs-keyword\">in<\/span> MongoLab\n  <span class=\"hljs-string\">\"password\"<\/span>: <span class=\"hljs-string\">\"ipaidad\"<\/span>,  <span class=\"hljs-regexp\">\/\/<\/span> password <span class=\"hljs-keyword\">for<\/span> database user created <span class=\"hljs-keyword\">in<\/span> MongoLab\n  <span class=\"hljs-string\">\"database\"<\/span>: <span class=\"hljs-string\">\"dadiapisandbox\"<\/span>,\n  <span class=\"hljs-string\">\"ssl\"<\/span>: <span class=\"hljs-keyword\">false<\/span>,\n  <span class=\"hljs-string\">\"replicaSet\"<\/span>: <span class=\"hljs-string\">\"\"<\/span>,\n  <span class=\"hljs-string\">\"databases\"<\/span>: {\n    <span class=\"hljs-string\">\"dadiapisandbox\"<\/span>: {\n      <span class=\"hljs-string\">\"authDatabase\"<\/span>: <span class=\"hljs-string\">\"dadiapisandbox\"<\/span>,  <span class=\"hljs-regexp\">\/\/<\/span> the name of the database to <span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-keyword\">for<\/span> authenticating, required <span class=\"hljs-keyword\">when<\/span> specifying a username <span class=\"hljs-keyword\">and<\/span> password\n      <span class=\"hljs-string\">\"hosts\"<\/span>: [\n        {\n          <span class=\"hljs-string\">\"host\"<\/span>: <span class=\"hljs-string\">\"ds159509.mlab.com\"<\/span>,\n          <span class=\"hljs-string\">\"port\"<\/span>: <span class=\"hljs-number\">59509<\/span>\n        }\n      ]\n    }\n  }\n}\n<\/code><\/pre>\n<h5><a href=\"#booting-api\" id=\"booting-api\" name=\"booting-api\" class=\"anchor\">Anchor link<\/a> <a href=\"#booting-api\">Booting API<\/a><\/h5>\n<p class=\"7xtjw4dqwy5mz7w3j\">When you start your API application it will attempt to connect to the MongoLab database using the specified settings. <\/p>\n<pre><code><span class=\"hljs-meta\">$<\/span><span class=\"bash\"> npm start<\/span>\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\">After API finishes booting, you can click on the &quot;Collections&quot; tab in the MongoLab website and see the collections that API has created from your workspace collection schemas.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><img decoding=\"async\" src=\"https:\/\/dadi.cloud\/files\/docs-sub\/assets\/api\/mlab\/12.png\" alt=\"\"><\/p>\n<h5><a href=\"#creating-an-api-user\" id=\"creating-an-api-user\" name=\"creating-an-api-user\" class=\"anchor\">Anchor link<\/a> <a href=\"#creating-an-api-user\">Creating an API user<\/a><\/h5>\n<p class=\"7xtjw4dqwy5mz7w3j\">Before interacting with any of the API collections, it&#39;s useful to create a client record so you can obtain an access token. See the <a href=\"#adding-clients\">Adding clients<\/a> section for more details. After creating a client record you should be able to query the <code>clientStore<\/code> collection on the MongoLab website to see the new document.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><img decoding=\"async\" src=\"https:\/\/dadi.cloud\/files\/docs-sub\/assets\/api\/mlab\/11.png\" alt=\"\"><\/p>\n<h5><a href=\"#what#39s-next\" id=\"what#39s-next\" name=\"what#39s-next\" class=\"anchor\">Anchor link<\/a> <a href=\"#what#39s-next\">What&#39;s next?<\/a><\/h5>\n<p class=\"7xtjw4dqwy5mz7w3j\">With API connected and a client record added to the database, you can begin using the REST API to store and retrieve data. See the sections <a href=\"#obtaining-an-access-token\">Obtaining an Access Token<\/a> and <a href=\"#retrieving-data\">Retrieving data<\/a> for more detail.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">The image below shows a &quot;book&quot; document added to the MongoLab database using the following requests:<\/p>\n<pre><code class=\"lang-console\">$ curl -X POST -H <span class=\"hljs-string\">\"Content-type: application\/json\"<\/span> <span class=\"hljs-params\">--data<\/span> '{<span class=\"hljs-string\">\"clientId\"<\/span>:<span class=\"hljs-string\">\"api-client\"<\/span>, <span class=\"hljs-string\">\"secret\"<\/span>: <span class=\"hljs-string\">\"client-secret\"<\/span>}' <span class=\"hljs-string\">\"http:\/\/127.0.0.1:3000\/token\"<\/span>\n<\/code><\/pre>\n<pre><code class=\"lang-console\">$ curl -X POST -H <span class=\"hljs-string\">\"Content-type: application\/json\"<\/span> -H <span class=\"hljs-string\">\"Authorization: Bearer 1e6624a9-324a-4d24-86c3-e4abd0921d9c\"<\/span>  <span class=\"hljs-params\">--data<\/span> '{<span class=\"hljs-string\">\"name\"<\/span>:<span class=\"hljs-string\">\"Test Book\"<\/span>, <span class=\"hljs-string\">\"authorId\"<\/span>: <span class=\"hljs-string\">\"123456781234567812345678\"<\/span>}' <span class=\"hljs-string\">\"http:\/\/127.0.0.1:3000\/vjoin\/testdb\/books\"<\/span>\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\"><img decoding=\"async\" src=\"https:\/\/dadi.cloud\/files\/docs-sub\/assets\/api\/mlab\/13.png\" alt=\"\"><\/p>\n<h3><a href=\"#couchdb-connector\" id=\"couchdb-connector\" name=\"couchdb-connector\" class=\"anchor\">Anchor link<\/a> <a href=\"#couchdb-connector\">CouchDB Connector<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">The CouchDB connector allows you to use CouchDB as the backend for API.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">Help improve the package at <a href=\"https:\/\/github.com\/dadi\/api-couchdb\">https:\/\/github.com\/dadi\/api-couchdb<\/a>.<\/p>\n<h4><a href=\"#installing-1\" id=\"installing-1\" name=\"installing-1\" class=\"anchor\">Anchor link<\/a> <a href=\"#installing-1\">Installing<\/a><\/h4>\n<pre><code class=\"lang-console\">$ <span class=\"hljs-built_in\">npm<\/span> install --save @dadi\/api-couchdb\n<\/code><\/pre>\n<h3><a href=\"#filestore-connector\" id=\"filestore-connector\" name=\"filestore-connector\" class=\"anchor\">Anchor link<\/a> <a href=\"#filestore-connector\">FileStore Connector<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">The FileStore connector allows you to use JSON files as the backend for API, via <a href=\"http:\/\/lokijs.org\/\">LokiJS<\/a>.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">Help improve the package at <a href=\"https:\/\/github.com\/dadi\/api-filestore\">https:\/\/github.com\/dadi\/api-filestore<\/a>.<\/p>\n<h4><a href=\"#installing-2\" id=\"installing-2\" name=\"installing-2\" class=\"anchor\">Anchor link<\/a> <a href=\"#installing-2\">Installing<\/a><\/h4>\n<pre><code class=\"lang-console\">$ <span class=\"hljs-built_in\">npm<\/span> install --save @dadi\/api-filestore\n<\/code><\/pre>\n<h3><a href=\"#building-a-connector\" id=\"building-a-connector\" name=\"building-a-connector\" class=\"anchor\">Anchor link<\/a> <a href=\"#building-a-connector\">Building a connector<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">Sample repository at <a href=\"https:\/\/github.com\/dadi\/api-connector-template\">https:\/\/github.com\/dadi\/api-connector-template<\/a>.<\/p>\n<h2><a href=\"#how-to-guides\" id=\"how-to-guides\" name=\"how-to-guides\" class=\"anchor\">Anchor link<\/a> <a href=\"#how-to-guides\">How-to guides<\/a><\/h2>\n<h3><a href=\"#migrating-from-version-3-to-4\" id=\"migrating-from-version-3-to-4\" name=\"migrating-from-version-3-to-4\" class=\"anchor\">Anchor link<\/a> <a href=\"#migrating-from-version-3-to-4\">Migrating from version 3 to 4<\/a><\/h3>\n<h4><a href=\"#access-control-list\" id=\"access-control-list\" name=\"access-control-list\" class=\"anchor\">Anchor link<\/a> <a href=\"#access-control-list\">Access control list<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">The main change from version 3 to 4 is the introduction of the <a href=\"#access-control\">access control list<\/a>. It&#39;s technically a breaking change, since any clients without <code>{&quot;accessType&quot;: &quot;admin&quot;}<\/code> will lose access to everything by default. They need to be assigned permissions for the individual resources they should be able to access, either directly or via roles.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">If you don&#39;t want to use the new advanced permissions and instead keep your clients with unrestricted access to API resources, make sure to set <code>{&quot;accessType&quot;: &quot;admin&quot;}<\/code> in their database records. API doesn&#39;t currently offer a way to change this property via the endpoints, so you&#39;ll need to manually make this change in the database.<\/p>\n<h4><a href=\"#removal-of-write-mode-on-configuraion-endpoints\" id=\"removal-of-write-mode-on-configuraion-endpoints\" name=\"removal-of-write-mode-on-configuraion-endpoints\" class=\"anchor\">Anchor link<\/a> <a href=\"#removal-of-write-mode-on-configuraion-endpoints\">Removal of write mode on configuraion endpoints<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">Version 4 removes the ability for clients to create, modify and delete collections, custom endpoints or update the main API configuration. The <em>read<\/em> endpoints were kept \u2013 e.g. <code>GET \/api\/config<\/code> is valid, but <code>POST \/api\/config<\/code> is not.<\/p>\n<h4><a href=\"#other-breaking-changes\" id=\"other-breaking-changes\" name=\"other-breaking-changes\" class=\"anchor\">Anchor link<\/a> <a href=\"#other-breaking-changes\">Other breaking changes<\/a><\/h4>\n<ul>\n<li>Requesting a document by ID (e.g. <code>\/version\/database\/collection\/doc123456<\/code>) now returns a 404 if the given ID does not correspond to a valid document, instead of returning a 200 with an empty result set. This behaviour is consistent with the <code>DELETE<\/code> and <code>PUT<\/code> verbs.<\/li>\n<\/ul>\n<h3><a href=\"#migrating-from-version-4-to-5\" id=\"migrating-from-version-4-to-5\" name=\"migrating-from-version-4-to-5\" class=\"anchor\">Anchor link<\/a> <a href=\"#migrating-from-version-4-to-5\">Migrating from version 4 to 5<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">Client records in version 5 have a different internal representation. To update an existing installation, you must migrate any existing clients (<strong>after<\/strong> upgrading the API dependency) by running the following command on the API directory:<\/p>\n<pre><code class=\"lang-console\"><span class=\"hljs-meta\">$<\/span><span class=\"bash\"> npx dadi-cli api clients:upgrade<\/span>\n<\/code><\/pre>\n<h3><a href=\"#connecting-to-api-with-api-wrapper\" id=\"connecting-to-api-with-api-wrapper\" name=\"connecting-to-api-with-api-wrapper\" class=\"anchor\">Anchor link<\/a> <a href=\"#connecting-to-api-with-api-wrapper\">Connecting to API with API wrapper<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">When consuming data from DADI API programmatically from a JavaScript application, you can use <a href=\"https:\/\/github.com\/dadi\/api-wrapper\">DADI API wrapper<\/a> as a high-level API to build your requests, allowing you to abstract most of the formalities around building an HTTP request and setting the right headers for the content type and authentication.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">In the example below, we can see how you could connect to an instance of DADI API and retrieve all the documents that match a certain query, which you can define using a <a href=\"https:\/\/github.com\/dadi\/api-wrapper#filters\">set of filters<\/a> that use a natural, conversational syntax.<\/p>\n<pre><code class=\"lang-js\">const DadiAPI = <span class=\"hljs-built_in\">require<\/span>(<span class=\"hljs-string\">'@dadi\/api-wrapper'<\/span>)\nlet api = <span class=\"hljs-keyword\">new<\/span> DadiAPI({\n  uri: <span class=\"hljs-string\">'https:\/\/api.somedomain.tech'<\/span>,\n  port: <span class=\"hljs-number\">80<\/span>,\n  credentials: {\n    clientId: <span class=\"hljs-string\">'johndoe'<\/span>,\n    secret: <span class=\"hljs-string\">'f00b4r'<\/span>\n  },\n  version: <span class=\"hljs-string\">'1.0'<\/span>,\n  database: <span class=\"hljs-string\">'my-db'<\/span>\n})\n<span class=\"hljs-regexp\">\/\/<\/span> Example: getting all documents where `<span class=\"javascript\">name<\/span>` contains <span class=\"hljs-string\">\"john\"<\/span> <span class=\"hljs-keyword\">and<\/span> age <span class=\"hljs-keyword\">is<\/span> greater than <span class=\"hljs-number\">18<\/span>\napi.<span class=\"hljs-keyword\">in<\/span>(<span class=\"hljs-string\">'users'<\/span>)\n .whereFieldContains(<span class=\"hljs-string\">'name'<\/span>, <span class=\"hljs-string\">'john'<\/span>)\n .whereFieldIsGreaterThan(<span class=\"hljs-string\">'age'<\/span>, <span class=\"hljs-number\">18<\/span>)\n .find()\n .<span class=\"hljs-keyword\">then<\/span>(<span class=\"hljs-function\"><span class=\"hljs-params\">({metadata, results})<\/span> =&gt;<\/span> {\n   <span class=\"hljs-regexp\">\/\/<\/span> Use documents here\n   processData(results)\n })\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\">For more information about API wrapper, including a comprehensive list of its filters and terminator functions, check the <a href=\"https:\/\/github.com\/dadi\/api-wrapper\">GitHub repository<\/a>.<\/p>\n<h3><a href=\"#auto-generate-documentation\" id=\"auto-generate-documentation\" name=\"auto-generate-documentation\" class=\"anchor\">Anchor link<\/a> <a href=\"#auto-generate-documentation\">Auto generate documentation<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">The <code>@dadi\/apidoc<\/code> package provides a set of auto-generated documentation for your API installation, reading information from the collection schemas and custom endpoints to describe the available HTTP methods and parameters required to interact with the API.<\/p>\n<ul>\n<li><a href=\"#generating-code-snippets\">Generating Code Snippets<\/a><\/li>\n<li><a href=\"#documenting-custom-endpoints\">Documenting custom endpoints<\/a><\/li>\n<li><a href=\"#showing-useful-example-values\">Showing useful example values<\/a><\/li>\n<li><a href=\"#excluding-collections-endpoints-and-fields\">Excluding Collections, Endpoints and Fields<\/a><\/li>\n<\/ul>\n<h4><a href=\"#installation-steps\" id=\"installation-steps\" name=\"installation-steps\" class=\"anchor\">Anchor link<\/a> <a href=\"#installation-steps\">Installation steps<\/a><\/h4>\n<ol>\n<li>Inside your API installation directory, run the following:<\/li>\n<\/ol>\n<pre><code class=\"lang-console\">$ <span class=\"hljs-built_in\">npm<\/span> install @dadi\/apidoc --save\n<\/code><\/pre>\n<ol start=\"2\">\n<li>The configuration file for API must be modified to enable the documentation middleware. Add an <code>apidoc<\/code> section to the configuration file:<\/li>\n<\/ol>\n<pre><code class=\"lang-js\"><span class=\"hljs-comment\">\"apidoc\"<\/span>: {\n  <span class=\"hljs-comment\">\"title\"<\/span>: <span class=\"hljs-comment\">\"&lt;Project Name&gt; Content API\"<\/span>,\n  <span class=\"hljs-comment\">\"description\"<\/span>: <span class=\"hljs-comment\">\"This is the _Content API_ for [Example](http:\/\/www.example.com).\"<\/span>,\n  <span class=\"hljs-comment\">\"markdown\"<\/span>: <span class=\"hljs-keyword\">false<\/span>,\n  <span class=\"hljs-comment\">\"path\"<\/span>: <span class=\"hljs-comment\">\"docs\"<\/span>,\n  <span class=\"hljs-comment\">\"generateCodeSnippets\"<\/span>: <span class=\"hljs-keyword\">false<\/span>,\n  <span class=\"hljs-comment\">\"themeVariables\"<\/span>: <span class=\"hljs-comment\">\"default\"<\/span>,\n  <span class=\"hljs-comment\">\"themeTemplate\"<\/span>: <span class=\"hljs-comment\">\"triple\"<\/span>,\n  <span class=\"hljs-comment\">\"themeStyle\"<\/span>: <span class=\"hljs-comment\">\"default\"<\/span>,\n  <span class=\"hljs-comment\">\"themeCondenseNav\"<\/span>: <span class=\"hljs-keyword\">true<\/span>,\n  <span class=\"hljs-comment\">\"themeFullWidth\"<\/span>: <span class=\"hljs-keyword\">false<\/span>\n}\n<\/code><\/pre>\n<ol start=\"3\">\n<li>Initialise the middleware from the main API entry point (such as the <code>main.js<\/code> or <code>index.js<\/code> file:<\/li>\n<\/ol>\n<pre><code class=\"lang-js\"><span class=\"hljs-keyword\">const<\/span> server = <span class=\"hljs-built_in\">require<\/span>(<span class=\"hljs-string\">'@dadi\/api'<\/span>)\n<span class=\"hljs-keyword\">const<\/span> config = <span class=\"hljs-built_in\">require<\/span>(<span class=\"hljs-string\">'@dadi\/api'<\/span>).Config\n<span class=\"hljs-keyword\">const<\/span> log = <span class=\"hljs-built_in\">require<\/span>(<span class=\"hljs-string\">'@dadi\/api'<\/span>).Log\nserver.start(<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span>(<span class=\"hljs-params\">&nbsp;<\/span>) <\/span>{\n  log.get().info(<span class=\"hljs-string\">'API Started'<\/span>)\n})\n<span class=\"hljs-comment\">\/\/ enable the documentation route<\/span>\n<span class=\"hljs-built_in\">require<\/span>(<span class=\"hljs-string\">'@dadi\/apidoc'<\/span>).init(server, config)\n<\/code><\/pre>\n<h4><a href=\"#browse-the-documentation\" id=\"browse-the-documentation\" name=\"browse-the-documentation\" class=\"anchor\">Anchor link<\/a> <a href=\"#browse-the-documentation\">Browse the documentation<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">The documentation can be accessed using the route <code>\/api\/1.0\/docs<\/code>, for example <code>https:\/\/api.somedomain.tech\/api\/1.0\/docs<\/code>.<\/p>\n<h4><a href=\"#generating-code-snippets\" id=\"generating-code-snippets\" name=\"generating-code-snippets\" class=\"anchor\">Anchor link<\/a> <a href=\"#generating-code-snippets\">Generating Code Snippets<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">If you want to generate code snippets (made possible by the configuration option<br \/>\n  <code>generateCodeSnippets<\/code>) you&#39;ll need to ensure sure your system has the following:<\/p>\n<ol>\n<li>Ruby, and the Ruby gem <code>awesome_print<\/code>:<\/li>\n<\/ol>\n<pre><code class=\"lang-console\"><span class=\"hljs-meta\">$<\/span><span class=\"bash\"> gem install awesome_print<\/span>\n<\/code><\/pre>\n<ol start=\"2\">\n<li>The <code>httpsnippet<\/code> package:<\/li>\n<\/ol>\n<pre><code class=\"lang-console\"><span class=\"hljs-meta\">$<\/span><span class=\"bash\"> npm install httpsnippet -g<\/span>\n<\/code><\/pre>\n<h4><a href=\"#documenting-custom-endpoints\" id=\"documenting-custom-endpoints\" name=\"documenting-custom-endpoints\" class=\"anchor\">Anchor link<\/a> <a href=\"#documenting-custom-endpoints\">Documenting custom endpoints<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">API collections are automatically documented using values from within the collection specification files. To have your documentation include useful information about custom endpoints, add <a href=\"http:\/\/usejsdoc.org\/\">JSDoc<\/a> comments to the endpoint files:<\/p>\n<pre><code class=\"lang-js\">\/**\n * Adds two numbers together.\n *\n * <span class=\"hljs-string\">``<\/span><span class=\"hljs-string\">`js\n * let result = add(1, 2);\n * `<\/span><span class=\"hljs-string\">``<\/span>\n *\n * @param {int} <span class=\"hljs-string\">`num1`<\/span> The first number.\n * @param {int} <span class=\"hljs-string\">`num2`<\/span> The second number.\n * @returns {int} The sum of the two numbers.\n * @api public\n *<span class=\"hljs-regexp\">\/<\/span>\n<\/code><\/pre>\n<h4><a href=\"#showing-useful-example-values\" id=\"showing-useful-example-values\" name=\"showing-useful-example-values\" class=\"anchor\">Anchor link<\/a> <a href=\"#showing-useful-example-values\">Showing useful example values<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">To show example data in the documentation that isn&#39;t simply the default of &quot;Hello World!&quot;, you can add properties to fields in the API collection specification file. The following properties can be added to fields:<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><code>example<\/code><\/strong>: the <code>example<\/code> property is a static value that will be the same every time you view the documentation:<\/p>\n<pre><code class=\"lang-json\"><span class=\"hljs-string\">\"platform\"<\/span>: {\n  <span class=\"hljs-string\">\"type\"<\/span>: <span class=\"hljs-string\">\"String\"<\/span>,\n  <span class=\"hljs-string\">\"required\"<\/span>: true,\n  <span class=\"hljs-string\">\"example\"<\/span>: <span class=\"hljs-string\">\"twitter\"<\/span>,\n  <span class=\"hljs-string\">\"validation\"<\/span>: {\n    <span class=\"hljs-string\">\"regex\"<\/span>: {\n      <span class=\"hljs-string\">\"pattern\"<\/span>: <span class=\"hljs-string\">\"twitter|facebook|instagram\"<\/span>\n    }\n  }\n}\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\"><strong><code>testDataFormat<\/code><\/strong>: the <code>testDataFormat<\/code> property allows you to specify any type from the <a href=\"https:\/\/github.com\/FotoVerite\/Faker.js\">faker<\/a> package, which will insert a random value of the selected type each time the documentation is viewed:<\/p>\n<pre><code class=\"lang-json\"><span class=\"hljs-string\">\"email\"<\/span>: {\n  <span class=\"hljs-string\">\"type\"<\/span>: <span class=\"hljs-string\">\"String\"<\/span>,\n  <span class=\"hljs-string\">\"required\"<\/span>: true,\n  <span class=\"hljs-string\">\"testDataFormat\"<\/span>: <span class=\"hljs-string\">\"{{internet.email}}\"<\/span>\n  <span class=\"hljs-string\">\"validation\"<\/span>: {\n    <span class=\"hljs-string\">\"regex\"<\/span>: {\n      <span class=\"hljs-string\">\"pattern\"<\/span>: <span class=\"hljs-string\">\".+@.+\"<\/span>\n    }\n  }\n}\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\">See a list of available options <a href=\"https:\/\/github.com\/FotoVerite\/Faker.js\">here<\/a>.<\/p>\n<h4><a href=\"#excluding-collections-endpoints-and-fields\" id=\"excluding-collections-endpoints-and-fields\" name=\"excluding-collections-endpoints-and-fields\" class=\"anchor\">Anchor link<\/a> <a href=\"#excluding-collections-endpoints-and-fields\">Excluding collections, endpoints and fields<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">Often an API contains collections and collection fields that are meant for internal use and including them in the API documentation is undesirable.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">To exclude collections and fields from your generated documentation, see the following sections.<\/p>\n<h5><a href=\"#excluding-collections\" id=\"excluding-collections\" name=\"excluding-collections\" class=\"anchor\">Anchor link<\/a> <a href=\"#excluding-collections\">Excluding collections<\/a><\/h5>\n<p class=\"7xtjw4dqwy5mz7w3j\">Add a <code>private<\/code> property to the collection specification&#39;s <code>settings<\/code> section:<\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"fields\"<\/span>: {\n    <span class=\"hljs-attr\">\"title\"<\/span>: {\n      <span class=\"hljs-attr\">\"type\"<\/span>: <span class=\"hljs-string\">\"String\"<\/span>,\n      <span class=\"hljs-attr\">\"required\"<\/span>: <span class=\"hljs-literal\">true<\/span>\n    },\n    <span class=\"hljs-attr\">\"author\"<\/span>: {\n      <span class=\"hljs-attr\">\"type\"<\/span>: <span class=\"hljs-string\">\"Reference\"<\/span>,\n      <span class=\"hljs-attr\">\"settings\"<\/span>: {\n        <span class=\"hljs-attr\">\"collection\"<\/span>: <span class=\"hljs-string\">\"people\"<\/span>\n      }\n    }\n  },\n  <span class=\"hljs-attr\">\"settings\"<\/span>: {\n    <span class=\"hljs-attr\">\"cache\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n    <span class=\"hljs-attr\">\"count\"<\/span>: <span class=\"hljs-number\">40<\/span>,\n    <span class=\"hljs-attr\">\"sort\"<\/span>: <span class=\"hljs-string\">\"title\"<\/span>,\n    <span class=\"hljs-attr\">\"sortOrder\"<\/span>: <span class=\"hljs-number\">1<\/span>,\n    <span class=\"hljs-attr\">\"private\"<\/span>: <span class=\"hljs-literal\">true<\/span>\n  }\n}\n<\/code><\/pre>\n<h5><a href=\"#excluding-endpoints\" id=\"excluding-endpoints\" name=\"excluding-endpoints\" class=\"anchor\">Anchor link<\/a> <a href=\"#excluding-endpoints\">Excluding endpoints<\/a><\/h5>\n<p class=\"7xtjw4dqwy5mz7w3j\">Add a <code>private<\/code> property to the endpoint file&#39;s <code>model.settings<\/code> section:<\/p>\n<pre><code class=\"lang-js\"><span class=\"hljs-built_in\">module<\/span>.exports.get = <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> (<span class=\"hljs-params\">req, res, next<\/span>) <\/span>{\n  res.setHeader(<span class=\"hljs-string\">'content-type'<\/span>, <span class=\"hljs-string\">'application\/json'<\/span>)\n  res.statusCode = <span class=\"hljs-number\">200<\/span>\n  res.end(<span class=\"hljs-built_in\">JSON<\/span>.stringify({<span class=\"hljs-attr\">message<\/span>: <span class=\"hljs-string\">'Hello World'<\/span>}))\n}\n<span class=\"hljs-built_in\">module<\/span>.exports.model = {\n  <span class=\"hljs-string\">\"settings\"<\/span>: {\n    <span class=\"hljs-string\">\"cache\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n    <span class=\"hljs-string\">\"authenticate\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n    <span class=\"hljs-string\">\"private\"<\/span>: <span class=\"hljs-literal\">true<\/span>\n  }\n}\n<\/code><\/pre>\n<h5><a href=\"#excluding-fields\" id=\"excluding-fields\" name=\"excluding-fields\" class=\"anchor\">Anchor link<\/a> <a href=\"#excluding-fields\">Excluding fields<\/a><\/h5>\n<p class=\"7xtjw4dqwy5mz7w3j\">Add a <code>private<\/code> property to the field specification:<\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"fields\"<\/span>: {\n    <span class=\"hljs-attr\">\"title\"<\/span>: {\n      <span class=\"hljs-attr\">\"type\"<\/span>: <span class=\"hljs-string\">\"String\"<\/span>,\n      <span class=\"hljs-attr\">\"required\"<\/span>: <span class=\"hljs-literal\">true<\/span>\n    },\n    <span class=\"hljs-attr\">\"internalId\"<\/span>: {\n      <span class=\"hljs-attr\">\"type\"<\/span>: <span class=\"hljs-string\">\"Number\"<\/span>,\n      <span class=\"hljs-attr\">\"required\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n      <span class=\"hljs-attr\">\"private\"<\/span>: <span class=\"hljs-literal\">true<\/span>\n    }\n  },\n  <span class=\"hljs-attr\">\"settings\"<\/span>: {\n    <span class=\"hljs-attr\">\"cache\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n    <span class=\"hljs-attr\">\"count\"<\/span>: <span class=\"hljs-number\">40<\/span>,\n    <span class=\"hljs-attr\">\"sort\"<\/span>: <span class=\"hljs-string\">\"title\"<\/span>,\n    <span class=\"hljs-attr\">\"sortOrder\"<\/span>: <span class=\"hljs-number\">1<\/span>\n  }\n}\n<\/code><\/pre>\n<h2><a href=\"#errors\" id=\"errors\" name=\"errors\" class=\"anchor\">Anchor link<\/a> <a href=\"#errors\">Errors<\/a><\/h2>\n<h3><a href=\"#api-0001\" id=\"api-0001\" name=\"api-0001\" class=\"anchor\">Anchor link<\/a> <a href=\"#api-0001\">API-0001<\/a><\/h3>\n<h4><a href=\"#missing-index-key\" id=\"missing-index-key\" name=\"missing-index-key\" class=\"anchor\">Anchor link<\/a> <a href=\"#missing-index-key\">Missing Index Key<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">You received an error similar to this:<\/p>\n<pre><code class=\"lang-json\">{\n  \"code\": \"API-0001\",\n  \"title\": \"Missing <span class=\"hljs-keyword\">Index<\/span> <span class=\"hljs-keyword\">Key<\/span><span class=\"hljs-string\">\",\n  \"<\/span>details<span class=\"hljs-string\">\": \"<\/span><span class=\"hljs-string\">'name'<\/span> <span class=\"hljs-keyword\">is<\/span> specified <span class=\"hljs-keyword\">as<\/span> the <span class=\"hljs-keyword\">primary<\/span> sort field, but <span class=\"hljs-keyword\">is<\/span> <span class=\"hljs-literal\">missing<\/span> <span class=\"hljs-keyword\">from<\/span> the <span class=\"hljs-keyword\">index<\/span> <span class=\"hljs-keyword\">key<\/span> <span class=\"hljs-keyword\">collection<\/span>.<span class=\"hljs-string\">\"\n}<\/span>\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\">[TODO]\n<h3><a href=\"#api-0002\" id=\"api-0002\" name=\"api-0002\" class=\"anchor\">Anchor link<\/a> <a href=\"#api-0002\">API-0002<\/a><\/h3>\n<h4><a href=\"#hook-error\" id=\"hook-error\" name=\"hook-error\" class=\"anchor\">Anchor link<\/a> <a href=\"#hook-error\">Hook Error<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">You received an error similar to this:<\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"success\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n  <span class=\"hljs-attr\">\"errors\"<\/span>: [\n    {\n      <span class=\"hljs-attr\">\"code\"<\/span>: <span class=\"hljs-string\">\"API-0002\"<\/span>,\n      <span class=\"hljs-attr\">\"title\"<\/span>: <span class=\"hljs-string\">\"Hook Error\"<\/span>,\n      <span class=\"hljs-attr\">\"details\"<\/span>: <span class=\"hljs-string\">\"The hook 'myHook' failed: 'ReferenceError: title is not defined'\"<\/span>\n    }\n  ]\n}\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\">[TODO]\n<h3><a href=\"#api-0003\" id=\"api-0003\" name=\"api-0003\" class=\"anchor\">Anchor link<\/a> <a href=\"#api-0003\">API-0003<\/a><\/h3>\n<h4><a href=\"#cache-path-missing\" id=\"cache-path-missing\" name=\"cache-path-missing\" class=\"anchor\">Anchor link<\/a> <a href=\"#cache-path-missing\">Cache Path Missing<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">To flush the cache, a path that matches a collection resource must be specified in the request body:<\/p>\n<pre><code class=\"lang-http\"><span class=\"hljs-keyword\">POST<\/span> <span class=\"hljs-string\">\/api\/flush<\/span> HTTP\/1.1\n<span class=\"hljs-attribute\">Host<\/span>: api.example.com\n<span class=\"hljs-attribute\">Authorization<\/span>: Bearer 4172bbf1-0890-41c7-b0db-477095a288b6\n<span class=\"hljs-attribute\">Content-Type<\/span>: application\/json\n<span class=\"json\">{ <span class=\"hljs-attr\">\"path\"<\/span>: <span class=\"hljs-string\">\"\/1.0\/library\/books\"<\/span> }<\/span>\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\">This command will flush all cache files that match the collection path specified.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">A successful cache flush returns a HTTP 200 response:<\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"result\"<\/span>: <span class=\"hljs-string\">\"success\"<\/span>,\n  <span class=\"hljs-attr\">\"message\"<\/span>: <span class=\"hljs-string\">\"Cache flush successful\"<\/span>\n}\n<\/code><\/pre>\n<h5><a href=\"#flush-all-files-1\" id=\"flush-all-files-1\" name=\"flush-all-files-1\" class=\"anchor\">Anchor link<\/a> <a href=\"#flush-all-files-1\">Flush all files<\/a><\/h5>\n<p class=\"7xtjw4dqwy5mz7w3j\">To flush all cache files, send <code>{ path: &quot;*&quot; }<\/code><\/p>\n<h3><a href=\"#migrating-from-version-2x-to-3x\" id=\"migrating-from-version-2x-to-3x\" name=\"migrating-from-version-2x-to-3x\" class=\"anchor\">Anchor link<\/a> <a href=\"#migrating-from-version-2x-to-3x\">Migrating from version 2.x to 3.x<\/a><\/h3>\n<p class=\"7xtjw4dqwy5mz7w3j\">API 3.0 comes with various performance and flexibility enhancements, some of which introduce breaking changes. This document is an overview of the changes that are required to make your application ready for the upgrade. <\/p>\n<h4><a href=\"#configuring-a-database-and-data-connector\" id=\"configuring-a-database-and-data-connector\" name=\"configuring-a-database-and-data-connector\" class=\"anchor\">Anchor link<\/a> <a href=\"#configuring-a-database-and-data-connector\">Configuring a database and data connector<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">Whilst API 2.0 requires a MongoDB database to run, version 3.0 is capable of working with virtually any database engine, as long as there is a data connector module for it.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">When migrating from 2.0, we need to explicitly specify MongoDB as our database engine by adding <code>@dadi\/api-mongodb<\/code> as a project dependency:<\/p>\n<pre><code class=\"lang-bash\">$ <span class=\"hljs-built_in\">npm<\/span> install @dadi\/api-mongodb --save\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\">API requires each data connector to have its own configuration file located in the same directory as API&#39;s main configuration files. Just like API, you&#39;ll need one for each environment you run the application in.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">For example, if you currently have a <code>config.development.json<\/code> and <code>config.production.json<\/code> configuration files, you&#39;ll need to place <code>mongodb.development.json<\/code> and <code>mongodb.production.json<\/code> in the same directory.<\/p>\n<pre><code class=\"lang-bash\">api-app\/\n  <span class=\"hljs-built_in\">config<\/span>\/              <span class=\"hljs-meta\"># contains environment-specific configuration files<\/span>\n    <span class=\"hljs-built_in\">config<\/span>.development.json\n    <span class=\"hljs-built_in\">config<\/span>.production.json\n    mongodb.development.json\n    mongodb.production.json\n  package.json\n  workspace\/\n    collections\/       \n    endpoints\/         \n<\/code><\/pre>\n<h5><a href=\"#automatic-migration-script\" id=\"automatic-migration-script\" name=\"automatic-migration-script\" class=\"anchor\">Anchor link<\/a> <a href=\"#automatic-migration-script\">Automatic migration script<\/a><\/h5>\n<p class=\"7xtjw4dqwy5mz7w3j\">We&#39;ve added a migration script which can backup your existing API 2.0 configuration files and generate new API 3.0-compatible files automatically.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\">To use it, run the following command from your existing API directory:<\/p>\n<pre><code class=\"lang-bash\">$ curl https:<span class=\"hljs-regexp\">\/\/<\/span>raw.githubusercontent.com<span class=\"hljs-regexp\">\/dadi\/<\/span>registry<span class=\"hljs-regexp\">\/master\/<\/span>api<span class=\"hljs-regexp\">\/migration-scripts\/<\/span>v2-v3.js | node\n<\/code><\/pre>\n<h5><a href=\"#manual-configuration\" id=\"manual-configuration\" name=\"manual-configuration\" class=\"anchor\">Anchor link<\/a> <a href=\"#manual-configuration\">Manual configuration<\/a><\/h5>\n<p class=\"7xtjw4dqwy5mz7w3j\">If you&#39;re configuring this manually, follow these steps:<\/p>\n<ol>\n<li>\n<p class=\"7xtjw4dqwy5mz7w3j\">Remove the contents of the <code>database<\/code> property from each of your API configuration files, and paste it into the corresponding MongoDB configuration file, so that it looks similar to the following:<\/p>\n<pre><code class=\"lang-json\"> {\n   <span class=\"hljs-attr\">\"hosts\"<\/span>: [\n     {\n       <span class=\"hljs-attr\">\"host\"<\/span>: <span class=\"hljs-string\">\"123.456.78.9\"<\/span>,\n       <span class=\"hljs-attr\">\"port\"<\/span>: <span class=\"hljs-number\">27017<\/span>\n     }\n   ],\n   <span class=\"hljs-attr\">\"username\"<\/span>: <span class=\"hljs-string\">\"\"<\/span>,\n   <span class=\"hljs-attr\">\"password\"<\/span>: <span class=\"hljs-string\">\"\"<\/span>,\n   <span class=\"hljs-attr\">\"testdb\"<\/span>: {\n     <span class=\"hljs-attr\">\"hosts\"<\/span>: [\n       {\n         <span class=\"hljs-attr\">\"host\"<\/span>: <span class=\"hljs-string\">\"111.222.33.4\"<\/span>,\n         <span class=\"hljs-attr\">\"port\"<\/span>: <span class=\"hljs-number\">27017<\/span>\n       }\n     ]\n   }\n }\n<\/code><\/pre>\n<\/li>\n<li>\n<p class=\"7xtjw4dqwy5mz7w3j\">Each block of database overrides should now be namespaced under a <code>databases<\/code> block. Using the above as our example, it should now be similar to the following. Notice how we&#39;ve moved the <code>&quot;testdb&quot;<\/code> database configuration <em>inside<\/em> the new <code>&quot;databases&quot;<\/code> block:<\/p>\n<\/li>\n<\/ol>\n<pre><code>```json\n{\n  <span class=\"hljs-string\">\"hosts\"<\/span>: [\n    {\n      <span class=\"hljs-string\">\"host\"<\/span>: <span class=\"hljs-string\">\"123.456.78.9\"<\/span>,\n      <span class=\"hljs-string\">\"port\"<\/span>: <span class=\"hljs-number\">27017<\/span>\n    }\n  ],\n  <span class=\"hljs-string\">\"username\"<\/span>: <span class=\"hljs-string\">\"\"<\/span>,\n  <span class=\"hljs-string\">\"password\"<\/span>: <span class=\"hljs-string\">\"\"<\/span>,\n  <span class=\"hljs-string\">\"databases\"<\/span>: {\n    <span class=\"hljs-string\">\"testdb\"<\/span>: {\n      <span class=\"hljs-string\">\"hosts\"<\/span>: [\n        {\n          <span class=\"hljs-string\">\"host\"<\/span>: <span class=\"hljs-string\">\"111.222.33.4\"<\/span>,\n          <span class=\"hljs-string\">\"port\"<\/span>: <span class=\"hljs-number\">27017<\/span>\n        }\n      ]\n    }\n  }\n}\n```\n<\/code><\/pre>\n<ol start=\"3\">\n<li>In the API configuration files, add a new property <code>&quot;datastore&quot;<\/code> where the <code>&quot;database&quot;<\/code> property was. It should have the value <code>&quot;@dadi\/api-mongodb&quot;<\/code>:<\/li>\n<\/ol>\n<pre><code>```json\n{\n  <span class=\"hljs-string\">\"server\"<\/span>: {\n    <span class=\"hljs-string\">\"host\"<\/span>: <span class=\"hljs-string\">\"127.0.0.1\"<\/span>,\n    <span class=\"hljs-string\">\"port\"<\/span>: <span class=\"hljs-number\">8000<\/span>\n  },\n  <span class=\"hljs-string\">\"datastore\"<\/span>: <span class=\"hljs-string\">\"@dadi\/api-mongodb\"<\/span>,\n  <span class=\"hljs-string\">\"caching\"<\/span>: {\n  }\n}\n```\n<\/code><\/pre>\n<ol start=\"4\">\n<li>\n<p class=\"7xtjw4dqwy5mz7w3j\">Your API configuration files should have an <code>&quot;auth&quot;<\/code> containing a <code>&quot;database&quot;<\/code> block. Change this to simply the name of the database you want to use for authentication, and add a <code>&quot;datastore&quot;<\/code> property with the value <code>&quot;@dadi\/api-mongodb&quot;<\/code>.<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"> <em>Before (<code>config.development.json<\/code>)<\/em><\/p>\n<pre><code class=\"lang-json\"> {\n   <span class=\"hljs-attr\">\"auth\"<\/span>: {\n     <span class=\"hljs-attr\">\"tokenUrl\"<\/span>: <span class=\"hljs-string\">\"\/token\"<\/span>,\n     <span class=\"hljs-attr\">\"tokenTtl\"<\/span>: <span class=\"hljs-number\">1800<\/span>,\n     <span class=\"hljs-attr\">\"clientCollection\"<\/span>: <span class=\"hljs-string\">\"clientStore\"<\/span>,\n     <span class=\"hljs-attr\">\"tokenCollection\"<\/span>: <span class=\"hljs-string\">\"tokenStore\"<\/span>,\n     <span class=\"hljs-attr\">\"database\"<\/span>: {\n       <span class=\"hljs-attr\">\"hosts\"<\/span>: [\n         {\n           <span class=\"hljs-attr\">\"host\"<\/span>: <span class=\"hljs-string\">\"127.0.0.1\"<\/span>,\n           <span class=\"hljs-attr\">\"port\"<\/span>: <span class=\"hljs-number\">27017<\/span>\n         }\n       ],\n       <span class=\"hljs-attr\">\"username\"<\/span>: <span class=\"hljs-string\">\"\"<\/span>,\n       <span class=\"hljs-attr\">\"password\"<\/span>: <span class=\"hljs-string\">\"\"<\/span>,\n       <span class=\"hljs-attr\">\"database\"<\/span>: <span class=\"hljs-string\">\"dadiapiauth\"<\/span>\n     }\n   }\n }\n<\/code><\/pre>\n<p class=\"7xtjw4dqwy5mz7w3j\"> <em>After (<code>config.development.json<\/code>)<\/em><\/p>\n<pre><code class=\"lang-json\"> {\n   <span class=\"hljs-attr\">\"auth\"<\/span>: {\n     <span class=\"hljs-attr\">\"tokenUrl\"<\/span>: <span class=\"hljs-string\">\"\/token\"<\/span>,\n     <span class=\"hljs-attr\">\"tokenTtl\"<\/span>: <span class=\"hljs-number\">1800<\/span>,\n     <span class=\"hljs-attr\">\"clientCollection\"<\/span>: <span class=\"hljs-string\">\"clientStore\"<\/span>,\n     <span class=\"hljs-attr\">\"tokenCollection\"<\/span>: <span class=\"hljs-string\">\"tokenStore\"<\/span>,\n     <span class=\"hljs-attr\">\"datastore\"<\/span>: <span class=\"hljs-string\">\"@dadi\/api-mongodb\"<\/span>,\n     <span class=\"hljs-attr\">\"database\"<\/span>: <span class=\"hljs-string\">\"dadiapiauth\"<\/span>\n   },\n }\n<\/code><\/pre>\n<\/li>\n<li>\n<p class=\"7xtjw4dqwy5mz7w3j\">If your chosen authentication database (e.g. <code>&quot;dadiapiauth&quot;<\/code>) has different hosts to the default you must  ensure an entry exists for it in the <code>&quot;databases&quot;<\/code> block in <code>mongodb.development.json<\/code>:<\/p>\n<p class=\"7xtjw4dqwy5mz7w3j\"> <em><code>mongodb.development.json<\/code><\/em><\/p>\n<pre><code class=\"lang-json\"> {\n   <span class=\"hljs-attr\">\"databases\"<\/span>: {\n     <span class=\"hljs-attr\">\"dadiapiauth\"<\/span>: {\n       <span class=\"hljs-attr\">\"hosts\"<\/span>: [\n         {\n           <span class=\"hljs-attr\">\"host\"<\/span>: <span class=\"hljs-string\">\"222.333.44.5\"<\/span>,\n           <span class=\"hljs-attr\">\"port\"<\/span>: <span class=\"hljs-number\">27017<\/span>\n         }\n       ]\n     }\n   }  \n }\n<\/code><\/pre>\n<\/li>\n<\/ol>\n<h4><a href=\"#what#39s-next-1\" id=\"what#39s-next-1\" name=\"what#39s-next-1\" class=\"anchor\">Anchor link<\/a> <a href=\"#what#39s-next-1\">What&#39;s next?<\/a><\/h4>\n<p class=\"7xtjw4dqwy5mz7w3j\">While the above configuration changes should be enough to get the application started, there are several more changes you should know about. They can be found in detail in the release notes for <a href=\"https:\/\/github.com\/dadi\/api\/releases\/tag\/v3.0.0\">API Vesion 3.0<\/a>.<\/p>\n<\/p><\/div>\n","protected":false,"raw":""},"excerpt":{"rendered":"<p>Anchor link Requirements Microservices in the DADI platform are [&hellip;]<\/p>\n","protected":false},"author":0,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"template_12.php","meta":{"footnotes":""},"class_list":["post-9","page","type-page","status-publish","hentry"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v24.2 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>DADI API Documentation<\/title>\n<meta name=\"description\" content=\"Documentation for DADI microservices.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"http:\/\/dadi.cloud\/docs-sub\/api\/\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"DADI API Documentation\" \/>\n<meta property=\"og:description\" content=\"Documentation for DADI microservices.\" \/>\n<meta property=\"og:url\" content=\"http:\/\/dadi.cloud\/docs-sub\/api\/\" \/>\n<meta property=\"og:site_name\" content=\"The local global network | DADI\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data1\" content=\"133 minutes\" \/>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"DADI API Documentation","description":"Documentation for DADI microservices.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"http:\/\/dadi.cloud\/docs-sub\/api\/","og_type":"article","og_title":"DADI API Documentation","og_description":"Documentation for DADI microservices.","og_url":"http:\/\/dadi.cloud\/docs-sub\/api\/","og_site_name":"The local global network | DADI","twitter_card":"summary_large_image","twitter_misc":{"Est. reading time":"133 minutes"}},"_links":{"self":[{"href":"https:\/\/dadi.cloud\/wp-json\/wp\/v2\/pages\/9","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dadi.cloud\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/dadi.cloud\/wp-json\/wp\/v2\/types\/page"}],"replies":[{"embeddable":true,"href":"https:\/\/dadi.cloud\/wp-json\/wp\/v2\/comments?post=9"}],"version-history":[{"count":0,"href":"https:\/\/dadi.cloud\/wp-json\/wp\/v2\/pages\/9\/revisions"}],"wp:attachment":[{"href":"https:\/\/dadi.cloud\/wp-json\/wp\/v2\/media?parent=9"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}