> For the complete documentation index, see [llms.txt](https://docs.graphlit.dev/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.graphlit.dev/api-guides/use-cases/content/content-ingest-text.md).

# Ingest Text

## Content: Ingest Text

### User Intent

"I want to ingest plain text directly into Graphlit without a file or URL"

### Operation

* **SDK Method**: `graphlit.ingestText()`
* **GraphQL**: `ingestText` mutation
* **Entity Type**: Content
* **Common Use Cases**: User-generated notes, chat messages, API responses, scraped text, clipboard content

### TypeScript (Canonical)

```typescript
import { Graphlit } from 'graphlit-client';
import { ContentState, ObservableTypes } from 'graphlit-client/dist/generated/graphql-types';

const graphlit = new Graphlit();

// Basic text ingestion (synchronous)
const response = await graphlit.ingestText(
  'This is my note about the project meeting. We discussed Q1 goals and timeline.',  // text
  'Meeting Notes - January 2025',  // name
  undefined,  // textType (optional)
  undefined,  // uri (optional - for reference)
  undefined,  // id (optional)
  undefined,  // identifier (optional)
  true,       // isSynchronous
  undefined,  // workflow (optional)
  undefined   // collections (optional)
);

const contentId = response.ingestText.id;
console.log(`Text ingested: ${contentId}`);

// Retrieve the content
const content = await graphlit.getContent(contentId);
console.log(`Content markdown: ${content.content.markdown}`);
```

## Ingest text (snake\_case method)

## Note: Python SDK uses named parameters, order doesn't matter

response = await graphlit.ingestText( text="This is my note about the project meeting.", name="Meeting Notes - January 2025", is\_synchronous=True )

content\_id = response.ingest\_text.id if response.ingest\_text else None

````

**C#**:
```csharp
using Graphlit;

var client = new Graphlit();

// Ingest text (PascalCase method)
var response = await graphlit.IngestText(
    text: "This is my note about the project meeting.",
    name: "Meeting Notes - January 2025",
    isSynchronous: true
);

var contentId = response.IngestText?.Id;
````

### Parameters

#### Required

* **`text`** (string): The text content to ingest
  * Can be plain text or markdown
  * No size limit specified, but keep reasonable for performance

#### Optional

* **`name`** (string): Display name for the content
* **`textType`** (TextTypes): Type hint for the text
  * `PLAIN` - Plain text (default)
  * `MARKDOWN` - Markdown formatted text
* **`uri`** (string): Optional reference URI for the text source
* **`id`** (string): Custom ID for the content
* **`identifier`** (string): Custom identifier for deduplication
* **`isSynchronous`** (boolean): Wait for ingestion to complete
  * **Default**: `false` (asynchronous)
  * **Recommended**: `true` for immediate use
* **`workflow`** (EntityReferenceInput): Workflow to apply during ingestion
* **`collections`** (EntityReferenceInput\[]): Collections to add content to
* **`observations`** (ObservationReferenceInput\[]): Observations to link
* **`correlationId`** (string): For tracking in production systems

### Response

```typescript
{
  ingestText: {
    id: string;              // Content ID
    name: string;            // Name you provided
    state: ContentState;     // FINISHED (if synchronous)
    type: ContentTEXT; // Always TEXT
    markdown: string;        // The ingested text
    textType?: TextTypes;    // PLAIN or MARKDOWN
    uri?: string;            // Reference URI if provided
  }
}
```

### Developer Hints

#### Key Differences from ingestUri

1. **No file parsing needed** - Text is used directly, no extraction step
2. **Immediate availability** - Even with `isSynchronous: false`, text is usually available immediately
3. **No file metadata** - No fileType, mimeType, or file-specific fields
4. **Markdown support** - Can ingest pre-formatted markdown

#### When to Use ingestText vs ingestUri

Use `ingestText` when:

* You already have the text in memory
* Text comes from user input, API, or database
* No file parsing needed
* You want to store snippets, notes, or short content

Use `ingestUri` when:

* Content is in a file (PDF, DOCX, etc.)
* Need file parsing/extraction
* Content is at a URL

#### Understanding isSynchronous

```typescript
// Asynchronous (default) - returns immediately
const response = await graphlit.ingestText(text, name, undefined, undefined, undefined, undefined, false);
// Content ID available immediately, processing happens in background

// Synchronous - waits for processing
const response = await graphlit.ingestText(text, name, undefined, undefined, undefined, undefined, true);
// Returns when content.state === 'FINISHED'
```

**For ingestText, the difference is minimal** since text doesn't require heavy processing. However, if you're using a workflow (e.g., entity extraction), synchronous mode ensures the workflow completes before returning.

### Variations

#### 1. Ingesting with Collections

Organize text into collections during ingestion:

```typescript
// Create a collection first
const collectionResponse = await graphlit.createCollection({
  name: 'Meeting Notes'
});

const collectionId = collectionResponse.createCollection.id;

// Ingest text into collection
const response = await graphlit.ingestText(
  'Discussion about Q1 product roadmap and feature priorities.',
  'Product Planning Meeting',
  undefined,  // textType
  undefined,  // uri
  undefined,  // workflow
  [{ id: collectionId }],  // collections
  true
);
```

#### 2. Ingesting Markdown

Preserve markdown formatting:

```typescript
const markdownText = `
# Project Update

## Completed Tasks
- Feature A implementation
- Bug fixes in module B

## Next Steps
- Code review
- Deployment planning
`;

const response = await graphlit.ingestText(
  markdownText,
  'Weekly Project Update',
  TextTypes.Markdown,  // Specify markdown type
  undefined,
  undefined,
  undefined,
  true
);

// The markdown structure is preserved
const content = await graphlit.getContent(response.ingestText.id);
console.log(content.content.markdown); // Includes formatting
```

#### 3. Ingesting with Entity Extraction

Apply a workflow to extract entities from text:

```typescript
// Create extraction workflow
const workflowInput: WorkflowInput = {
  name: 'Extract People and Orgs',
  extraction: {
    jobs: [
      {
        connector: {
          type: EntityExtractionServiceTypes.ModelText,
          modelText: {
            extractedTypes: [
              ObservableTypes.Person,
              ObservableTypes.Organization
            ]
          }
        }
      }
    ]
  }
};

const workflowResponse = await graphlit.createWorkflow(workflowInput);

// Ingest text with extraction
const response = await graphlit.ingestText(
  'John Smith from Acme Corp discussed the partnership with Jane Doe from TechCo.',
  'Partnership Discussion',
  undefined,
  undefined,
  { id: workflowResponse.createWorkflow.id },  // workflow
  undefined,
  true  // Must be synchronous to wait for extraction
);

// Retrieve with extracted entities
const content = await graphlit.getContent(response.ingestText.id);
console.log(`Extracted ${content.content.observations?.length || 0} entities`);
// Will include Person entities for "John Smith" and "Jane Doe"
// Will include Organization entities for "Acme Corp" and "TechCo"
```

#### 4. Ingesting with Reference URI

Track the source of text:

```typescript
// Text scraped from a web API
const scrapedText = 'Product description from external API...';

const response = await graphlit.ingestText(
  scrapedText,
  'Product Description - Widget A',
  TextTypes.Plain,
  'https://api.example.com/products/widget-a',  // Reference URI
  undefined,
  undefined,
  true
);

// The URI is stored for reference
const content = await graphlit.getContent(response.ingestText.id);
console.log(`Source: ${content.content.uri}`);
```

### Common Issues

**Issue**: Text ingested but not appearing in search\
**Solution**: Ensure embeddings are generated. Check project configuration for embedding model. If using asynchronous mode, wait a few seconds for embedding generation.

**Issue**: Special characters or formatting lost\
**Solution**: Use `textType: TextTypes.Markdown` if your text includes markdown formatting. Plain text is default.

**Issue**: Workflow not executing\
**Solution**: Must use `isSynchronous: true` when applying workflows. Asynchronous mode may return before workflow completes.

**Issue**: Content state is `AWAITING_EXTRACTION`\
**Solution**: Wait for processing to complete if using asynchronous mode. Or switch to synchronous mode.

### Production Example

**From Public Samples**:

```typescript
// Server-side text ingestion with all options
const response = await graphlit.ingestText(
  text,
  name,
  textType as TextTypes | undefined,
  uri,
  workflow ? { id: workflow } : undefined,
  collections?.map((id) => ({ id })),
  isSynchronous
);
```

**Re-ingesting updated text**:

```typescript
// Update content by re-ingesting with same name
const response = await graphlit.ingestText(
  editedText,
  originalName,
  TextTypes.Plain,
  undefined,
  undefined,
  undefined,
  true
);
```
