or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

blog-management.mdclient-setup.mdindex.mdpost-operations.mdtagged-and-generic.mduser-operations.md

post-operations.mddocs/

0

# Post Operations

1

2

Modern NPF (Neue Post Format) post creation, editing, and deletion with media upload support, plus legacy post format methods for backward compatibility.

3

4

## Capabilities

5

6

### NPF Post Creation

7

8

Creates a new post using the modern Neue Post Format with support for media uploads and complex content layouts.

9

10

```javascript { .api }

11

/**

12

* Creates or reblogs an NPF post

13

* @param blogIdentifier - Blog name or URL where the post will be created

14

* @param params - Post content and configuration parameters

15

* @returns Promise resolving to created post information

16

*/

17

createPost(blogIdentifier: string, params: NpfPostParams | NpfReblogParams): Promise<any>;

18

19

interface NpfPostParams {

20

/** An array of NPF content blocks to be used to make the post */

21

content: NpfContentBlock[];

22

/** An array of NPF layout objects to be used to lay out the post content */

23

layout?: NpfLayoutBlock[];

24

/** The initial state of the new post. Defaults to "published" */

25

state?: 'published' | 'queue' | 'draft' | 'private' | 'unapproved';

26

/** The exact future date and time (ISO 8601 format) to publish the post */

27

publish_on?: string;

28

/** The exact date and time (ISO 8601 format) in the past to backdate the post */

29

date?: string;

30

/** Tags to associate with the post */

31

tags?: string[];

32

/** A source attribution for the post content */

33

source_url?: string;

34

/** Whether this should be a private answer, if this is an answer */

35

is_private?: boolean;

36

/** A custom URL slug to use in the post's permalink URL */

37

slug?: string;

38

/** Who can interact with this when reblogging */

39

interactability_reblog?: 'everyone' | 'noone';

40

}

41

42

interface NpfReblogParams extends NpfPostParams {

43

/** The unique public identifier of the Tumblelog that's being reblogged from */

44

parent_tumblelog_uuid: string;

45

/** The unique public post ID being reblogged */

46

parent_post_id: string;

47

/** The unique per-post hash validating that this is a genuine reblog action */

48

reblog_key: string;

49

/** Whether or not to hide the reblog trail with this new post */

50

hide_trail?: boolean;

51

/** Array of specific reblog trail item indexes to exclude from your reblog */

52

exclude_trail_items?: number[];

53

}

54

```

55

56

**Usage Examples:**

57

58

```javascript

59

const fs = require('node:fs');

60

61

// Create a simple text post

62

await client.createPost('myblog', {

63

content: [

64

{

65

type: 'text',

66

text: 'Hello, Tumblr! This is my first NPF post.',

67

},

68

],

69

tags: ['hello', 'first-post'],

70

});

71

72

// Create a post with image upload

73

await client.createPost('myblog', {

74

content: [

75

{

76

type: 'image',

77

media: fs.createReadStream('/path/to/image.jpg'),

78

alt_text: 'A beautiful sunset over the mountains',

79

},

80

{

81

type: 'text',

82

text: 'Amazing sunset from my hike today!',

83

},

84

],

85

tags: ['photography', 'nature'],

86

});

87

88

// Create a scheduled post

89

await client.createPost('myblog', {

90

content: [

91

{

92

type: 'text',

93

text: 'This post is scheduled for the future!',

94

},

95

],

96

state: 'queue',

97

publish_on: '2024-12-25T12:00:00Z',

98

});

99

100

// Reblog a post with additional content

101

await client.createPost('myblog', {

102

content: [

103

{

104

type: 'text',

105

text: 'Great points in this post!',

106

},

107

],

108

parent_tumblelog_uuid: 'original-blog-uuid',

109

parent_post_id: '12345678901',

110

reblog_key: 'AbCdEfGh',

111

});

112

```

113

114

### NPF Post Editing

115

116

Edits an existing NPF post with updated content, layout, or metadata.

117

118

```javascript { .api }

119

/**

120

* Edit an NPF post

121

* @param blogIdentifier - Blog name or URL containing the post

122

* @param postId - The ID of the post to edit

123

* @param params - Updated post content and configuration parameters

124

* @returns Promise resolving to updated post information

125

*/

126

editPost(blogIdentifier: string, postId: string, params: NpfPostParams | NpfReblogParams): Promise<any>;

127

```

128

129

**Usage Examples:**

130

131

```javascript

132

// Edit post content

133

await client.editPost('myblog', '12345678901', {

134

content: [

135

{

136

type: 'text',

137

text: 'Updated content for this post!',

138

},

139

],

140

tags: ['updated', 'edited'],

141

});

142

143

// Update post tags only

144

await client.editPost('myblog', '12345678901', {

145

content: [], // Keep existing content

146

tags: ['new-tag', 'another-tag'],

147

});

148

149

// Change post state

150

await client.editPost('myblog', '12345678901', {

151

content: [], // Keep existing content

152

state: 'draft', // Move to drafts

153

});

154

```

155

156

### Post Deletion

157

158

Permanently deletes a post from a blog.

159

160

```javascript { .api }

161

/**

162

* Deletes a given post

163

* @param blogIdentifier - Blog name or URL containing the post

164

* @param postId - The ID of the post to delete

165

* @returns Promise resolving when deletion completes

166

*/

167

deletePost(blogIdentifier: string, postId: string): Promise<any>;

168

```

169

170

**Usage Examples:**

171

172

```javascript

173

// Delete a post

174

await client.deletePost('myblog', '12345678901');

175

176

// Delete multiple posts

177

const postsToDelete = ['12345678901', '12345678902', '12345678903'];

178

for (const postId of postsToDelete) {

179

await client.deletePost('myblog', postId);

180

}

181

```

182

183

### Legacy Post Creation (Deprecated)

184

185

Creates a post using the legacy post format. This method is deprecated in favor of NPF methods.

186

187

```javascript { .api }

188

/**

189

* Creates a post on the given blog using legacy format

190

* @deprecated Legacy post creation methods are deprecated. Use NPF methods.

191

* @param blogIdentifier - Blog name or URL

192

* @param params - Legacy post parameters

193

* @returns Promise resolving to created post information

194

*/

195

createLegacyPost(blogIdentifier: string, params: Record<string, any>): Promise<any>;

196

```

197

198

**Usage Examples:**

199

200

```javascript

201

// Create legacy text post (deprecated - use createPost instead)

202

await client.createLegacyPost('myblog', {

203

type: 'text',

204

title: 'My Post Title',

205

body: 'This is the post body content.',

206

tags: 'tag1,tag2,tag3',

207

});

208

209

// Create legacy photo post (deprecated)

210

await client.createLegacyPost('myblog', {

211

type: 'photo',

212

caption: 'Photo caption',

213

source: 'https://example.com/image.jpg',

214

});

215

```

216

217

### Legacy Post Editing (Deprecated)

218

219

Edits a post using the legacy post format. This method is deprecated in favor of NPF methods.

220

221

```javascript { .api }

222

/**

223

* Edits a given post using legacy format

224

* @deprecated Legacy post creation methods are deprecated. Use NPF methods.

225

* @param blogIdentifier - Blog name or URL

226

* @param params - Legacy post parameters including post ID

227

* @returns Promise resolving when edit completes

228

*/

229

editLegacyPost(blogIdentifier: string, params: Record<string, any>): Promise<any>;

230

```

231

232

**Usage Examples:**

233

234

```javascript

235

// Edit legacy post (deprecated - use editPost instead)

236

await client.editLegacyPost('myblog', {

237

id: '12345678901',

238

title: 'Updated Post Title',

239

body: 'Updated post body content.',

240

});

241

```

242

243

### Legacy Post Reblogging (Deprecated)

244

245

Reblogs a post using the legacy post format. This method is deprecated in favor of NPF methods.

246

247

```javascript { .api }

248

/**

249

* Reblogs a given post using legacy format

250

* @deprecated Legacy post creation methods are deprecated. Use NPF methods.

251

* @param blogIdentifier - Blog name or URL

252

* @param params - Legacy reblog parameters

253

* @returns Promise resolving when reblog completes

254

*/

255

reblogPost(blogIdentifier: string, params: Record<string, any>): Promise<any>;

256

```

257

258

**Usage Examples:**

259

260

```javascript

261

// Reblog post (deprecated - use createPost with reblog params instead)

262

await client.reblogPost('myblog', {

263

id: '12345678901',

264

reblog_key: 'AbCdEfGh',

265

comment: 'Great post!',

266

});

267

```

268

269

## NPF Content Block Types

270

271

```javascript { .api }

272

// Content block type union

273

type NpfContentBlock = AudioBlock | ImageBlock | LinkBlock | PaywallBlock | TextBlock | VideoBlock;

274

275

// Text content block

276

interface TextBlock {

277

type: 'text';

278

text?: string;

279

subtype?: 'heading1' | 'heading2' | 'quirky' | 'quote' | 'indented' | 'chat' | 'ordered-list-item' | 'unordered-list-item';

280

[prop: string]: any;

281

}

282

283

// Image content block with media upload support

284

interface ImageBlock {

285

type: 'image';

286

media: ReadStream | MediaObject;

287

alt_text?: string;

288

caption?: string;

289

[prop: string]: any;

290

}

291

292

// Video content block with media upload support

293

interface VideoBlock {

294

type: 'video';

295

media: ReadStream | MediaObject;

296

[prop: string]: any;

297

}

298

299

// Audio content block with media upload support

300

interface AudioBlock {

301

type: 'audio';

302

media: ReadStream | MediaObject;

303

title?: string;

304

artist?: string;

305

album?: string;

306

[prop: string]: any;

307

}

308

309

// Link content block

310

interface LinkBlock {

311

type: 'link';

312

url?: string;

313

title?: string;

314

description?: string;

315

author?: string;

316

site_name?: string;

317

display_url?: string;

318

poster?: MediaObject[];

319

[prop: string]: any;

320

}

321

322

// Paywall content block

323

interface PaywallBlock {

324

type: 'paywall';

325

text?: string;

326

title?: string;

327

url?: string;

328

[prop: string]: any;

329

}

330

331

// Media object for referencing existing media

332

interface MediaObject {

333

url: string;

334

type?: string;

335

width?: number;

336

height?: number;

337

original_dimensions_missing?: boolean;

338

has_original_dimensions?: boolean;

339

cropped?: boolean;

340

}

341

```

342

343

## NPF Layout Block Types

344

345

```javascript { .api }

346

// Layout block type union

347

type NpfLayoutBlock = NpfLayoutAsk | NpfLayoutRows;

348

349

// Ask layout for question/answer posts

350

interface NpfLayoutAsk {

351

type: 'ask';

352

blocks: readonly number[];

353

attribution: {

354

type: 'user' | 'blog' | 'link' | 'app';

355

url?: string;

356

name?: string;

357

avatar?: MediaObject[];

358

};

359

}

360

361

// Rows layout for organizing content blocks

362

interface NpfLayoutRows {

363

type: 'rows';

364

display: readonly {

365

blocks: readonly number[];

366

mode?: {

367

type: 'carousel' | 'photoset';

368

};

369

}[];

370

truncate_after?: 1;

371

}

372

```

373

374

## Media Upload Support

375

376

NPF posts support media uploads through Node.js ReadStream objects:

377

378

```javascript

379

const fs = require('node:fs');

380

381

// Upload image from file system

382

await client.createPost('myblog', {

383

content: [

384

{

385

type: 'image',

386

media: fs.createReadStream('./photo.jpg'),

387

alt_text: 'Description of the image',

388

},

389

],

390

});

391

392

// Upload video

393

await client.createPost('myblog', {

394

content: [

395

{

396

type: 'video',

397

media: fs.createReadStream('./video.mp4'),

398

},

399

],

400

});

401

402

// Upload audio

403

await client.createPost('myblog', {

404

content: [

405

{

406

type: 'audio',

407

media: fs.createReadStream('./song.mp3'),

408

title: 'Song Title',

409

artist: 'Artist Name',

410

},

411

],

412

});

413

```

414

415

## Authentication Requirements

416

417

All post operations require OAuth authentication with all four credentials:

418

- `consumer_key`

419

- `consumer_secret`

420

- `token`

421

- `token_secret`

422

423

Additionally, you must have posting permissions for the specified blog.