Table of Contents
JSON API Endpoints
This section lists the different API endpoints you can use to access or update Protogrid data. The respective http method is defined as [METHOD] following the endpoint in this documentation.
Response
Every request to such an API endpoint returns a JSON object. The returned JSON object always contains an error and a result object. If the request was successful, the result object contains the requested or updated data. When the request fails, the errors object contains the error messages which occurred when trying to execute the request.
Example successful response
{ "errors": [], "protogrid_environment_version": "1.3.9", "result":{ "key": {…}, "key": […], "key": "data" } }
Example failure response
{ "errors": [ { … }, { … } ], "protogrid_environment_version": "1.3.9", "result": {} }
Field Types
In Protogrid there exist different types of fields such as numbers, text or dates.
Number Field
Text Field
Date Time Field
Protogrid always uses ISO 8601 standard in UTC timezone for storing date time values.
Relation Field
Role Field
Rich Text Field
Endpoints
The Protogrid JSON API offers the following API endpoints:
/api/v2/apps
[GET] Returns a list of all Applications to which the authenticated user has access to.
Example request:
https://example.protogrid.com/api/v2/apps
Example response:
{ "errors": [], "protogrid_environment_version": "1.3.9", "result":[ { "app_id": "appc55b3773-5503-4c41-a9aa-3a561c40fa04", "description": "Example App", "logo_url": "", "theme_color": "blue-dark", "title": "Example App ", "url": "/example", "url_name": "example" }, { "app_id": "appID", "description": "Your awesome app", … }, … ] }
/api/v2/apps/<app_id>
[GET] Returns basic information about one Application.
Example request:
https://example.protogrid.com/api/v2/apps/appc55b3773-5503-4c41-a9aa-3a561c40fa04
Example response:
{ "errors": [], "protogrid_environment_version": "1.3.9", "result": { "app_id": "appc55b3773-5503-4c41-a9aa-3a561c40fa04", "description": "Example App", "logo_url": "", "theme_color": "blue-dark", "title": "Example App ", "url": "/example", "url_name": "example" } }
/api/v2/apps/<app_id>/views
[GET] Returns a list of all view names in this Application. Details on what views are supported, see all available views.
Example request:
https://example.protogrid.com/api/v2/apps/appc55b3773-5503-4c41-a9aa-3a561c40fa04/views
Example response:
{ "errors": [], "protogrid_environment_version": "1.3.9", "result": { "views": [ {"view_name": "examples_by_id"}, {…} ] } }
/api/v2/apps/<app_id>/views/<view_name>
Most of the API endpoints except you to specify App or Card IDs. At the time at which this data is requested, these ids therefore already need to be known. It is therefore necessary to have convenient ways of asking Protogrid about what ids are available based on different search criteria. Database views can be used to acquire collections of data based on sorting and filtering URL parameters.
[GET] Returns all the entries in the specified view. Please note that URL parameters must be URI encoded. URL Parameter:
- start_key: [“proto_key”, “column_key”, “filter_value”, null], where column_key and filter_value are optional.
- end_key: [“proto_key”, “column_key”, “filter_value”, {}], where column_key and filter_value are optional
- keys: [“key1”, “key2”, “key3”, …], only returns the entries for the specified keys
- page_number: Number of the desired page starting at 0 for the first page. Page length is determined by the 'limit' parameter (counted before filtering for read access rights).
- limit: Accepts a number, which defines how many Cards are returned at most with the result object. Fewer Cards can be returned if not all Cards are visible due to read acces restrictions.
- Example: limit=15
- Default value: 10
- descending: If set to true the results will be in descending order. If set to true start_key and end_key must be exchanged.
- Example: descending=true
- Default value: False
- include_cards: If set to true the result contains the cards for the keys as well.
- Example: include_cards=true
- Default value: False
- Please note that the “include_cards” parameter has a high cost in terms of performance. We therefore recommend using this functionality very economically, i.e. on as few view rows as possible.
Please note:
- You may only use either “keys” or “start_key” and “end_key”.
- Key values must be cut off after 300 characters (e. g. string values and sortstrings) because these values are also cut off in the view index.
Details: For more details about the URL parameters see the CouchDB documentation.
Full list of views can be found here.
Example request:
https://example.protogrid.com/api/v2/apps/appc55b3773-5503-4c41-a9aa-3a561c40fa04/views/example_view?start_key=["example_proto_key",null]&end_key=["example_proto_key",{}]&page_number=1&limit=2&descending=false
The URL parameters need to be URI encoded. So from the example above the start_key parameter would look like
start_key= %5B%22example_proto_key%22%2Cnull%5D
Example response:
{ "errors": [], "protogrid_environment_version": "1.3.9", "result": { "next_card_key": "key", "rows": [ {"key": "example_document_key"}, {…} ] } }
/api/v2/apps/<app_id>/cards
[POST] Creates a new Card. It is necessary to specify a 'proto_key' denoting the Proto on which the new Card will be based. Initial values for the 'design_elements' can be sent along. Mandatory design elements must always be set. If a Card ID of an existing card is specified in the property '_id', Protogrid updates this Card with the provided data. If an array of Card objects is supplied in the POST request body, all of them will be created/updated as a bulk operation. Note that in bulk operation either all or none of the passed Cards will be saved. For example, out of 100 Cards, none will be saved if a single Card has caused validation errors. As response this endpoint returns a list of all created/updated Cards.
Example request:
https://example.protogrid.com/api/v2/apps/appc55b3773-5503-4c41-a9aa-3a561c40fa04/cards
In the POST request body, a JSON object needs to be sent as shown in the following example:
{ "proto_key": "some_proto_key", "design_elements": [ { "definition_key": "example_design_element_key", "value": "example_value" }, … ] }
Example response:
{ "errors": [], "messages": [], "protogrid_environment_version": "2.1.5", "result": { "_id": "some_card_id", "_rev": "some_rev_id", "denormalized": {…}, "design_elements": {…}, … } }
Deprecated functionalities:
- Specification of a user-defined Card ID for a new Card: In previous versions, it was possible to freely specify the Card ID for a new Card in the '_id' property. This functionality is deprecated and cannot be used in future releases. In particular, instead of relying on this feature to insert foreign IDs into Protogrid, we suggest using an additional auxiliary field containing the foreign ID.
/api/v2/apps/<app_id>/cards/<card_key>
[GET] Returns a specific Card identified by 'card_key'.
[DELETE] Logically deletes a specific Card identified by 'card_key'. Please note that the deleted Card will be still available, either through the API or the UI using the trash. The return value contains the newly deleted Card.
[POST] Updates an existing Card identified by 'card_key'. If the '_id' property is set in the JSON, it needs to match the 'card_key'. In addition, the 'proto_key' must match that of the existing Card.
Example request:
https://example.protogrid.com/api/v2/apps/appc55b3773-5503-4c41-a9aa-3a561c40fa04/cards/some_card_id
In the POST request body, a JSON object needs to be sent as shown in the following example:
{ "_id": "some_card_id", "proto_key": "some_proto_key", "design_elements": [ { "definition_key": "example_design_element_key", "value": "example_value" }, … ] }
Example response:
{ "errors": [], "messages": [], "protogrid_environment_version": "2.1.5", "result": { "_id": "some_card_id", "_rev": "some_rev_id", "denormalized": {…}, "design_elements": {…}, … } }
/api/v2/apps/<app_id>/cards/<card_key>/attachments/<file_name>
[GET] Returns the attachment identified by 'file_name' of a Card identified by 'card_key'.
[PUT] Uploads the Form Data attachment with name 'attachment-upload' to the specified Card. If this Card already has an attachment with the specified file name, the existing attachment is replaced by the uploaded one.
Example GET request:
https://example.protogrid.com/api/v2/apps/appc55b3773-5503-4c41-a9aa-3a561c40fa04/cards/89e74e40-b0ef-4bc3-8e89-a43a43763087/attachments/Bildschirmfoto%202021-01-22%20um%2014.11.15.png
Example code for PUT request:
var HOST = "https://example.protogrid.com/"; var APP_NAME = "example_app"; var CARD_KEY = "89e74e40-b0ef-4bc3-8e89-a43a43763087"; function uploadFile(file, progressCallback, successCallback) { function createFormData(file) { var data = new FormData(); data.append("Content-Type", file.type); data.append("attachment-upload", file); return data; } var attachment_base_url = HOST + "api/v2/apps/" + APP_NAME + "/cards/" + CARD_KEY + "/attachments/"; var initial_file_name = file.name; var xhr = new XMLHttpRequest(); xhr.open("PUT", attachment_base_url + initial_file_name, true); xhr.upload.addEventListener("progress", function(progress_event) { var progress = progress_event.loaded / progress_event.total * 66; // We want the progress bar to show "loading" until the server response is back. progressCallback(progress); }); xhr.addEventListener("load", function() { if (xhr.status == 200) { var saved_filename = initial_file_name; if (xhr.response && typeof(xhr.response) === 'string' && xhr.response !== '') { var response = JSON.parse(xhr.response); if (response && typeof(response) === 'object' && response.result && typeof(response.result) === 'object' && response.result.file_name && typeof(response.result.file_name) === 'string' && response.result.file_name !== '') { saved_filename = response.result.file_name; } } progressCallback(100); successCallback({ url: attachment_base_url + saved_filename }); } }); xhr.send(createFormData(file)); }
The corresponding Form Data:
------WebKitFormBoundarya04hDppsnTo2uPOR Content-Disposition: form-data; name="Content-Type" image/png ------WebKitFormBoundarya04hDppsnTo2uPOR Content-Disposition: form-data; name="attachment-upload"; filename="Bildschirmfoto 2021-01-22 um 14.11.15.png" Content-Type: image/png ------WebKitFormBoundarya04hDppsnTo2uPOR--
Example response after successful attachment upload:
{ "errors": [], "result": { "file_name": "Bildschirmfoto_2021-01-22_um_14.11.15.png" } }
/api/v2/apps/<app_id>/protos
[GET] Returns a list of all protos of the specified application.
The following URL parameter can be used for paging:
- limit: Defines how many proto keys are returned. Takes a number between 1 and 1000, default is 10.
The returned result contains a key “next_card_key” whose value is the next key not returned in this answer.
Example request:
https://example.protogrid.com/api/v2/apps/appc55b3773-5503-4c41-a9aa-3a561c40fa04/protos?limit=1
Example result:
{ "errors": [], "protogrid_environment_version": "1.3.9", "result": { "next_card_key": "NextProtoKey" "protos": [ {"key": "ExampleProtoKey"} ] } }
/api/v2/apps/<app_id>/protos/<proto_key>
[GET] Returns detailed information about the specified Proto.
Example request:
https://example.protogrid.com/api/v2/apps/appc55b3773-5503-4c41-a9aa-3a561c40fa04/protos/example_proto_key
Example result:
{ "errors": [], "protogrid_environment_version": "1.3.9", "result": { "key": "example_proto_key", "shortname": "Example Proto", "field_and_widget_keys": [ { "allow_new_cards": true, "cardinality_setting": 2, "couchdb_viewname": "", "disable_label": false, "display_priority": 7, "element_type": "Relation", "grid_size_setting": 0, "help_text": "", "hidden": false, "label_multilanguage_key": "&&mlkey_design_elements", "multiple_values_setting": 1, "name": "card_design_elements", "parent_application_setting": "", "parent_entity_proto_setting": "DesignElementDefinition", "requirement_setting": 0, "show_card_type": true, "show_created_setting": false, "show_creator_setting": false, "show_modified_setting": false, "show_modifier_setting": false, "show_short_name_setting": false, "show_to_users": 0, "user_enabled_setting": 0, "value": [ "design_element_key_1 ", "design_element_key_2", … ], "value_type": "key" }, {…}, … ] } }
/api/v2/apps/<app_id>/protos/<proto_key>/card-keys
[GET] Returns the keys for all Cards based on the specified proto.
The following URL parameter can be used for paging:
- limit: Defines how many card keys are returned. Takes a number between 1 and 1000, default is 10.
The returned result contains a key “next_card_key” whose value is the next key not returned in this answer.
Example request:
https://example.protogrid.com/api/v2/apps/appc55b3773-5503-4c41-a9aa-3a561c40fa04/protos/example_proto/card-keys?limit=1
Example result:
{ "errors": [], "protogrid_environment_version": "1.3.9", "result": [ "card_keys":[ "ExampleProtoKey", "ExampleSortstring", "ExampleCardKey" ], "next_card_key": "NextCardKey" ] }
/api/v2/apps/<app_id>/mailsend
[POST] Send an email
To be able to use this endpoint, the SMTP mail server of your organization must first be configured as the designated mail relay server in your Environment. If this has not been done yet, please contact Protogrid Support.
Protogrid will fist try to establish a TLS session to the specified mail relay server and authenticate using the supplied credentials. If TLS is not available it will try to connect using SSL. Finally if SSL is not available the function tries to connect using unsecured SMTP protocol.
The mail will be sent according to the currently logged in user (mail address specified in user profile and the field “SMTP Server Password” if requested by the mailserver).
The following JSON data fields can be used:
- to: TO addresses (Array of Strings, mandatory)
- cc: CC addresses (Array of Strings)
- bcc: BCC addresses (Array of Strings)
- reply_to: ReplyTo addresses (Array of Strings)
- from: From address if other than logged in user (String)
- subject: Subject (String, mandatory)
- body_text_plain: Body text in plain text format (String)
- body_text_html: Body text in HTML format (String)
- inline_images: Images for embedded display in HTML body using “cid” references (Array of Objects)
- attachments: Documents to attach to the email (Array of Objects)
Attachments and inline images must already reside inside Protogrid, each attached to a Card and the logged in user must have read access to this Card(s). Attachments and inline images are specified in the POST request body using objects with the following structure:
{ "card_id": "<ID of the Card on which the attachment or image resides>", "attachment_key": "<ID of the attachment as it is listed in the Card specified above>" }
For maximum compatibility with all receiving systems, we recommend to not use any special characters in attachment and inline-image filenames. Inline images can be referenced from the body_text_html using the cid URL scheme and attachment_key as content-id (see https://datatracker.ietf.org/doc/html/rfc2392).
By default, users can send a mail to up to 10 recipients. This limit can be increased via the roles assigned to the users using the field “Allowed Number of Recipients per Mail Sent” on each Role Definition. However, a mail never can be sent to more than 500 recipients.
Example client-side jQuery request:
$.post({ url: "https://example.protogrid.com/api/v2/apps/appc55b3773-5503-4c41-a9aa-3a561c40fa04/mailsend", data: JSON.stringify({ "to": ["Tester 1️⃣ <test1@ategra.ch>", "Tester 2️⃣ <test2@ategra.ch>"], "cc": ["Tester 3️⃣ <test3@ategra.ch>", "Tester 4️⃣ <test4@ategra.ch>"], "bcc": ["Tester 5️⃣ <test5@ategra.ch>", "Tester 6️⃣ <test6@ategra.ch>"], "reply_to": ["Tester 7️⃣ <test7@ategra.ch>", "Tester 8️⃣ <test8@ategra.ch>"], "from": "Tester 0️⃣ <test0@ategra.ch>", "subject": "Test Email with Emojis 👍", "body_text_plain": "This is a test message in plain text 😎.", "body_text_html": "This is a <b>test</b> message 🤖.<br><br>Please check if the message is displayed correctly using several different mail clients or tools like Mailtrap (<a href='https://mailtrap.io'>link</a>).<br><br><img src='cid:c3e59e8b-1a4f-4503-fec1-17292d9413ac'></img>", "inline_images": [ {"card_id": "ffc3a027-2fed-45f8-8aa8-adec18a90439", "attachment_key": "c3e59e8b-1a4f-4503-fec1-17292d9413ac"} ], "attachments": [ {"card_id": "ffc3a027-2fed-45f8-8aa8-adec18a90439", "attachment_key": "e3f68fff-93f9-4a31-9835-5394a4f09f3c"} ] }), contentType: 'application/json; charset=utf-8' }).done(function (response) { alert("Data: " + JSON.stringify(response)); });
In the response you receive a success message and/or details about the particular error as a JSON with the following structure:
- errors [Array]: Contains information if no single email could be sent, otherwise it is empty.
- messages [Array]: Contains information if Protogrid could not establish the connection to the mail server with the most secure transport encryption, otherwise it is empty.
- result [Object]: Contains information regarding individual recipients to whom the email could not be delivered. If the email could be delivered to all recipients equals to { “success”: true }.
Example response:
{ "errors": [], "messages": [ "Couldn't send the mail using a secure TlS communication channel. Trying SSL instead.", "Couldn't send the mail an SSL communication channel. Trying without encryption." ], "result": { "external@recipient.ch": [ 554, "5.7.1 <external@recipient.ch>: Relay access denied" ] } }
/api/v2/apps/<app_name>/cards/<card_key>/fields/<element_id>/generate_document
[POST] Generates a document based on a template file (must be of type .docx). The template might contain placeholders which are filled with the field values of the Card identified by 'card_key'. The resulting document is stored in the attachment field with ID 'element_id' on the card with ID 'card_key'.
Please note that URL parameters must be URI encoded. URL Parameter:
- template_card_id (String, required): The ID of the Card where the template file is stored (String).
- template_attachment_key (String, optional): The Attachment Key of the template file. If omitted, the first attachment on the specified Template Card will be used.
- new_filename (String, optional): The filename of the newly created file. If omitted, the file name is automatically compiled based on the file name of the template.
- language (String, optional): The BCP 47 language tag of the desired language, e. g. 'de_CH'. This is used for multilanguage fields as well for formatting number and date time fields. If omitted, the current user's language is used.
Optionally, in the POST request body additional placeholder values may be provided in JSON format.
Example client-side jQuery request:
$.post({ url: "/api/v2/apps/example_app/cards/c3e59e8b-1a4f-4503-fec1-17292d9413ac/fields/9b3b8ea4-be36-4b12-b5b0-ee90ff3249b9/generate_document?template_card_id=e46b8972-e9e9-477c-cee2-c16cde1ed2d7", contentType: 'application/json; charset=utf-8', data: JSON.stringify({ 'placeholder_values_override': { 'movie_reviews': [ {'Reviewer Name': 'Roger Ebert', 'Criticism': 'This movie is boring because of the following...'}, {'Reviewer Name': 'Gene Siskel', 'Criticism': 'I like the way...'} ] } }), }).done(function (response) { console.log("Data: " + JSON.stringify(response)); });
As a response you receive a JSON with the following structure:
- errors [Array]: Contains details about the particular error (e. g. information about wrong placeholders in the template) in case of failure.
- result [Object]: Contains the metadata of the newly generated file in the attachment field with ID 'element_id' in case of success.
Usage of Placeholders in Templates:
- Placeholders start with
{{, end with}}and contain the label or alias of the field whose value is to be inserted into the document. Example:{{Title of Movie}} - For numerical values, you can set in the field definition whether they should be displayed with a thousands separator and to how many decimal places they should be rounded.
- For date values, you can specify display options (
Sfor a shorter format and/orWfor additionally indicating the day of the week) by stating them after the field name and a%%. Example:{{Date of Premiere%%SW}} - If a value is to be inserted into the generated document that is located in a Related Card, you must first specify the Relation Field followed by
||and then the target field of the Related Card. Example:{{Genre Category||Suitable For Children}} - If you only want to insert a space or a comma after a placeholder value if this value exists at all, this can be defined using
&&after the field name. Example:{{Subtitle&&, }}{{Year of Publication}} - If you only want to insert a line break after a placeholder value if this value exists at all, this can be achieved by additionally using
§§. Example:{{Subtitle&&§§}}{{Year of Publication}} - If an entire sentence or paragraph is only to be placed in the document, when a certain condition is met, this can be achieved by enclosing the sentence/paragraph in two placeholders - the first starting with
??the second with!!. The condition is formulated using either==( match) or!=( mismatch). Example:{{??Genre Category==Thriller}}Thrillers are characterized by giving their audiences heightened feelings of suspense, anxiety...{{!!Genre Category==Thriller}} - The conditional insertion of a table row can also be implemented in the same way. The first placeholder must be inserted at the leftmost cell at the very beginning and the second placeholder at the rightmost cell at the very end.
- Loops can be defined to display the values of tag fields in the same way as conditions. The sentence/paragraph that is to be repeated per tag field entry must be enclosed in two placeholders with the name of the tag field - the first beginning with
??, the second with!!. Within the repeated text, the field values of the Related Card referenced by the tag field entry can be accessed using direct placeholders. Example:{{??Actors in This Movie}}Name: {{Name of Actor}}, Age: {{Age of Actor}}, Origin: {{Country of Birth}}{{!!Actors in This Movie}} - Analogously, loops can also be defined to display the contents of embedded TableViews. For optional filtering, any number of pairs of filter columns and filter values can be specified in the placeholder indicated by
%%. The table entries are always filtered by the current Card and sorted according to the sorting settings in the TableView definition. Example:{{??Recent Reviews of This Moview%%Year of Review%%2025}}Autor: {{Reviewer}}, Rating: {{Number of Stars}}/5{{!!Recent Reviews of This Moview%%Year of Review%%2025}} - It is possible to use a generated document again in a second step as a template for generating another document. Placeholders that are not to be filled in during the first generation process, but in the second step, must be marked with equals signs:
{{=Date of Approval=}}
/api/v2/apps/<app_name>/cards/<card_key>/fields/<element_id>/generate_pdf
[POST] Generates an overall PDF document based on one or multiple input document(s) of either .docx or .pdf type. The resulting PDF is stored in the attachment field with ID 'element_id' on the card with ID 'card_key'.
Please note that URL parameters must be URI encoded. URL Parameter:
- new_filename (String, optional): The filename of the newly created document. If omitted, the file name is determined automatically based on the file name of the first input document.
The input documents must already reside inside Protogrid, each attached to a Card and the logged in user must have read access to this Card(s). The input documents are specified in the POST request body using objects with the following structure:
{ "card_id": "<ID of the Card on which the input document resides>", "attachment_key": "<ID of the input document as it is listed in the Card specified above>" }
Example client-side jQuery request:
$.post({ url: "/api/v2/apps/example_app/cards/c3e59e8b-1a4f-4503-fec1-17292d9413ac/fields/9b3b8ea4-be36-4b12-b5b0-ee90ff3249b9/generate_pdf", contentType: 'application/json; charset=utf-8', data: JSON.stringify({ 'input_attachments': [ {'card_id': 'c3e59e8b-1a4f-4503-fec1-17292d9413a', 'attachment_key': 'b6016027-c8a4-41f0-8a98-1f0fb9adea6a'}, {'card_id': '41706217-45a1-4980-9c55-3f98e62c1411', 'attachment_key': '475fe553-46ff-4168-dc3b-57509b015887'} ] }), }).done(function (response) { console.log("Data: " + JSON.stringify(response)); });
In the response you receive a success message and/or details about the particular error as a JSON with the following structure:
- errors [Array]: Contains details about the particular error (e. g. information about an input document with unsupported file type) in case of failure.
- result [Object]: Contains the metadata of the newly generated file in the attachment field with ID 'element_id' in case of success.
Example response:
{ "errors": [ "The passed attachment with key 'b6016027-c8a4-41f0-8a98-1f0fb9adea6a' is not of type .docx or .pdf and therefore is not processed." ], "protogrid_environment_version": "2.19.1", "result": { "attachment_entry": { "attachment_key": "9a027e3a-1ce6-4135-aa77-83b3074b2acc", "created": "2025-05-21T12:11:29.225Z", "creator": "org.couchdb.user:d9040e95-6de0-45b4-d228-baee6b8e8c86", "filename": "Protogrid Quickstart Tutorial.pdf", "latest_mutation": "d313b386-2169-416f-acd0-be5d64b000f5-Mutation", "length": 694227, "mime_type": "application/pdf", "modified": "2025-05-21T12:11:29.225Z", "modifier": "org.couchdb.user:d9040e95-6de0-45b4-d228-baee6b8e8c86" }, "attachment_list": [ { "attachment_key": "b6016027-c8a4-41f0-8a98-1f0fb9adea6a", "created": "2025-05-20T11:51:49.119Z", "creator": "org.couchdb.user:d9040e95-6de0-45b4-d228-baee6b8e8c86", "filename": "Protogrid Logo.png", "latest_mutation": "fcb10a55-5207-4fda-eb48-c1015d5fa5a0-Mutation", "length": 23614, "mime_type": "image/png", "modified": "2025-05-20T11:51:49.119Z", "modifier": "org.couchdb.user:d9040e95-6de0-45b4-d228-baee6b8e8c86" }, { "attachment_key": "9a027e3a-1ce6-4135-aa77-83b3074b2acc", "created": "2025-05-21T12:11:29.225Z", "creator": "org.couchdb.user:d9040e95-6de0-45b4-d228-baee6b8e8c86", "filename": "Protogrid Quickstart Tutorial.pdf", "latest_mutation": "d313b386-2169-416f-acd0-be5d64b000f5-Mutation", "length": 694227, "mime_type": "application/pdf", "modified": "2025-05-21T12:11:29.225Z", "modifier": "org.couchdb.user:d9040e95-6de0-45b4-d228-baee6b8e8c86" } ] } }