Skip to main content
Supermemory’s graph automatically derives new facts from patterns across your existing memories (see Graph Memory). These derived facts are guesses — the engine wasn’t told them directly — so they are flagged as inferred (isInference: true) and down-weighted in search until confirmed. These two endpoints let you build a review experience on top of that queue: list the inferred memories awaiting review, then approve, decline, or undo a decision on each one.
These endpoints are scoped to a single container tag (space), under /v3/container-tags/{containerTag}.

How review affects ranking

While a memory is unreviewed and inferred it is down-weighted in search, so the engine’s guesses rank below facts you stated explicitly. Reviewing it resolves that either way:
ActionResultEffect on search
ApproveisInference clearedRanks like a stated fact — no longer down-weighted
DeclineisForgotten setRemoved from search entirely — a rejected guess is forgotten
Undoback to unreviewedReturns to the queue; inferred and down-weighted again
A reviewed memory is stamped with reviewStatus in its metadata so it drops out of the review queue (declined memories also leave search, since they’re forgotten). Undo clears that stamp — and un-forgets a declined memory — bringing it back.

List Inferred Memories

Return the inferred memories for a container tag that are still awaiting review (the review queue). Reviewed memories are excluded.
GET /v3/container-tags/{containerTag}/inferred
const res = await fetch(
  "https://api.supermemory.ai/v3/container-tags/user_123/inferred",
  { headers: { "Authorization": `Bearer ${API_KEY}` } }
);

const { memories, total } = await res.json();

Path parameters

ParameterTypeDescription
containerTagstringThe container tag / space to read the review queue for

Response

{
  "memories": [
    {
      "id": "mem_abc123",
      "memory": "Alex likely works on Stripe's core payments product",
      "parentCount": 3,
      "createdAt": "2025-01-15T10:30:00.000Z",
      "updatedAt": "2025-01-15T10:30:00.000Z",
      "metadata": { "source": "derive" }
    }
  ],
  "total": 1
}
FieldTypeDescription
memories[].idstringMemory entry ID — pass to the review endpoint
memories[].memorystringThe inferred memory text
memories[].parentCountnumberHow many source memories this was derived from. Higher = stronger signal
memories[].createdAtstringISO 8601 timestamp
memories[].updatedAtstringISO 8601 timestamp
memories[].metadataobject | nullArbitrary metadata stored on the memory
totalnumberCount of unreviewed inferred memories returned
The queue returns up to 50 memories, ordered by parentCount descending (most strongly supported first), then by createdAt descending. It excludes anything that is forgotten, expired, or already reviewed. An unknown or empty container tag returns { "memories": [], "total": 0 }.

Review an Inferred Memory

Record a decision on a single inferred memory.
POST /v3/container-tags/{containerTag}/inferred/{memoryId}/review
const res = await fetch(
  "https://api.supermemory.ai/v3/container-tags/user_123/inferred/mem_abc123/review",
  {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${API_KEY}`,
      "Content-Type": "application/json"
    },
    body: JSON.stringify({ action: "approve" })
  }
);

const result = await res.json();
// { id: "mem_abc123", isInference: false, isForgotten: false, reviewStatus: "approved" }

Path parameters

ParameterTypeDescription
containerTagstringThe container tag / space the memory belongs to
memoryIdstringThe memory entry ID from the list endpoint

Body parameters

ParameterTypeRequiredDescription
actionstringyesOne of approve, decline, or undo
The reject action is named decline. There is no reject value.
Action semantics:
  • approve — Promote the memory: clears isInference, so it ranks like a stated fact instead of a down-weighted guess. Stamps reviewStatus: "approved".
  • decline — Reject the suggestion: the memory is forgotten (isForgotten: true) and stamped reviewStatus: "declined", so it leaves both search and the review queue.
  • undo — Revert a prior approve/decline back to the unreviewed inferred state: restores isInference: true, un-forgets the memory (isForgotten: false), and clears the review stamp, so it returns to the queue.

Response

{
  "id": "mem_abc123",
  "isInference": false,
  "isForgotten": false,
  "reviewStatus": "approved"
}
FieldTypeDescription
idstringThe reviewed memory ID
isInferencebooleanfalse after approve; true after decline or undo
isForgottenbooleantrue after decline (the memory is forgotten); false otherwise
reviewStatus"approved" | "declined" | nullThe new status; null after an undo

Errors

StatusWhen
401Missing or invalid authentication
404The container tag or memory was not found in your organization
409The memory isn’t reviewable for this action — it’s not an inferred memory, or there’s no prior review to undo

Building a review experience

The endpoints are designed for an optimistic, one-at-a-time review UI (swipe to keep / decline, with undo). A typical client fetches the queue once, then pops each card off locally as the user decides — undo re-adds it.
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";

const BASE = "https://api.supermemory.ai/v3";
const key = (tag: string) => ["inferred-memories", tag] as const;

export type InferredMemory = {
  id: string;
  memory: string;
  parentCount: number;
  createdAt: string;
  updatedAt: string;
  metadata: Record<string, unknown> | null;
};

export type ReviewAction = "approve" | "decline" | "undo";

export function useInferredMemories(containerTag: string) {
  return useQuery({
    queryKey: key(containerTag),
    queryFn: async (): Promise<InferredMemory[]> => {
      const res = await fetch(`${BASE}/container-tags/${containerTag}/inferred`, {
        headers: { Authorization: `Bearer ${API_KEY}` },
      });
      if (!res.ok) throw new Error("Failed to load review queue");
      const data = await res.json();
      return data.memories ?? [];
    },
    staleTime: 60_000,
  });
}

export function useReviewInferredMemory(containerTag: string) {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: async (vars: { memoryId: string; action: ReviewAction }) => {
      const res = await fetch(
        `${BASE}/container-tags/${containerTag}/inferred/${vars.memoryId}/review`,
        {
          method: "POST",
          headers: {
            Authorization: `Bearer ${API_KEY}`,
            "Content-Type": "application/json",
          },
          body: JSON.stringify({ action: vars.action }),
        },
      );
      if (!res.ok) throw new Error("Review failed");
      return res.json();
    },
    onSuccess: (_data, { memoryId, action }) => {
      // approve/decline remove the card; undo brings it back, so refetch.
      if (action === "undo") {
        queryClient.invalidateQueries({ queryKey: key(containerTag) });
        return;
      }
      queryClient.setQueryData<InferredMemory[]>(key(containerTag), (prev) =>
        prev?.filter((m) => m.id !== memoryId),
      );
    },
  });
}
There is no separate “skip” action. A swipe-to-skip is purely client-side — don’t send a request and the memory simply stays in the queue for a later session.

Next Steps