def restrict_use_due_to_api_limit_grace_period_over() -> None:
    """
    Restrict API use once a grace period has ended.

    Since free plans don't have predefined subscription periods, we
    use a rolling thirty day period to filter them.
    """
    now = timezone.now()
    grace_period = now - timedelta(days=API_USAGE_GRACE_PERIOD)
    month_start = now - timedelta(30)
    queryset = (
        OrganisationAPIUsageNotification.objects.filter(
            Q(
                notified_at__gte=month_start,
                notified_at__lte=grace_period,
                percent_usage__gte=100,
            )
            | Q(
                notified_at__gte=month_start,
                notified_at__lte=now,
                percent_usage__gte=100,
                organisation__breached_grace_period__isnull=False,
            )
        )
        .values("organisation")
        .annotate(max_value=Max("percent_usage"))
    )

    organisation_ids = []
    for result in queryset:
        organisation_ids.append(result["organisation"])

    organisations = (
        Organisation.objects.filter(
            id__in=organisation_ids,
            subscription__plan=FREE_PLAN_ID,
            api_limit_access_block__isnull=True,
        )
        .select_related("subscription", "subscription_information_cache")
        .exclude(
            stop_serving_flags=True,
            block_access_to_admin=True,
        )
    )

    api_limit_access_blocks = []
    flagsmith_client = get_client("local", local_eval=True)

    for organisation in organisations:
        flags = flagsmith_client.get_identity_flags(
            organisation.flagsmith_identifier,
            traits={
                "organisation_id": organisation.id,
                "subscription.plan": organisation.subscription.plan,
            },
        )

        stop_serving = flags.is_feature_enabled("api_limiting_stop_serving_flags")
        block_access = flags.is_feature_enabled("api_limiting_block_access_to_admin")

        if not stop_serving and not block_access:
            continue

        if not organisation.has_subscription_information_cache():
            continue

        OrganisationBreachedGracePeriod.objects.get_or_create(organisation=organisation)

        subscription_cache = organisation.subscription_information_cache
        api_usage = get_current_api_usage(
            organisation_id=organisation.id,
            date_start=now - timedelta(days=30),
        )
        if api_usage / subscription_cache.allowed_30d_api_calls < 1.0:
            logger.info(
                f"API use for organisation {organisation.id} has fallen to below limit, so not restricting use."
            )
            continue

        organisation.stop_serving_flags = stop_serving
        organisation.block_access_to_admin = block_access

        if stop_serving:
            send_api_flags_blocked_notification(organisation)

        # Save models individually to allow lifecycle hooks to fire.
        organisation.save()

        api_limit_access_blocks.append(APILimitAccessBlock(organisation=organisation))

    APILimitAccessBlock.objects.bulk_create(api_limit_access_blocks)

    Restrict API use once a grace period has ended.

    Since free plans don't have predefined subscription periods, we
    use a rolling thirty day period to filter them.
    
api/organisations/tasks.py