API

Atlos offers a project-scoped API to help investigators integrate with third-party services like mapping and archival applications.

You can learn more about the API authentication scheme and endpoints below. API tokens are only accessible to project owners.

Please note that the API is in beta and not all operations are supported; if you need something, please get in touch via email or on Discord.

Create an API token

  1. Navigate to the project for which you need an API token.
  2. Navigate to the Access page of the project.
  3. Press the Create button in the API Tokens section of the page.
  4. Assign the token a name, write a description of what the token is used for, and select permissions for the token.
  5. Click the Create Token button.

API Vocabulary

Atlos’ API uses several terms that users of Atlos might be unfamiliar with:

  • Slugs are six character unique IDs for incidents. AD12H45 is the slug in CIV-AD12H45. Atlos displays incidents’ slugs in the web app. Slugs are also the last part of an incident’s URL.
  • IDs are unique identifiers for projects, pieces of source material, and artifacts. They look like this: d0bce96b-4468-44be-a0d1-419dbd96a879. While incidents have IDs that are sometimes exposed in the API, API endpoints use slugs to refer to incidents and IDs to refer to everything else.
  • Artifacts are the individual files in a piece of source material. A piece of source material, like an archived link, may have zero, one, or more photos, videos, and other files associated with it. This is the hierarchy of content on Atlos:
        • Artifact 1
        • Artifact 2
      • Authentication

        API tokens are sensitive—they allow read and write access to your project. By default, every API token will have access to a READ endpoint.

        To authenticate against the API, include an Authorization header and set its value to Bearer <your token>. In python, that looks like this:

        requests.get(
            f"https://platform.atlos.org/api/v2/{endpoint}",
            headers={"Authorization": f"Bearer {api_token}"},
            params={"cursor": cursor},
        )

        Pagination

        Paginate using the cursor query parameter, whose value is provided by the next and previous keys in the response. Results are available under the results key.

        API Endpoints

        The Atlos API supports GET and POST endpoints. All GET endpoints return 30 results at a time.

        Get all incidents in a project

        GET /api/v2/incidents returns all incidents in a project.

        • Sort— Most recently modified incidents are listed first.
        • Filter— You can optionally pass search parameters to filter results using the same format as the in-platform incident search page’s URL. For example, to return only incidents with the status “To Do” or “Cancelled”, query /api/v2/incidents?attr_status[]=To+Do&attr_status=Cancelled.
        requests.get(
            f"https://platform.atlos.org/api/v2/incidents?attr_status[]=To+Do&attr_status=Cancelled",
            headers={"Authorization": f"Bearer {api_token}"},
            params={"cursor": cursor},
        )

        Get all source material in a project

        GET /api/v2/source_material returns all source material in a project.

        • Sort— Most recently modified source material is listed first.
        requests.get(
            f"httpps://platform.atlos.org/api/v2/source_material",
            headers={"Authorization": f"Bearer {api_token}"},
            params={"cursor": cursor},
        )

        Get a specific piece of source material

        GET /api/v2/source_material/:id returns the source material with the given ID.

        requests.get(
            f"https://platform.atlos.org/api/v2/source_material/d0bce96b-4468-44be-a0d1-419dbd96a879",
            headers={"Authorization": f"Bearer {api_token}"}
        )

        Create a new piece of source material

        POST /api/v2/source_material/new/:slug creates a new piece of source material in the already-existing incident with slug :slug. This endpoint has two optional parameters:

        • url, a URL for Atlos to archive (optional).
        • archive, a boolean value indicating whether Atlos should archive the URL in url (optional).

        Note that if you opt not to archive a link, you will create an empty piece of source material to which you can add artifacts later.

        requests.post(
            f"https://platform.atlos.org/api/v2/source_material/new/ABCDEF",
            headers={"Authorization": f"Bearer {api_token}"},
            params={"url": "https://atlos.org", "archive": True},
        )

        Set source material metadata

        POST /api/v2/source_material/metadata/:id/:namespace with parameter metadata (JSON dictionary) sets the metadata of the given piece of source material (identified by its ID) in the given namespace. Namespaces are used to separate different types of metadata. Typically, an API user would use a namespace that is unique to their application (for example, Bellingcat’s auto archiver uses the auto-archiver namespace). This endpoint expects a JSON content type.

        Using this endpoint will overwrite any existing metadata in the given namespace. Metadata is returned by the API and may be shown in the Atlos web interface as well.

        requests.post(
            f"https://platform.atlos.org/api/v2/source_material/metadata/:id/auto-archiver",
            headers={"Authorization": f"Bearer {api_token}"},
            json={"metadata": {"key": "value"}},
        )

        Upload a file (artifact) to a piece of source material

        POST /api/v2/source_material/upload/:id uploads a file to the piece of source material with ID :id. This endpoint has two parameters:

        • file, which should be sent as a multipart form request (required).
        • title, the title of the file (optional). If provided, Atlos will be display the title in the interface.

        Note: To upload a file to a new incident, you must first create an empty piece of source material. Files always belong to a piece of source material.

        requests.post(
            f"https://platform.atlos.org/api/v2/source_material/upload/:id",
            headers={"Authorization": f"Bearer {api_token}"},
            params={
                "title": media.properties
            },
            files={"file": (os.path.basename(media.filename), open(media.filename, "rb"))},
        )

        Get updates and comments

        GET /api/v2/updates returns all updates (including comments) in a project.

        • Sort— Most recent updates are listed first.
        • Filter— To see updates for a specific incident, append the slug query parameter to the endpoint (e.g., /api/v2/updates?slug=incident-slug). The slug is the last part of the URL for the incident, and is also available in the ‘slug’ field of the incident object returned by other endpoints.
        requests.get(
            f"https://platform.atlos.org/api/v2/updates?slug=ABCDEF",
            headers={"Authorization": f"Bearer {api_token}"},
            params={"cursor": cursor},
        )

        Add a comment to an incident

        POST /api/v2/add_comment/:slug adds a comment to the incident with slug :slug. This endpoint has one required parameter:

        • message contains the string contents of the comment.
        requests.post(
            f"https://platform.atlos.org/api/v2/add_comment/ABCDEF",
            headers={"Authorization": f"Bearer {api_token}"},
            params={"message": "This is a comment."},
        )

        Update an incident’s attribute value

        POST /api/v2/update/:slug/:attribute_name updates the attribute :attribute_name in the incident with slug :slug. It has two parameters:

        • value, the new value of the attribute (required). For text or single-select attributes, value should be a string. For multi-select attributes, value should be a list of strings.
        • message, a string to be displayed as an explanation for the update (optional). If message is provided, it will be added as a comment to the incident (as part of the tracked change).

        The :attribute_name may not be the name of the attribute displayed in the interface:

        • Core attributes have string names (such as description and status).
        • Custom attributes are identified by a long ID.

        To find the name of an attribute, open the attribute editing window and copy the last part of the URL. For example, in the URL https://platform.atlos.org/incidents/EPIHRZ/update/c37c2619-3377-4b97-989b-f3481c7f1948, the attribute’s ID is c37c2619-3377-4b97-989b-f3481c7f1948.

        requests.post(
            f"https://platform.atlos.org/api/v2/update/ABCDE/status",
            headers={"Authorization": f"Bearer {self.api_token}"},
            json={"value": "To Do", "message": "This is a comment."},
        )
        
        requests.post(
            f"https://platform.atlos.org/api/v2/update/ABCDE/c37c2619-3377-4b97-989b-f3481c7f1948",
            headers={"Authorization": f"Bearer {self.api_token}"},
            json={"value": ["Civilian-military interaction", "Protest"], "message": "This is a comment."},
        )