DataScope
BUSINESS · TASKS
Form answers, their exports, and inspection questions in the account they connected.
Acts as the person, not as itself
Each user connects their own account. Every call carries both identities — the agent and the person it is acting for — so the agent can never reach past what that individual can already do.
Credentials never touch the agent
Tokens live in the vault and attach server-side at call time. The agent holds a session, not a secret, and revoking access does not mean rotating a key.
Every call on the record
Who asked, which agent acted, which action ran, and the verdict that let it through — one audit trail across every integration, not one per vendor.
What an agent can do
Each action is granted on its own. An agent allowed to read is not thereby allowed to write, and the scope beside each row is what the acting user must have connected for it to run at all.
datascope_get_filesREADList recently generated files via GET /api/external/files. List the PDF and Excel files DataScope generated in a date range, each with the form it came from, the user and a `url` on www.mydatascope.com. Nearly the same shape as List recent notifications, which reports the files a user was NOTIFIED about; this reports the files that were generated. The window defaults to the last 7 days, and this returns the LINKS, not the files. CREDENTIAL-BLIND, MEASURED 2026-09-23: this route answers `200 []` to a WRONG key and -- negative-controlled -- to no credential at all, where `/task_assigns` on the same host answers 401 to the same request. An empty result here therefore does NOT mean the account is empty. Before reporting that nothing was found, call List task assignments or List tickets for a period, which do reject a bad key with 401, to confirm the connection is actually authenticated. The DataScope API is available on the Professional plan and above; on a free or Starter account every call is refused however correct the key is. DataScope counts its rate limit per SOURCE IP rather than per key -- its own reference says "the limit is counted per source IP, not per token" -- and answers 429 with an HTML page titled "500 Error" and no Retry-After header. A 429 is a THROTTLE, never a bad key: wait and retry rather than re-pasting the key, and expect other DataScope connections from this deployment to share the same budget.
datascope_get_findings_get_by_idREADGet one ticket via GET /api/external/findings/get/{id}. Read one ticket by its Firestore document id. The SHAPE DIFFERS FROM THE LIST: dates come back as ISO 8601 here and formatted to account preferences there, `type` is the type ID here and the resolved type NAME there, and assignees and invitees are comma-separated names here rather than structured objects. So do not parse both replies with one reader. 404 means not found, 403 means the credential may not read it. The DataScope API is available on the Professional plan and above; on a free or Starter account every call is refused however correct the key is. DataScope counts its rate limit per SOURCE IP rather than per key -- its own reference says "the limit is counted per source IP, not per token" -- and answers 429 with an HTML page titled "500 Error" and no Retry-After header. A 429 is a THROTTLE, never a bad key: wait and retry rather than re-pasting the key, and expect other DataScope connections from this deployment to share the same budget.
datascope_get_findings_listREADList tickets for a period via GET /api/external/findings/list. List the account's tickets (DataScope's issue tracker, formerly called Issues and still spelled `findings` in the URL) created within a date range, each with its status, priority, location, creator, assignees, invitees and the form answer it came from. DATES ARE `dd-mm-yyyy` HERE, which is not the format the answers or task tools take; the range defaults to the last 7 days and MAY NOT EXCEED 90 -- a wider one answers 422. Paged with `limit` (default and max 200) and `offset` (max 2000). The `id` is a Firestore document id and is what Get one ticket takes. Assignees and invitees arrive twice, as a structured object and as a `&&`-separated string; prefer the object. The DataScope API is available on the Professional plan and above; on a free or Starter account every call is refused however correct the key is. DataScope counts its rate limit per SOURCE IP rather than per key -- its own reference says "the limit is counted per source IP, not per token" -- and answers 429 with an HTML page titled "500 Error" and no Retry-After header. A 429 is a THROTTLE, never a bad key: wait and retry rather than re-pasting the key, and expect other DataScope connections from this deployment to share the same budget.
datascope_get_findings_typesREADList ticket types via GET /api/external/findings/types. List the ticket types configured in the account, each as `{"id": "<Firestore id>", "name": "<name>"}`, optionally narrowed by a `search` on the name. Create a ticket accepts either the id or the name in its `type` field, and a type carries preset data that is applied to tickets created with it. CREDENTIAL-BLIND, MEASURED 2026-09-23: this route answers `200 []` to a WRONG key and -- negative-controlled -- to no credential at all, where `/task_assigns` on the same host answers 401 to the same request. An empty result here therefore does NOT mean the account is empty. Before reporting that nothing was found, call List task assignments or List tickets for a period, which do reject a bad key with 401, to confirm the connection is actually authenticated. The DataScope API is available on the Professional plan and above; on a free or Starter account every call is refused however correct the key is. DataScope counts its rate limit per SOURCE IP rather than per key -- its own reference says "the limit is counted per source IP, not per token" -- and answers 429 with an HTML page titled "500 Error" and no Retry-After header. A 429 is a THROTTLE, never a bad key: wait and retry rather than re-pasting the key, and expect other DataScope connections from this deployment to share the same budget.
datascope_get_last_findingsREADGet the five most recent tickets via GET /api/external/last_findings. Return the five most recently created tickets, with no parameters and no filtering -- the cheap "what just happened" read. Use List tickets for a period for anything selective. MEASURED 2026-09-23: with a wrong key this route answers `500 {"status":500,"error":"Internal Server Error"}` rather than a 401, so a 500 here does NOT distinguish a DataScope outage from a credential problem -- confirm the connection with List task assignments before treating a 500 as an outage. The DataScope API is available on the Professional plan and above; on a free or Starter account every call is refused however correct the key is. DataScope counts its rate limit per SOURCE IP rather than per key -- its own reference says "the limit is counted per source IP, not per token" -- and answers 429 with an HTML page titled "500 Error" and no Retry-After header. A 429 is a THROTTLE, never a bad key: wait and retry rather than re-pasting the key, and expect other DataScope connections from this deployment to share the same budget.
datascope_get_list_statesREADList the account's answer statuses via GET /api/external/list_states. List the answer statuses configured in this account -- the values that appear as `form_state` on an answer. Each row is `{"type": "unicode", "key": <id>, "identifier": "<name>"}`, and `key` is exactly what Change an answer's status expects as `form_state_id`. Takes no parameters. TWO THINGS THE REPLY DOES NOT TELL YOU. A status deleted in the web app is still listed here, because the response is not filtered by the deleted flag (the answers export reports `-` as the form_state of an answer whose status was deleted). And MEASURED 2026-09-23 this route VALIDATES BEFORE IT AUTHENTICATES: it answers 400 {"error":true} to a bogus key, so a 400 here is not evidence about the credential. The DataScope API is available on the Professional plan and above; on a free or Starter account every call is refused however correct the key is. DataScope counts its rate limit per SOURCE IP rather than per key -- its own reference says "the limit is counted per source IP, not per token" -- and answers 429 with an HTML page titled "500 Error" and no Retry-After header. A 429 is a THROTTLE, never a bad key: wait and retry rather than re-pasting the key, and expect other DataScope connections from this deployment to share the same budget.
datascope_get_locationsREADList all locations via GET /api/external/locations. List every location in the account: `id`, `name`, `description`, `code`, `address`, `city`, `region`, `country`, latitude and longitude, `phone`, `company_code` and `company_name`. The `id` is what Update a location and the `location_id` filters on the answers and task tools expect. Takes no parameters -- there is no filter and no paging on this endpoint. CREDENTIAL-BLIND, MEASURED 2026-09-23: this route answers `200 []` to a WRONG key and -- negative-controlled -- to no credential at all, where `/task_assigns` on the same host answers 401 to the same request. An empty result here therefore does NOT mean the account is empty. Before reporting that nothing was found, call List task assignments or List tickets for a period, which do reject a bad key with 401, to confirm the connection is actually authenticated. The DataScope API is available on the Professional plan and above; on a free or Starter account every call is refused however correct the key is. DataScope counts its rate limit per SOURCE IP rather than per key -- its own reference says "the limit is counted per source IP, not per token" -- and answers 429 with an HTML page titled "500 Error" and no Retry-After header. A 429 is a THROTTLE, never a bad key: wait and retry rather than re-pasting the key, and expect other DataScope connections from this deployment to share the same budget.
datascope_get_metadata_objectREADGet one element of a list via GET /api/external/metadata_object. Read one element of a custom list by its id, returning the same fields as List the elements of a list for a single row. Both the list's internal code and the element's id are query parameters here -- this endpoint does not take the id in the path, unlike the update below. CREDENTIAL-BLIND, MEASURED 2026-09-23: this route answers `200 []` to a WRONG key and -- negative-controlled -- to no credential at all, where `/task_assigns` on the same host answers 401 to the same request. An empty result here therefore does NOT mean the account is empty. Before reporting that nothing was found, call List task assignments or List tickets for a period, which do reject a bad key with 401, to confirm the connection is actually authenticated. The DataScope API is available on the Professional plan and above; on a free or Starter account every call is refused however correct the key is. DataScope counts its rate limit per SOURCE IP rather than per key -- its own reference says "the limit is counted per source IP, not per token" -- and answers 429 with an HTML page titled "500 Error" and no Retry-After header. A 429 is a THROTTLE, never a bad key: wait and retry rather than re-pasting the key, and expect other DataScope connections from this deployment to share the same budget.
datascope_get_metadata_objectsREADList the elements of a list via GET /api/external/metadata_objects. List the elements of one of the account's custom lists -- the products, equipment, categories and so on that a form's dropdown questions choose from. Each element carries `id`, `name`, `description`, `code`, `attribute1`, `attribute2`, `list_id` and its timestamps. `metadata_type` is the list's internal code; the answers export reports it alongside `metadata_id` on every answer to a list-backed question, which is how you find the code for a list you have seen used. CREDENTIAL-BLIND, MEASURED 2026-09-23: this route answers `200 []` to a WRONG key and -- negative-controlled -- to no credential at all, where `/task_assigns` on the same host answers 401 to the same request. An empty result here therefore does NOT mean the account is empty. Before reporting that nothing was found, call List task assignments or List tickets for a period, which do reject a bad key with 401, to confirm the connection is actually authenticated. The DataScope API is available on the Professional plan and above; on a free or Starter account every call is refused however correct the key is. DataScope counts its rate limit per SOURCE IP rather than per key -- its own reference says "the limit is counted per source IP, not per token" -- and answers 429 with an HTML page titled "500 Error" and no Retry-After header. A 429 is a THROTTLE, never a bad key: wait and retry rather than re-pasting the key, and expect other DataScope connections from this deployment to share the same budget.
datascope_get_notificationsREADList recent notifications via GET /api/external/notifications. List the PDF and Excel documents DataScope has notified users about in a date range, each with the form it came from, the user it went to and a `url` on www.mydatascope.com pointing at the file. The window defaults to the last 7 days. This returns the LINKS, not the files -- nothing here downloads anything. CREDENTIAL-BLIND, MEASURED 2026-09-23: this route answers `200 []` to a WRONG key and -- negative-controlled -- to no credential at all, where `/task_assigns` on the same host answers 401 to the same request. An empty result here therefore does NOT mean the account is empty. Before reporting that nothing was found, call List task assignments or List tickets for a period, which do reject a bad key with 401, to confirm the connection is actually authenticated. The DataScope API is available on the Professional plan and above; on a free or Starter account every call is refused however correct the key is. DataScope counts its rate limit per SOURCE IP rather than per key -- its own reference says "the limit is counted per source IP, not per token" -- and answers 429 with an HTML page titled "500 Error" and no Retry-After header. A 429 is a THROTTLE, never a bad key: wait and retry rather than re-pasting the key, and expect other DataScope connections from this deployment to share the same budget.
datascope_get_signatures_listREADList signature requests via GET /api/external/signatures/list. List the account's signature requests with their signers nested, ordered by `updated_at` ascending and paged with a keyset cursor. This is what answers "which of the five signers is still missing": each request carries `status` (pending / completed / rejected / deleted), `required_signatures_count` already resolved for any quorum, `signer_ids` and a `signers[]` array whose rows say who signed and when. PAGING: read `next_cursor` from the reply and send it back as `since`; a page with fewer rows than `limit` is the last. The cursor is `<ISO8601>|<form_signature_request_id>` rather than a timestamp alone because `updated_at` has one-second resolution and a bulk signature writes a batch inside one second -- a timestamp-only cursor would skip the rest of such a batch permanently. USE `signer_ids` TO RETIRE SIGNERS: a signer removed while editing a request is deleted outright rather than flagged, so diffing your stored rows against that list is the only way to notice one is gone. `custom_fields` accepts only `signer_identity` and `documents`, and an unrecognised value answers 400 listing the accepted ones. `signer_identity` RETURNS PERSONAL DATA -- names, national id numbers, personal emails, company and role -- so ask for it only when it is needed. `start`/`end` accept ISO 8601 only; a format like 08/01/2026 is rejected with a 400 rather than guessed. The key's user must hold EXPORT permission in DataScope (the reference says so: "The user whose token you use needs export permission in DataScope"); without it this is refused even on a Professional plan. The DataScope API is available on the Professional plan and above; on a free or Starter account every call is refused however correct the key is. DataScope counts its rate limit per SOURCE IP rather than per key -- its own reference says "the limit is counted per source IP, not per token" -- and answers 429 with an HTML page titled "500 Error" and no Retry-After header. A 429 is a THROTTLE, never a bad key: wait and retry rather than re-pasting the key, and expect other DataScope connections from this deployment to share the same budget.
datascope_get_task_assignsREADList task assignments via GET /api/external/task_assigns. List the account's task assignments with the same fields as the platform's Excel export plus the internal `id`: the assigned user, form and location, whether each was completed and on time, the delay, and the code of the answer that closed it. Paged with `limit` (default 100, max 300) and `offset`, and the reply's `total` is the count matching the filters -- with no filters that is every historical task in the account, so send `start` and `end` unless you mean all of it. THIS IS ALSO THE TOOL TO USE TO CONFIRM A CONNECTION WORKS: measured 2026-09-23 it answers 401 to a wrong key and to no credential at all, where six of this provider's other read routes answer `200 []` to both. The DataScope API is available on the Professional plan and above; on a free or Starter account every call is refused however correct the key is. DataScope counts its rate limit per SOURCE IP rather than per key -- its own reference says "the limit is counted per source IP, not per token" -- and answers 429 with an HTML page titled "500 Error" and no Retry-After header. A 429 is a THROTTLE, never a bad key: wait and retry rather than re-pasting the key, and expect other DataScope connections from this deployment to share the same budget.
datascope_get_task_assigns_by_idREADGet one task assignment via GET /api/external/task_assigns/{id}. Read the full detail of one task assignment: who it is assigned to, the form and location, whether it was completed and on time, the delay, the response window and the id of the answer that closed it (`response_code`). Returns the same fields as List task assignments. A 404 means the assignment does not belong to this account -- which is also what a wrong id looks like. Use `id`, the internal database id, not `assign_id`, which is your own code and may repeat across periods. The DataScope API is available on the Professional plan and above; on a free or Starter account every call is refused however correct the key is. DataScope counts its rate limit per SOURCE IP rather than per key -- its own reference says "the limit is counted per source IP, not per token" -- and answers 429 with an HTML page titled "500 Error" and no Retry-After header. A 429 is a THROTTLE, never a bad key: wait and retry rather than re-pasting the key, and expect other DataScope connections from this deployment to share the same budget.
datascope_get_v5_answersREADExport form answers via GET /api/external/v5/answers. Export the answers submitted to your DataScope forms: one record per form answer with `form_answer_id`, `form_id`, `form_name`, `form_code`, `form_state`, `user_name`, `user_identifier`, `created_at`, `updated_at`, latitude/longitude and the questions themselves. THIS IS THE ONLY ANSWERS TOOL, and it covers every version DataScope has published: the reference says V5 "can reproduce the response shape of every previous version (v1, v2, v3, v4)", so pass `version` to pick the baseline shape and `custom_fields` to add data on top, instead of looking for a v2 or v4 tool. By default each question becomes its own top-level key, which means the response shape changes per form; send `custom_fields=answers_data_in_array` to get a stable shape with the questions nested in an `answers` array. PAGING: `limit` defaults to and maxes at 200, and for anything incremental send `date_modified=true` and `order_date=true` TOGETHER and page with `since=<updated_at>|<form_answer_id>` taken from the last record of the previous page -- filtering by modification date while sorting by something else drops records at page boundaries, and a malformed cursor answers 400 {"error": "invalid_since_cursor"}. The date window defaults to the last 7 days (`days_limit`) and cannot exceed 90 days. The key's user must hold EXPORT permission in DataScope (the reference says so: "The user whose token you use needs export permission in DataScope"); without it this is refused even on a Professional plan. The DataScope API is available on the Professional plan and above; on a free or Starter account every call is refused however correct the key is. DataScope counts its rate limit per SOURCE IP rather than per key -- its own reference says "the limit is counted per source IP, not per token" -- and answers 429 with an HTML page titled "500 Error" and no Retry-After header. A 429 is a THROTTLE, never a bad key: wait and retry rather than re-pasting the key, and expect other DataScope connections from this deployment to share the same budget.
datascope_post_assign_taskWRITEAssign a form to a user via POST /api/external/assign_task. Schedule a form for a user to fill in at a location and time -- the task that then appears in their DataScope app. `user_id` is the user's EMAIL despite the name, `form_id` is the number in the form editor URL, and `gap` is how many hours they have to complete it. THE LOCATION FIELDS CREATE OR UPDATE A LOCATION: `l_code` names it and the `location_*`, `l_phone`, `l_email`, `c_name` and `c_code` fields are applied to it, so a typo in `l_code` makes a new location rather than failing. READ THE REPLY, NOT THE STATUS: MEASURED 2026-09-23, this route answers HTTP 200 with `{"error":"invalid token"}` when the credential is wrong, so a 200 here does not mean the task was created -- check for an `error` key in the body before reporting success. The DataScope API is available on the Professional plan and above; on a free or Starter account every call is refused however correct the key is. DataScope counts its rate limit per SOURCE IP rather than per key -- its own reference says "the limit is counted per source IP, not per token" -- and answers 429 with an HTML page titled "500 Error" and no Retry-After header. A 429 is a THROTTLE, never a bad key: wait and retry rather than re-pasting the key, and expect other DataScope connections from this deployment to share the same budget.
datascope_post_change_form_answerWRITEChange one answer to one question via POST /api/external/change_form_answer. Overwrite the value of ONE question inside one already-submitted form answer, naming the answer by its form's name and the answer's code. The reply is `{"status": "ok", "form_answer": {"id": ..., "form_id": ...}}`. There is no undo and no read-back of the previous value, so read the answer with Export form answers first if you need it. `subform_index` starts at 1 and is left unset for a question that is not inside a subform. MEASURED 2026-09-23: this route VALIDATES BEFORE IT AUTHENTICATES -- a call with no parameters answers a bodyless 400 whatever the key is -- so a 400 here is about the arguments and says nothing about the credential. The DataScope API is available on the Professional plan and above; on a free or Starter account every call is refused however correct the key is. DataScope counts its rate limit per SOURCE IP rather than per key -- its own reference says "the limit is counted per source IP, not per token" -- and answers 429 with an HTML page titled "500 Error" and no Retry-After header. A 429 is a THROTTLE, never a bad key: wait and retry rather than re-pasting the key, and expect other DataScope connections from this deployment to share the same budget.
datascope_post_change_stateWRITEChange an answer's status via POST /api/external/change_state. Move one submitted answer to a different status, exactly as changing it in the web app would: the change is recorded in the answer's history, the webhooks configured for status changes fire, and the user who submitted the answer receives a push notification when the account has status-change notifications enabled. So this is not a silent field update -- it notifies people. Get `form_state_id` from List the account's answer statuses. A 400 comes back with an EMPTY body whenever the form name, the answer code or the status id does not match something in the account, so check all three; MEASURED 2026-09-23 this route validates before it authenticates, so that 400 is not evidence about the key either. The DataScope API is available on the Professional plan and above; on a free or Starter account every call is refused however correct the key is. DataScope counts its rate limit per SOURCE IP rather than per key -- its own reference says "the limit is counted per source IP, not per token" -- and answers 429 with an HTML page titled "500 Error" and no Retry-After header. A 429 is a THROTTLE, never a bad key: wait and retry rather than re-pasting the key, and expect other DataScope connections from this deployment to share the same budget.
datascope_post_findings_createWRITECreate a ticket via POST /api/external/findings/create. Create a ticket and assign it to people. `name`, `description`, `expiration_date` and `assignees` are all required; assignees and invitees are MobileUser ids or emails, up to 100 each, and `author_email` falls back to the owner of the API key -- so a ticket created through a shared key is attributed to that key's owner unless you say otherwise. Passing `type` applies that ticket type's preset data. 201 on success, 422 on wrong parameters, 403 when the credential may not write. MEASURED 2026-09-23: with a wrong key this route answers `500 {"status":500,"error":"Internal Server Error"}` rather than a 401, so a 500 here does not distinguish an outage from a credential problem. The DataScope API is available on the Professional plan and above; on a free or Starter account every call is refused however correct the key is. DataScope counts its rate limit per SOURCE IP rather than per key -- its own reference says "the limit is counted per source IP, not per token" -- and answers 429 with an HTML page titled "500 Error" and no Retry-After header. A 429 is a THROTTLE, never a bad key: wait and retry rather than re-pasting the key, and expect other DataScope connections from this deployment to share the same budget.
datascope_post_locationsWRITECreate a location via POST /api/external/locations. Create a location -- the places a form can be answered at and a task assigned to. The reply is the created location including its new `id`. DataScope answers 201 on success, 422 on wrong parameters and 403 when the credential may not write. Locations are their own resource: the list tools below (`metadata_type`) explicitly refuse `locations`, so this is the only way to create one. The DataScope API is available on the Professional plan and above; on a free or Starter account every call is refused however correct the key is. DataScope counts its rate limit per SOURCE IP rather than per key -- its own reference says "the limit is counted per source IP, not per token" -- and answers 429 with an HTML page titled "500 Error" and no Retry-After header. A 429 is a THROTTLE, never a bad key: wait and retry rather than re-pasting the key, and expect other DataScope connections from this deployment to share the same budget.
datascope_post_locations_by_idWRITEUpdate a location via POST /api/external/locations/{id}. Update a location by its internal id. The whole `location` object is sent, so read the current values with List all locations first and send them back with your change: DataScope's reference documents no partial-update semantics, and the reply is the location as it now stands. 422 on wrong parameters, 403 when the credential may not write. The DataScope API is available on the Professional plan and above; on a free or Starter account every call is refused however correct the key is. DataScope counts its rate limit per SOURCE IP rather than per key -- its own reference says "the limit is counted per source IP, not per token" -- and answers 429 with an HTML page titled "500 Error" and no Retry-After header. A 429 is a THROTTLE, never a bad key: wait and retry rather than re-pasting the key, and expect other DataScope connections from this deployment to share the same budget.
datascope_post_metadata_objectWRITECreate a list element via POST /api/external/metadata_object. Add one element to a custom list. The list is named in the `metadata_type` QUERY parameter and the element itself in the body's `list_object`. The reply is the created element with its new `id` and the `metadata_type` it landed in. NOT FOR LOCATIONS: the reference says to use the locations endpoints for those, and Create a location is the tool for it. 201 on success, 422 on wrong parameters, 403 when the credential may not write. The DataScope API is available on the Professional plan and above; on a free or Starter account every call is refused however correct the key is. DataScope counts its rate limit per SOURCE IP rather than per key -- its own reference says "the limit is counted per source IP, not per token" -- and answers 429 with an HTML page titled "500 Error" and no Retry-After header. A 429 is a THROTTLE, never a bad key: wait and retry rather than re-pasting the key, and expect other DataScope connections from this deployment to share the same budget.
datascope_post_metadata_object_by_idWRITEUpdate a list element via POST /api/external/metadata_object/{id}. Update one element of a custom list by its internal id. The whole `list_object` is sent, so read the current values first and send them back with your change. Note the id is in the PATH here while the read above takes it as a query parameter -- that asymmetry is DataScope's, not ours. 422 on wrong parameters, 403 when the credential may not write. The DataScope API is available on the Professional plan and above; on a free or Starter account every call is refused however correct the key is. DataScope counts its rate limit per SOURCE IP rather than per key -- its own reference says "the limit is counted per source IP, not per token" -- and answers 429 with an HTML page titled "500 Error" and no Retry-After header. A 429 is a THROTTLE, never a bad key: wait and retry rather than re-pasting the key, and expect other DataScope connections from this deployment to share the same budget.
datascope_post_metadata_objects_bulk_updateWRITEReplace every element of a list via POST /api/external/metadata_objects/bulk_update. DESTRUCTIVE, AND IN A WAY THE NAME DOES NOT SUGGEST. This does not merge: DataScope's own warning is "This operation will delete all existing objects for the specified metadata_type and replace them with the new objects provided". Elements are matched by `code` -- an existing code is updated, a new one is created, and EVERY ELEMENT WHOSE CODE IS ABSENT FROM `list_objects` IS SOFT-DELETED. So a partial array silently empties most of a list. READ THE LIST FIRST with List the elements of a list and send the full set back with your changes. The reply's `length` is the number of elements the list ends up with, which is the cheapest check that the call did what was meant. DataScope marks this endpoint EXPERIMENTAL ("Changes may be made to functionality or structure as we continue testing"). `metadata_type` must not be `locations` -- that answers 400; use the locations tools. The DataScope API is available on the Professional plan and above; on a free or Starter account every call is refused however correct the key is. DataScope counts its rate limit per SOURCE IP rather than per key -- its own reference says "the limit is counted per source IP, not per token" -- and answers 429 with an HTML page titled "500 Error" and no Retry-After header. A 429 is a THROTTLE, never a bad key: wait and retry rather than re-pasting the key, and expect other DataScope connections from this deployment to share the same budget.
datascope_post_metadata_typesWRITECreate an empty list via POST /api/external/metadata_types. Create a new, empty custom list. The reply carries the list's `id` and its `code`, and that code is the `metadata_type` every list-element tool takes. Add elements to it with Create a list element, or all at once with Replace every element of a list. 201 on success, 422 on wrong parameters, 403 when the credential may not write. The DataScope API is available on the Professional plan and above; on a free or Starter account every call is refused however correct the key is. DataScope counts its rate limit per SOURCE IP rather than per key -- its own reference says "the limit is counted per source IP, not per token" -- and answers 429 with an HTML page titled "500 Error" and no Retry-After header. A 429 is a THROTTLE, never a bad key: wait and retry rather than re-pasting the key, and expect other DataScope connections from this deployment to share the same budget.
datascope_post_metadata_types_by_idWRITEUpdate a list via POST /api/external/metadata_types/{id}. Update a custom list's own name, description, code or type -- not its elements, which Create a list element and Replace every element of a list own. CHANGING `code` CHANGES THE `metadata_type` every other list tool addresses this list by, so anything holding the old code stops finding it. 422 on wrong parameters, 403 when the credential may not write. The DataScope API is available on the Professional plan and above; on a free or Starter account every call is refused however correct the key is. DataScope counts its rate limit per SOURCE IP rather than per key -- its own reference says "the limit is counted per source IP, not per token" -- and answers 429 with an HTML page titled "500 Error" and no Retry-After header. A 429 is a THROTTLE, never a bad key: wait and retry rather than re-pasting the key, and expect other DataScope connections from this deployment to share the same budget.
Often connected alongside
Put DataScope behind one governed endpoint.
Same permissions, same audit trail, whatever else you connect next.