diff --git a/api/config/settings/common.py b/api/config/settings/common.py
index 45480c9ea356f861c972a2867340099ffce60e91..91691f2a5bf93a6cb1f9947165df1a7cf9dbdc13 100644
--- a/api/config/settings/common.py
+++ b/api/config/settings/common.py
@@ -94,6 +94,9 @@ FEDERATION_MUSIC_NEEDS_APPROVAL = env.bool(
 )
 # XXX: deprecated, see #186
 FEDERATION_ACTOR_FETCH_DELAY = env.int("FEDERATION_ACTOR_FETCH_DELAY", default=60 * 12)
+FEDERATION_SERVICE_ACTOR_USERNAME = env(
+    "FEDERATION_SERVICE_ACTOR_USERNAME", default="service"
+)
 ALLOWED_HOSTS = env.list("DJANGO_ALLOWED_HOSTS", default=[]) + [FUNKWHALE_HOSTNAME]
 
 # APP CONFIGURATION
diff --git a/api/funkwhale_api/common/utils.py b/api/funkwhale_api/common/utils.py
index bd9fd87c54de936f642cafc85e535cf7d8e50871..eec7a02cc301664901d37adbe8143d3b18e01faf 100644
--- a/api/funkwhale_api/common/utils.py
+++ b/api/funkwhale_api/common/utils.py
@@ -147,3 +147,24 @@ def order_for_search(qs, field):
     this function will order the given qs based on the length of the given field
     """
     return qs.annotate(__size=models.functions.Length(field)).order_by("__size")
+
+
+def recursive_getattr(obj, key, permissive=False):
+    """
+    Given a dictionary such as {'user': {'name': 'Bob'}} and
+    a dotted string such as user.name, returns 'Bob'.
+
+    If the value is not present, returns None
+    """
+    v = obj
+    for k in key.split("."):
+        try:
+            v = v.get(k)
+        except (TypeError, AttributeError):
+            if not permissive:
+                raise
+            return
+        if v is None:
+            return
+
+    return v
diff --git a/api/funkwhale_api/federation/activity.py b/api/funkwhale_api/federation/activity.py
index b9f8ffd69292fe1868417e058ad81d3e094327c4..94b7fd54e51eaf3bea88c1aaab66b3f30725a763 100644
--- a/api/funkwhale_api/federation/activity.py
+++ b/api/funkwhale_api/federation/activity.py
@@ -9,6 +9,8 @@ from django.db.models import Q
 from funkwhale_api.common import channels
 from funkwhale_api.common import utils as funkwhale_utils
 
+recursive_getattr = funkwhale_utils.recursive_getattr
+
 
 logger = logging.getLogger(__name__)
 PUBLIC_ADDRESS = "https://www.w3.org/ns/activitystreams#Public"
@@ -89,9 +91,9 @@ def should_reject(id, actor_id=None, payload={}):
 
     media_types = ["Audio", "Artist", "Album", "Track", "Library", "Image"]
     relevant_values = [
-        recursive_gettattr(payload, "type", permissive=True),
-        recursive_gettattr(payload, "object.type", permissive=True),
-        recursive_gettattr(payload, "target.type", permissive=True),
+        recursive_getattr(payload, "type", permissive=True),
+        recursive_getattr(payload, "object.type", permissive=True),
+        recursive_getattr(payload, "target.type", permissive=True),
     ]
     # if one of the payload types match our internal media types, then
     # we apply policies that reject media
@@ -343,7 +345,7 @@ class OutboxRouter(Router):
             return activities
 
 
-def recursive_gettattr(obj, key, permissive=False):
+def recursive_getattr(obj, key, permissive=False):
     """
     Given a dictionary such as {'user': {'name': 'Bob'}} and
     a dotted string such as user.name, returns 'Bob'.
@@ -366,7 +368,7 @@ def recursive_gettattr(obj, key, permissive=False):
 
 def match_route(route, payload):
     for key, value in route.items():
-        payload_value = recursive_gettattr(payload, key)
+        payload_value = recursive_getattr(payload, key)
         if payload_value != value:
             return False
 
diff --git a/api/funkwhale_api/federation/actors.py b/api/funkwhale_api/federation/actors.py
index c7a0c7c6b61c0bdbe83253286b5cb156b0370ba0..95997f95257dfcfd59f143447373e767bb52ae6f 100644
--- a/api/funkwhale_api/federation/actors.py
+++ b/api/funkwhale_api/federation/actors.py
@@ -5,8 +5,9 @@ from django.conf import settings
 from django.utils import timezone
 
 from funkwhale_api.common import preferences, session
+from funkwhale_api.users import models as users_models
 
-from . import models, serializers
+from . import keys, models, serializers
 
 logger = logging.getLogger(__name__)
 
@@ -28,7 +29,7 @@ def get_actor_data(actor_url):
 def get_actor(fid, skip_cache=False):
     if not skip_cache:
         try:
-            actor = models.Actor.objects.get(fid=fid)
+            actor = models.Actor.objects.select_related().get(fid=fid)
         except models.Actor.DoesNotExist:
             actor = None
         fetch_delta = datetime.timedelta(
@@ -42,3 +43,23 @@ def get_actor(fid, skip_cache=False):
     serializer.is_valid(raise_exception=True)
 
     return serializer.save(last_fetch_date=timezone.now())
+
+
+def get_service_actor():
+    name, domain = (
+        settings.FEDERATION_SERVICE_ACTOR_USERNAME,
+        settings.FEDERATION_HOSTNAME,
+    )
+    try:
+        return models.Actor.objects.select_related().get(
+            preferred_username=name, domain__name=domain
+        )
+    except models.Actor.DoesNotExist:
+        pass
+
+    args = users_models.get_actor_data(name)
+    private, public = keys.get_key_pair()
+    args["private_key"] = private.decode("utf-8")
+    args["public_key"] = public.decode("utf-8")
+    args["type"] = "Service"
+    return models.Actor.objects.create(**args)
diff --git a/api/funkwhale_api/federation/authentication.py b/api/funkwhale_api/federation/authentication.py
index dd7a142dfe483aa9ee51b1d50de72c4c52a3ce4c..75e0332421feb115eac1ee58acc2906b2ae06ae5 100644
--- a/api/funkwhale_api/federation/authentication.py
+++ b/api/funkwhale_api/federation/authentication.py
@@ -1,11 +1,13 @@
 import cryptography
 import logging
+import datetime
 
 from django.contrib.auth.models import AnonymousUser
-from rest_framework import authentication, exceptions as rest_exceptions
+from django.utils import timezone
 
+from rest_framework import authentication, exceptions as rest_exceptions
 from funkwhale_api.moderation import models as moderation_models
-from . import actors, exceptions, keys, signing, utils
+from . import actors, exceptions, keys, signing, tasks, utils
 
 
 logger = logging.getLogger(__name__)
@@ -57,6 +59,15 @@ class SignatureAuthentication(authentication.BaseAuthentication):
             actor = actors.get_actor(actor_url, skip_cache=True)
             signing.verify_django(request, actor.public_key.encode("utf-8"))
 
+        # we trigger a nodeinfo update on the actor's domain, if needed
+        fetch_delay = 24 * 3600
+        now = timezone.now()
+        last_fetch = actor.domain.nodeinfo_fetch_date
+        if not last_fetch or (
+            last_fetch < (now - datetime.timedelta(seconds=fetch_delay))
+        ):
+            tasks.update_domain_nodeinfo(domain_name=actor.domain.name)
+            actor.domain.refresh_from_db()
         return actor
 
     def authenticate(self, request):
diff --git a/api/funkwhale_api/federation/factories.py b/api/funkwhale_api/federation/factories.py
index f54f6867861230e3b2bc7ffd4fcf1adbcd61fe3a..e9a51779e2a98bb96d2e7bfc627bda8ad4c12c05 100644
--- a/api/funkwhale_api/federation/factories.py
+++ b/api/funkwhale_api/federation/factories.py
@@ -69,6 +69,7 @@ def create_user(actor):
 @registry.register
 class DomainFactory(NoUpdateOnCreate, factory.django.DjangoModelFactory):
     name = factory.Faker("domain_name")
+    nodeinfo_fetch_date = factory.LazyFunction(lambda: timezone.now())
 
     class Meta:
         model = "federation.Domain"
diff --git a/api/funkwhale_api/federation/migrations/0017_auto_20190130_0926.py b/api/funkwhale_api/federation/migrations/0017_auto_20190130_0926.py
new file mode 100644
index 0000000000000000000000000000000000000000..7c025fa48bf637cced238317b09a26b1d3b46ea7
--- /dev/null
+++ b/api/funkwhale_api/federation/migrations/0017_auto_20190130_0926.py
@@ -0,0 +1,36 @@
+# Generated by Django 2.1.5 on 2019-01-30 09:26
+
+import django.contrib.postgres.fields.jsonb
+from django.db import migrations, models
+import django.db.models.deletion
+import funkwhale_api.common.validators
+import funkwhale_api.federation.models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('federation', '0016_auto_20181227_1605'),
+    ]
+
+    operations = [
+        migrations.RemoveField(
+            model_name='actor',
+            name='old_domain',
+        ),
+        migrations.AddField(
+            model_name='domain',
+            name='service_actor',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='managed_domains', to='federation.Actor'),
+        ),
+        migrations.AlterField(
+            model_name='domain',
+            name='name',
+            field=models.CharField(max_length=255, primary_key=True, serialize=False, validators=[funkwhale_api.common.validators.DomainValidator()]),
+        ),
+        migrations.AlterField(
+            model_name='domain',
+            name='nodeinfo',
+            field=django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=funkwhale_api.federation.models.empty_dict, max_length=50000),
+        ),
+    ]
diff --git a/api/funkwhale_api/federation/models.py b/api/funkwhale_api/federation/models.py
index 59360aea10374ff2d4e804008fb9f62aeecb156f..03e9560a5cf83c6e29020bf5eaf3f9c44cafcb9f 100644
--- a/api/funkwhale_api/federation/models.py
+++ b/api/funkwhale_api/federation/models.py
@@ -46,7 +46,9 @@ class FederationMixin(models.Model):
 
 class ActorQuerySet(models.QuerySet):
     def local(self, include=True):
-        return self.exclude(user__isnull=include)
+        if include:
+            return self.filter(domain__name=settings.FEDERATION_HOSTNAME)
+        return self.exclude(domain__name=settings.FEDERATION_HOSTNAME)
 
     def with_current_usage(self):
         qs = self
@@ -92,7 +94,13 @@ class Domain(models.Model):
     creation_date = models.DateTimeField(default=timezone.now)
     nodeinfo_fetch_date = models.DateTimeField(default=None, null=True, blank=True)
     nodeinfo = JSONField(default=empty_dict, max_length=50000, blank=True)
-
+    service_actor = models.ForeignKey(
+        "Actor",
+        related_name="managed_domains",
+        on_delete=models.SET_NULL,
+        null=True,
+        blank=True,
+    )
     objects = DomainQuerySet.as_manager()
 
     def __str__(self):
diff --git a/api/funkwhale_api/federation/tasks.py b/api/funkwhale_api/federation/tasks.py
index f7d8913b7634f7b1529f65300aa8aea97a59bb81..9722cd88a228b816b9c101a24d79bfae2bb0c4dc 100644
--- a/api/funkwhale_api/federation/tasks.py
+++ b/api/funkwhale_api/federation/tasks.py
@@ -11,6 +11,7 @@ from requests.exceptions import RequestException
 
 from funkwhale_api.common import preferences
 from funkwhale_api.common import session
+from funkwhale_api.common import utils as common_utils
 from funkwhale_api.music import models as music_models
 from funkwhale_api.taskapp import celery
 
@@ -18,6 +19,7 @@ from . import keys
 from . import models, signing
 from . import serializers
 from . import routes
+from . import utils
 
 logger = logging.getLogger(__name__)
 
@@ -184,9 +186,27 @@ def update_domain_nodeinfo(domain):
         nodeinfo = {"status": "ok", "payload": fetch_nodeinfo(domain.name)}
     except (requests.RequestException, serializers.serializers.ValidationError) as e:
         nodeinfo = {"status": "error", "error": str(e)}
+
+    service_actor_id = common_utils.recursive_getattr(
+        nodeinfo, "payload.metadata.actorId", permissive=True
+    )
+    try:
+        domain.service_actor = (
+            utils.retrieve_ap_object(
+                service_actor_id,
+                queryset=models.Actor,
+                serializer_class=serializers.ActorSerializer,
+            )
+            if service_actor_id
+            else None
+        )
+    except (serializers.serializers.ValidationError, RequestException) as e:
+        logger.warning(
+            "Cannot fetch system actor for domain %s: %s", domain.name, str(e)
+        )
     domain.nodeinfo_fetch_date = now
     domain.nodeinfo = nodeinfo
-    domain.save(update_fields=["nodeinfo", "nodeinfo_fetch_date"])
+    domain.save(update_fields=["nodeinfo", "nodeinfo_fetch_date", "service_actor"])
 
 
 def delete_qs(qs):
diff --git a/api/funkwhale_api/instance/nodeinfo.py b/api/funkwhale_api/instance/nodeinfo.py
index 286cb0284f9d922c74b10d10b4cd5ee4f3a70d1f..081773b5306eed6a1accfbbbbb932813467edfc6 100644
--- a/api/funkwhale_api/instance/nodeinfo.py
+++ b/api/funkwhale_api/instance/nodeinfo.py
@@ -2,6 +2,7 @@ import memoize.djangocache
 
 import funkwhale_api
 from funkwhale_api.common import preferences
+from funkwhale_api.federation import actors
 
 from . import stats
 
@@ -19,6 +20,7 @@ def get():
         "openRegistrations": preferences.get("users__registration_enabled"),
         "usage": {"users": {"total": 0, "activeHalfyear": 0, "activeMonth": 0}},
         "metadata": {
+            "actorId": actors.get_service_actor().fid,
             "private": preferences.get("instance__nodeinfo_private"),
             "shortDescription": preferences.get("instance__short_description"),
             "longDescription": preferences.get("instance__long_description"),
diff --git a/api/funkwhale_api/users/models.py b/api/funkwhale_api/users/models.py
index 32e4869a37fbaa1ac313a2e88e7033ac7e9faeca..b34693ed0b4089cba80780a1d69dba0de43a223a 100644
--- a/api/funkwhale_api/users/models.py
+++ b/api/funkwhale_api/users/models.py
@@ -245,41 +245,52 @@ class Invitation(models.Model):
         return super().save(**kwargs)
 
 
-def get_actor_data(user):
-    username = federation_utils.slugify_username(user.username)
+def get_actor_data(username):
+    slugified_username = federation_utils.slugify_username(username)
     return {
-        "preferred_username": username,
+        "preferred_username": slugified_username,
         "domain": federation_models.Domain.objects.get_or_create(
             name=settings.FEDERATION_HOSTNAME
         )[0],
         "type": "Person",
-        "name": user.username,
+        "name": username,
         "manually_approves_followers": False,
         "fid": federation_utils.full_url(
-            reverse("federation:actors-detail", kwargs={"preferred_username": username})
+            reverse(
+                "federation:actors-detail",
+                kwargs={"preferred_username": slugified_username},
+            )
         ),
         "shared_inbox_url": federation_models.get_shared_inbox_url(),
         "inbox_url": federation_utils.full_url(
-            reverse("federation:actors-inbox", kwargs={"preferred_username": username})
+            reverse(
+                "federation:actors-inbox",
+                kwargs={"preferred_username": slugified_username},
+            )
         ),
         "outbox_url": federation_utils.full_url(
-            reverse("federation:actors-outbox", kwargs={"preferred_username": username})
+            reverse(
+                "federation:actors-outbox",
+                kwargs={"preferred_username": slugified_username},
+            )
         ),
         "followers_url": federation_utils.full_url(
             reverse(
-                "federation:actors-followers", kwargs={"preferred_username": username}
+                "federation:actors-followers",
+                kwargs={"preferred_username": slugified_username},
             )
         ),
         "following_url": federation_utils.full_url(
             reverse(
-                "federation:actors-following", kwargs={"preferred_username": username}
+                "federation:actors-following",
+                kwargs={"preferred_username": slugified_username},
             )
         ),
     }
 
 
 def create_actor(user):
-    args = get_actor_data(user)
+    args = get_actor_data(user.username)
     private, public = keys.get_key_pair()
     args["private_key"] = private.decode("utf-8")
     args["public_key"] = public.decode("utf-8")
diff --git a/api/tests/federation/test_actors.py b/api/tests/federation/test_actors.py
index a416cd78f3289e5f48acb3466eb3145777d34467..97ecf31ad0690ce128f2616086b8fce146727a1d 100644
--- a/api/tests/federation/test_actors.py
+++ b/api/tests/federation/test_actors.py
@@ -46,3 +46,15 @@ def test_get_actor_refresh(factories, preferences, mocker):
     assert new_actor == actor
     assert new_actor.last_fetch_date > actor.last_fetch_date
     assert new_actor.preferred_username == "New me"
+
+
+def test_get_service_actor(db, settings):
+    settings.FEDERATION_HOSTNAME = "test.hello"
+    settings.FEDERATION_SERVICE_ACTOR_USERNAME = "bob"
+    actor = actors.get_service_actor()
+
+    assert actor.preferred_username == "bob"
+    assert actor.domain.name == "test.hello"
+    assert actor.private_key is not None
+    assert actor.type == "Service"
+    assert actor.public_key is not None
diff --git a/api/tests/federation/test_authentication.py b/api/tests/federation/test_authentication.py
index 7af7089f66c19bcadbb77a98e3c4eac253cf4382..3298f9543c24dbf82456ed2eff451d6adceff728 100644
--- a/api/tests/federation/test_authentication.py
+++ b/api/tests/federation/test_authentication.py
@@ -5,6 +5,7 @@ from funkwhale_api.federation import authentication, exceptions, keys
 
 def test_authenticate(factories, mocker, api_request):
     private, public = keys.get_key_pair()
+    factories["federation.Domain"](name="test.federation", nodeinfo_fetch_date=None)
     actor_url = "https://test.federation/actor"
     mocker.patch(
         "funkwhale_api.federation.actors.get_actor_data",
@@ -22,6 +23,10 @@ def test_authenticate(factories, mocker, api_request):
             },
         },
     )
+    update_domain_nodeinfo = mocker.patch(
+        "funkwhale_api.federation.tasks.update_domain_nodeinfo"
+    )
+
     signed_request = factories["federation.SignedRequest"](
         auth__key=private, auth__key_id=actor_url + "#main-key", auth__headers=["date"]
     )
@@ -40,6 +45,7 @@ def test_authenticate(factories, mocker, api_request):
     assert user.is_anonymous is True
     assert actor.public_key == public.decode("utf-8")
     assert actor.fid == actor_url
+    update_domain_nodeinfo.assert_called_once_with(domain_name="test.federation")
 
 
 def test_authenticate_skips_blocked_domain(factories, api_request):
diff --git a/api/tests/federation/test_tasks.py b/api/tests/federation/test_tasks.py
index f3216eed77f235322ef61cb716f2c02b5a7e9bf1..7e73be26f3f6e9aaffdf203638d91a4556d55116 100644
--- a/api/tests/federation/test_tasks.py
+++ b/api/tests/federation/test_tasks.py
@@ -161,22 +161,32 @@ def test_fetch_nodeinfo(factories, r_mock, now):
 
 
 def test_update_domain_nodeinfo(factories, mocker, now):
-    domain = factories["federation.Domain"]()
-    mocker.patch.object(tasks, "fetch_nodeinfo", return_value={"hello": "world"})
+    domain = factories["federation.Domain"](nodeinfo_fetch_date=None)
+    actor = factories["federation.Actor"](fid="https://actor.id")
+    mocker.patch.object(
+        tasks,
+        "fetch_nodeinfo",
+        return_value={"hello": "world", "metadata": {"actorId": "https://actor.id"}},
+    )
 
     assert domain.nodeinfo == {}
     assert domain.nodeinfo_fetch_date is None
+    assert domain.service_actor is None
 
     tasks.update_domain_nodeinfo(domain_name=domain.name)
 
     domain.refresh_from_db()
 
     assert domain.nodeinfo_fetch_date == now
-    assert domain.nodeinfo == {"status": "ok", "payload": {"hello": "world"}}
+    assert domain.nodeinfo == {
+        "status": "ok",
+        "payload": {"hello": "world", "metadata": {"actorId": "https://actor.id"}},
+    }
+    assert domain.service_actor == actor
 
 
 def test_update_domain_nodeinfo_error(factories, r_mock, now):
-    domain = factories["federation.Domain"]()
+    domain = factories["federation.Domain"](nodeinfo_fetch_date=None)
     wellknown_url = "https://{}/.well-known/nodeinfo".format(domain.name)
 
     r_mock.get(wellknown_url, status_code=500)
diff --git a/api/tests/federation/test_views.py b/api/tests/federation/test_views.py
index 2caa7856a10c81ba13aaf024a7f155d0bb074c9e..282ee16fef51c75da77f614ecad6824448c23aab 100644
--- a/api/tests/federation/test_views.py
+++ b/api/tests/federation/test_views.py
@@ -2,7 +2,7 @@ import pytest
 from django.core.paginator import Paginator
 from django.urls import reverse
 
-from funkwhale_api.federation import serializers, webfinger
+from funkwhale_api.federation import actors, serializers, webfinger
 
 
 def test_wellknown_webfinger_validates_resource(db, api_client, settings, mocker):
@@ -54,6 +54,19 @@ def test_local_actor_detail(factories, api_client):
     assert response.data == serializer.data
 
 
+def test_service_actor_detail(factories, api_client):
+    actor = actors.get_service_actor()
+    url = reverse(
+        "federation:actors-detail",
+        kwargs={"preferred_username": actor.preferred_username},
+    )
+    serializer = serializers.ActorSerializer(actor)
+    response = api_client.get(url)
+
+    assert response.status_code == 200
+    assert response.data == serializer.data
+
+
 def test_local_actor_inbox_post_requires_auth(factories, api_client):
     user = factories["users.User"](with_actor=True)
     url = reverse(
diff --git a/api/tests/instance/test_nodeinfo.py b/api/tests/instance/test_nodeinfo.py
index a5bdc70933c696faae1297540532b594453d110b..90dc7e7062e69292873c856ff4b71ffdf29512a2 100644
--- a/api/tests/instance/test_nodeinfo.py
+++ b/api/tests/instance/test_nodeinfo.py
@@ -1,5 +1,6 @@
 import funkwhale_api
 from funkwhale_api.instance import nodeinfo
+from funkwhale_api.federation import actors
 
 
 def test_nodeinfo_dump(preferences, mocker):
@@ -23,6 +24,7 @@ def test_nodeinfo_dump(preferences, mocker):
         "openRegistrations": preferences["users__registration_enabled"],
         "usage": {"users": {"total": 1, "activeHalfyear": 12, "activeMonth": 13}},
         "metadata": {
+            "actorId": actors.get_service_actor().fid,
             "private": preferences["instance__nodeinfo_private"],
             "shortDescription": preferences["instance__short_description"],
             "longDescription": preferences["instance__long_description"],
@@ -60,6 +62,7 @@ def test_nodeinfo_dump_stats_disabled(preferences, mocker):
         "openRegistrations": preferences["users__registration_enabled"],
         "usage": {"users": {"total": 0, "activeHalfyear": 0, "activeMonth": 0}},
         "metadata": {
+            "actorId": actors.get_service_actor().fid,
             "private": preferences["instance__nodeinfo_private"],
             "shortDescription": preferences["instance__short_description"],
             "longDescription": preferences["instance__long_description"],
diff --git a/api/tests/manage/test_serializers.py b/api/tests/manage/test_serializers.py
index 53bc2504b2487e018448755f4cd25b9438108efe..aef8dc4ea9c837124401733ead8dcbb64ae06aec 100644
--- a/api/tests/manage/test_serializers.py
+++ b/api/tests/manage/test_serializers.py
@@ -40,7 +40,7 @@ def test_user_update_permission(factories):
 
 
 def test_manage_domain_serializer(factories, now):
-    domain = factories["federation.Domain"]()
+    domain = factories["federation.Domain"](nodeinfo_fetch_date=None)
     setattr(domain, "actors_count", 42)
     setattr(domain, "outbox_activities_count", 23)
     expected = {
diff --git a/changes/changelog.d/system-actor.enhancement b/changes/changelog.d/system-actor.enhancement
new file mode 100644
index 0000000000000000000000000000000000000000..25c5534a862c73b3f121f5bf08cdc90b69dbe3ef
--- /dev/null
+++ b/changes/changelog.d/system-actor.enhancement
@@ -0,0 +1 @@
+Expose an instance-level actor (service@domain) in nodeinfo endpoint (#689)