Skip to content

Past Blog API

Endpoints for managing past blog articles (old_blog) targeted for migration. Registered past blogs are the input for AI rewriting (blog_rewriter); the results are stored in blog.

Past blog schema

Field Type Notes
id string _id
race_id string | null _id of the linked race; not every past blog has one
race_type enum | null auto_racing / bicycle_racing / horse_racing
blog_type string | null Series type (e.g. jockey interview, Saito column)
category string | null Broad category (e.g. interview, race recap, prediction). Stored as a string
source_url string | null URL of the source blog article
published_at number | null Publish time of the source article. UNIX timestamp (ms)
name string Title
body_html string HTML body from the source
created_at number UNIX timestamp (ms)
updated_at number UNIX timestamp (ms)

embedding is not returned

The embedding vector is kept internally and never included in API responses.


POST /v1/old_blogs

Overview

Registers a past blog article.

On registration, "category + title + body (tags stripped)" is flattened to text and embedded with Amazon Bedrock Titan Text Embeddings v2. That vector is carried over to blog on rewrite and used for related-blog search.

Embedding is supplementary: if it fails, registration still succeeds (embedding stays unset).

Request and Response

Headers

Request

  • Content-Type: application/json

Response

  • Content-Type: application/json

URI

POST /v1/old_blogs

Request body

{
  "name": "string",
  "body_html": "string",
  "race_id": "string",
  "race_type": "horse_racing",
  "blog_type": "string",
  "category": "string",
  "source_url": "string",
  "published_at": 1234567890000
}
Field Type Required Notes
name string โ—ฏ Title
body_html string โ—ฏ HTML body
race_id string _id of the linked race
race_type enum auto_racing / bicycle_racing / horse_racing
blog_type string Series type
category string Broad category; used by blog_builder to pick the article template
source_url string Source URL; also the base for absolutizing relative image src values
published_at number Source publish time. UNIX timestamp (ms)

Response

201 Created โ€” returns the past blog schema.

Error handling

Description Status code Status
Invalid request body 422 Unprocessable Entity
Internal server error 500 Internal Server Error

Processing flow

flowchart TD
    Start([POST /v1/old_blogs]) --> Embed[Embed category + title + body]
    Embed -->|failure| Save[Store without a vector]
    Embed -->|success| Save2[Store with the vector]
    Save --> Success[201 Created]
    Save2 --> Success

GET /v1/old_blogs

Overview

Lists past blog articles.

URI

GET /v1/old_blogs

Query parameters

Parameter Type Required Notes
race_id string Filter by race
page number Page number. Default: 1
size number Items per page. Default: 10
order enum asc / desc (by updated_at). Default: desc

Response

200 OK

{
  "list": [
    {
      "id": "string",
      "race_id": "string",
      "race_type": "horse_racing",
      "blog_type": null,
      "category": "ใƒฌใƒผใ‚นๅ›ž้กง",
      "source_url": "string",
      "published_at": 1234567890000,
      "name": "string",
      "body_html": "string",
      "created_at": 1234567890000,
      "updated_at": 1234567890000
    }
  ],
  "current_page": 1,
  "total_count": 10
}

GET /v1/old_blogs/{old_blog_id}

Overview

Fetches a single past blog article.

Response

200 OK โ€” returns the past blog schema.

Error handling

Description Status code Status
Past blog not found 404 Not Found
Internal server error 500 Internal Server Error

PUT /v1/old_blogs/{old_blog_id}

Overview

Updates only the category of a past blog article.

Because the embedding is generated with the category included, changing the category regenerates the vector. If regeneration fails, the existing vector is kept and the update proceeds.

If the category is unchanged, nothing is written and the current record is returned.

URI

PUT /v1/old_blogs/{old_blog_id}

Request body

{
  "category": "string"
}
Field Type Required Notes
category string Broad category

Response

200 OK โ€” returns the updated past blog schema.

Error handling

Description Status code Status
Past blog not found 404 Not Found
Internal server error 500 Internal Server Error

No DELETE

There is no delete endpoint for past blogs.


POST /v1/old_blogs/{old_blog_id}/rewrite

Overview

Starts a rewrite of the given past blog.

A blog is created in generating state and a job is dispatched to the blog_rewriter Lambda over SQS (the blog-rewriter queue). The new blog inherits:

Field Source
name old_blog.name
race_id old_blog.race_id, falling back to the request's race_id
race_type old_blog.race_type, otherwise resolved by looking up the race
blog_type old_blog.blog_type
source_url old_blog.source_url
category_id A category record whose name matches old_blog.category; no category if none matches
embedding old_blog.embedding

When the blog is not tied to a race, race video / race result analysis is skipped and only a content-preserving rewrite is performed.

URI

POST /v1/old_blogs/{old_blog_id}/rewrite
Path parameter Type Notes
old_blog_id string old_blog._id

Request body

{
  "race_id": "string"
}
Field Type Required Notes
race_id string Race _id to use when old_blog.race_id is unset. The body itself may be omitted

Response

202 Accepted

{
  "id": "string"
}
Field Type Notes
id string _id of the created blog

Error handling

Description Status code Status
Past blog not found 404 Not Found
race_id given but the race does not exist 404 Not Found
Internal server error 500 Internal Server Error

Processing flow

flowchart TD
    Start([POST /v1/old_blogs/old_blog_id/rewrite]) --> Fetch[Fetch the past blog]
    Fetch -->|not found| E404[404 Not Found]
    Fetch -->|found| Race[Resolve race linkage]
    Race --> Category[Resolve category_id from the category name]
    Category --> Save[Save blog as generating]
    Save --> SendSQS[Send to blog-rewriter queue]
    SendSQS --> Success[202 Accepted]
    SendSQS -.->|async| Rewrite[blog_rewriter rewrites the body]
    Rewrite -.-> Build[blog_builder builds and stores the HTML]
    Build -.-> Draft[status becomes draft]