Is there a way to add tags per client API?

Hi,
I would like to revive a topic that was asked 2017 but no answer was given. Maybe that changed in 2020:
Is there a way to add tags to a document using the REST or WebDav or whatever API?
If so, could someone give me an example?
I would like to test nextcloud as an DMS and thus have to import several thousend tagged documents.

Thanks

Like Upload and get file throught tag properties?

Thank you, the part with “PROPPATCH” looks pretty much like what I was looking for.
However, appearently it does not work. If I execute it, then I get 200 OK as response but no tag is added. I assume I can see tags in the details as “collaborative tags” or am I mistaken? The name insinuates that there may be other categories of tags.

Maybe important: My nextcloud version is 17.0.2.

BTW: Is there a way to show tags in the files list right next to file names?

curl -X PROPPATCH \
  https://nextcloud.test/remote.php/dav/files/admin/test.png \
  -H 'Authorization: Basic YWRtaW46YWRtaW4=' \
  -H 'Connection: keep-alive' \
  -H 'Content-Length: 258' \
  -H 'Content-Type: application/xml' \
  -d '<?xml version="1.0"?>
<d:propertyupdate xmlns:d="DAV:" xmlns:oc="http://owncloud.org/ns">
    <d:set>
        <d:prop>
            <oc:tags>
                <oc:tag>Wallpapers</oc:tag>
            </oc:tags>
        </d:prop>
    </d:set>
</d:propertyupdate>'

I think there are Systemtags what we see on the tab “tag” and there is the property oc:tags which can have a groupof tag-properties. I think you just update property-tags of a resource. To add a systemtag, you can run the following request:

curl ‘your/nextcloud/server/path/remote.php/dav/systemtags/’ -H ‘Connection: keep-alive’ -H ‘requesttoken: Hwwe1jFy4+VUzkQvdZ2Rliu4bZZg8vFRkITIHrfjVjw=:bW5br2IZ29cW9whGMND+2FjcIf0jy95i2uifSe25JgQ=’ -H ‘X-Requested-With: XMLHttpRequest’ -H ‘User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36’ -H ‘Content-Type: application/json’ -H ‘Accept: /’ -H ‘Origin: your/nextcloud/server/path’ -H ‘Accept-Encoding: gzip, deflate’ -H ‘Accept-Language: en-GB,en-US;q=0.9,en;q=0.8,de;q=0.7’ -H ‘Cookie: nc_sameSiteCookielax=true; nc_sameSiteCookiestrict=true; nc_username=yourUsername; oc_sessionPassphrase=szbMZo1paGbmRVr%2Fr8rcL%2Fz%2FuZ6QX09blpQpYLVXRGexUkGcU9lBmeqcxQmD4AAxyDJ%2BBwJleJGtwnr0m%2F1Sj4WuxOeGCnhx2FaFgfLguTQfFksQq5QrYKzdqoaV%2BBUr; ockdwm1acqn7=e05121c702f545e2510e57323ebe06f6; nc_token=wL%2Btd37Ak%2BNBSRCO7sdl0gwEzRyivVYV; nc_session_id=e05121c702f545e2510e57323ebe06f6’ --data-binary ‘{“userVisible”:true,“userAssignable”:true,“canAssign”:true,“name”:“tagName”}’ --compressed --insecure

you can test it with postman and before add your the Authorization basic and change set your nextcloud server path and your username.

I hope it could help you.

Oh. Collaborative tags (=> systemtags codewise) seems to be a different story than Tags (=> vobjects codewise). I don’t know if there is way how to connect them :disappointed:

Good finding @Arthur1 :+1:

curl -X PUT \
  https://nextcloud.test/remote.php/dav/systemtags-relations/files/1371/1 \
  -H 'Accept: */*' \
  -H 'Accept-Encoding: gzip, deflate' \
  -H 'Authorization: Basic YWRtaW46YWRtaW4=' \
  -H 'Cache-Control: no-cache' \
  -H 'Connection: keep-alive' \
  -H 'Content-Length: 0' \
  -H 'Content-Type: application/json' \
  -H 'Host: nextcloud.test' \
  -H 'cache-control: no-cache' \

Above request will save Tag 1 for File with ID 1371.

curl -X DELETE \
  'https://nextcloud.test/remote.php/dav/systemtags-relations/files/1371/1' \
  -H 'Accept: */*' \
  -H 'Accept-Encoding: gzip, deflate' \
  -H 'Authorization: Basic YWRtaW46YWRtaW4=' \
  -H 'Cache-Control: no-cache' \
  -H 'Connection: keep-alive' \
  -H 'Content-Length: 0' \
  -H 'Content-Type: application/json' \
  -H 'Host: nextcloud.test' \
  -H 'cache-control: no-cache'

Will delete Tag 1 from File with ID 1371.

2 Likes

Thank you for the hint with the curl-call.
I tried it but it did not work as expected.
First, I added a tag “Test” to a file.
Then I applied daniel512’s command to another file (file id=7) and tag (=1,). I get no response in this case but there appears no tag in the details of the file. When I try another tag id then I get an error response, so I believe the tag id exists.

Even if it worked I have the feeling the process is quite complicated:

  1. Upload a file
  2. Get the Id of the file (I guess via PROPFIND request)
  3. Get the list of tags, check if the desired tag is already there, get the id of it. (No idea how)
  4. If not, add tag, get id of tag (no idea how)
  5. Add tag id to file id.

Isnt there a way to add a tag by name to the file by name?
Otherwise is there a comprehensive documentation of the API? I could not find the call for daniel512’s post.
When I google I just find:
https://docs.nextcloud.com/server/latest/developer_manual/client_apis/WebDAV/basic.html#webdav-basics
which is not very comprehensive.

I added a tag via web and checked the xhr request :wink: Yes adding a tag by path would be nice.

You mean the call is what the web client is doing when I add a tag? Smart.
However it does not appear to work in my case. How can I find out what I am doing wrong?

I do not know how to proceed. The curl call does not return an error. I do not know how to list all tags to check the ids. The administrative page in the web client speaks of collaborative tags but your call suggests system-tags which as I understand cannot be seen or used in the web client.

I am that close to migrate my DMS to nextcloud but I would need tags for it and cannot add them manually.

Tags an Nextcloud are a long story. If that is a must have for you better stay with the DMS :disappointed:



I guess there is not much code missing to add support for setting tags via a proppatch call (it’s already possible for the “old” tags with oc:tags). But someone has to do it :wink:

I am impressed how fast you answer. Thank you for that.
I rechecked: I had a wrong file id when testing the curl call. I requested the right one per propfind.
Now I can add an existing tag.

Now there are only two pieces missing:
How do I get the ID of a tag and:
How do I add a new tag to the list.

curl -X POST \
  https://nextcloud.test/remote.php/dav/systemtags/ \
  -H 'Accept: */*' \
  -H 'Accept-Encoding: gzip, deflate' \
  -H 'Authorization: Basic YWRtaW46YWRtaW4=' \
  -H 'Cache-Control: no-cache' \
  -H 'Connection: keep-alive' \
  -H 'Content-Length: 79' \
  -H 'Content-Type: application/json' \
  -H 'Host: nextcloud.test' \
  -H 'cache-control: no-cache' \
  -d '{"userVisible":true,"userAssignable":true,"canAssign":true,"name":"Teeeeeeest"}'
curl -X PROPFIND \
  https://nextcloud.test/remote.php/dav/systemtags/ \
  -H 'Accept: */*' \
  -H 'Accept-Encoding: gzip, deflate' \
  -H 'Authorization: Basic YWRtaW46YWRtaW4=' \
  -H 'Cache-Control: no-cache' \
  -H 'Connection: keep-alive' \
  -H 'Content-Length: 0' \
  -H 'Content-Type: application/json' \
  -H 'Host: nextcloud.test' \
  -H 'cache-control: no-cache'

Response is like below. Take href. /x is the tagId.

<?xml version="1.0"?>
<d:multistatus xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns" xmlns:oc="http://owncloud.org/ns" xmlns:nc="http://nextcloud.org/ns">
    <d:response>
        <d:href>/remote.php/dav/systemtags/</d:href>
        <d:propstat>
            <d:prop>
                <d:resourcetype>
                    <d:collection/>
                </d:resourcetype>
            </d:prop>
            <d:status>HTTP/1.1 200 OK</d:status>
        </d:propstat>
    </d:response>
    <d:response>
        <d:href>/remote.php/dav/systemtags/3</d:href>
        <d:propstat>
            <d:prop>
                <d:resourcetype/>
            </d:prop>
            <d:status>HTTP/1.1 200 OK</d:status>
        </d:propstat>
        <d:propstat>
            <d:prop>
                <d:getlastmodified/>
                <d:getcontentlength/>
                <d:quota-used-bytes/>
                <d:quota-available-bytes/>
                <d:getetag/>
                <d:getcontenttype/>
            </d:prop>
            <d:status>HTTP/1.1 404 Not Found</d:status>
        </d:propstat>
    </d:response>
    <d:response>
        <d:href>/remote.php/dav/systemtags/1</d:href>
        <d:propstat>
            <d:prop>
                <d:resourcetype/>
            </d:prop>
            <d:status>HTTP/1.1 200 OK</d:status>
        </d:propstat>
        <d:propstat>
            <d:prop>
                <d:getlastmodified/>
                <d:getcontentlength/>
                <d:quota-used-bytes/>
                <d:quota-available-bytes/>
                <d:getetag/>
                <d:getcontenttype/>
            </d:prop>
            <d:status>HTTP/1.1 404 Not Found</d:status>
        </d:propstat>
    </d:response>
</d:multistatus>
1 Like

Great. Works as described. Where do you get all this information on the API from?
It is a bit embarassing asking all that info from you bit by bit.
I guess I can get the tag name for a tag id by PROPFINDing /dav/systemtags/x ?

It’s a pattern. Every dav endpoint works similar :wink:

some information could be found here

@TobiCloud how is it going? Did you moved to Nextcloud as DMS? I’m very curious because i’m looking for the same.

Hello abijma,

sorry for the late response. As you can imagine after that time I did not find a solution to the remaining issues to use it properly as a lightweight DMS. They are:

  • I could not find a comprehensive documentation of the API. The best I got is here: Basic APIs — Nextcloud 15 Developer Manual 15 documentation. Mind the number 15 in the URL. I have nowhere the feeling anyone cares for the documentation. However, what is shown there works.

  • I cannot find a comprehensive list of avaliable properties for the tag list. Because of that I cannot determine the tag name from the ID. Here I am stuck. You need the id to add the tag to the file as described above.

Other issues that keep me from using Nextcloud as DMS up to now:

  • I use elasticsearch as an search engine. It is great when works. However, the installation needs a plugin to elasticsearch ‘ingest-attachment’. Whenever ubuntu updates eleasticsearch, it stops working as I have to update that plugin manually, even if the update is on the patch level 7.10.X. In nextcloud you don’t notice because the search just silently fails.

  • Elasticsearch does not search the tags. You can only use the filter on left side navigator.

  • I have not found out how to display the tags next to the file. I know there was a feature request some years ago but that was set ‘Deprecated’.

  • I have issues adding tags manually. When I click on the “…” next to a file I have to open ‘details’, then I have to click on ‘…’ for the entry “tags”. However, often the input box for the tags does not open. I do not know what I am doing wrong here. Anyway, too complicated to quickly add tags.

Why I would like to use nextcloud as a DMS anyway:

  • Best search performance on OCR’ed documents compared to other open-source dms like openkm and mayan.

  • I can keep a tree structure of the files. Call me antiquated but it helps keeping organized.

  • Access by file explorer by the sync mechanism. Easier to use with windows than webdav.

Maybe someone has news on my issues and can help solving the tag issue.

Best regards

thaks for the response @TobiCloud !

I know this a very old topic, but this is for me the first search result on this topic, and as it is not yet fully resolved I would like to add a solution:

List all available system tags, including tag name, so you could get the tag id for the tag name:

curl --location --request PROPFIND 'https://nextcloud.example.com/remote.php/dav/systemtags/' \
--header 'Depth: 1' \
--header 'Content-Type: application/xml' \
--header 'Authorization: Basic XXXX' \
--data '<d:propfind xmlns:d="DAV:" xmlns:oc="http://owncloud.org/ns" xmlns:nc="http://nextcloud.org/ns">
    <d:prop>
        <oc:id />
        <oc:user-assignable />
        <oc:user-visible />
        <oc:can-assign />
        <oc:display-name />
    </d:prop>
</d:propfind>'

Gives a result like:

<?xml version="1.0"?>
<d:multistatus xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns" xmlns:oc="http://owncloud.org/ns" xmlns:nc="http://nextcloud.org/ns">
    <d:response>
        <d:href>/remote.php/dav/systemtags/</d:href>
        <d:propstat>
            <d:prop>
                <oc:id/>
                <oc:user-assignable/>
                <oc:user-visible/>
                <oc:can-assign/>
                <oc:display-name/>
            </d:prop>
            <d:status>HTTP/1.1 404 Not Found</d:status>
        </d:propstat>
    </d:response>
    <d:response>
        <d:href>/remote.php/dav/systemtags/3</d:href>
        <d:propstat>
            <d:prop>
                <oc:id>3</oc:id>
                <oc:user-assignable>true</oc:user-assignable>
                <oc:user-visible>true</oc:user-visible>
                <oc:can-assign>true</oc:can-assign>
                <oc:display-name>Invoice</oc:display-name>
            </d:prop>
            <d:status>HTTP/1.1 200 OK</d:status>
        </d:propstat>
    </d:response>
    <d:response>
        <d:href>/remote.php/dav/systemtags/2</d:href>
        <d:propstat>
            <d:prop>
                <oc:id>2</oc:id>
                <oc:user-assignable>true</oc:user-assignable>
                <oc:user-visible>true</oc:user-visible>
                <oc:can-assign>true</oc:can-assign>
                <oc:display-name>Recipie</oc:display-name>
            </d:prop>
            <d:status>HTTP/1.1 200 OK</d:status>
        </d:propstat>
    </d:response>
</d:multistatus>

The same way you could get the tags already assigned for a file with ID [FILE ID]:

curl --location --request PROPFIND 'https://nextcloud.example.com/remote.php/dav/systemtags-relations/files/[FILE ID]' \
--header 'Depth: 1' \
--header 'Content-Type: application/xml' \
--header 'Authorization: Basic xxx' \
--data '<d:propfind xmlns:d="DAV:" xmlns:oc="http://owncloud.org/ns" xmlns:nc="http://nextcloud.org/ns">
    <d:prop>
        <oc:id />
        <oc:user-assignable />
        <oc:user-visible />
        <oc:can-assign />
        <oc:display-name />
    </d:prop>
</d:propfind>'

Gives:

<?xml version="1.0"?>
<d:multistatus xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns" xmlns:oc="http://owncloud.org/ns" xmlns:nc="http://nextcloud.org/ns">
    <d:response>
        <d:href>/remote.php/dav/systemtags-relations/files/[FILE ID]/</d:href>
        <d:propstat>
            <d:prop>
                <oc:id/>
                <oc:user-assignable/>
                <oc:user-visible/>
                <oc:can-assign/>
                <oc:display-name/>
            </d:prop>
            <d:status>HTTP/1.1 404 Not Found</d:status>
        </d:propstat>
    </d:response>
    <d:response>
        <d:href>/remote.php/dav/systemtags-relations/files/[FILE ID]/2</d:href>
        <d:propstat>
            <d:prop>
                <oc:id>2</oc:id>
                <oc:user-assignable>true</oc:user-assignable>
                <oc:user-visible>true</oc:user-visible>
                <oc:can-assign>true</oc:can-assign>
                <oc:display-name>Recipie</oc:display-name>
            </d:prop>
            <d:status>HTTP/1.1 200 OK</d:status>
        </d:propstat>
    </d:response>
</d:multistatus>

Adding (PUT on https://nextcloud.example.com/remote.php/dav/systemtags-relations/files/[FILE ID]/[TAG ID]) / removing tags to files (DELETE on same url) was already described.

I stumbled across this and didnt notice there was an update. I would still love to use Nextcloud as DMS. But I need proper tagging. Especially for my current 3000+ documents.
@StefanR Does this also work for collaborative tags. I always get confused by that.