OG Awesome API
Generate beautiful 1200×630 Open Graph images on-the-fly via a simple POST API.
Overview
OG Awesome exposes four theme-specific POST endpoints. Call an endpoint from your server, receive a { "url": "..." } JSON response, and use that CDN URL directly as your og:image.
- Returns a CDN URL — fast worldwide delivery
- Same params on repeat requests return the cached URL instantly
- Optional
downloadflag — receive the raw PNG binary instead of JSON - API key passed via
x-api-keyheader — never exposed in URLs - Requires an active Pro subscription
Quick Start
- 1. Get your API key
Subscribe to Pro, then go to Dashboard → API Keys to create a key.
- 2. POST to an endpoint
curl -X POST https://ogawesome.com/og \ -H "Content-Type: application/json" \ -H "x-api-key: YOUR_API_KEY" \ -d '{ "title": "Hello World", "template": "gradient" }' - 3. Use the returned URL
// Response: { "url": "https://./og-images/abc123.png" } // Add to your HTML: <meta property="og:image" content="https://./og-images/abc123.png" />
npm SDK — og-awesome
Instead of calling the API with raw fetch, you can use the official type-safe Node.js / Edge SDK. It works in Next.js, Node.js, and any Edge Runtime.
Latest version: 0.1.10
Install
npm install og-awesome # or pnpm add og-awesome
Initialise
import { OgAwesome } from 'og-awesome'
const og = new OgAwesome({ apiKey: process.env.OG_API_KEY })Default theme
const { url } = await og.default({
title: 'Hello World',
template: 'gradient',
font: 'FunnelSans',
weight: '700',
})Blog theme
const { url } = await og.blog({
title: 'TypeScript Tips You Need to Know',
subtitle: 'Level up your type safety.',
author: 'Jane Doe',
siteName: 'Dev Weekly',
titleFontSize: 68,
subtitleFontSize: 34,
authorFontSize: 24,
siteNameFontSize: 20,
authorImage: 'https://example.com/avatar.jpg',
template: 'dark',
})Product theme
const { url } = await og.product({
productName: 'Acme Widget Pro',
tagline: 'The fastest widget on the market.',
brandName: 'Acme Corp',
titleFontSize: 72,
subtitleFontSize: 34,
authorFontSize: 28,
image: product.imageUrl, // required
template: 'split',
})Profile theme
const { url } = await og.profile({
name: 'Jane Doe',
jobTitle: 'Senior Engineer',
company: 'Acme Corp',
titleFontSize: 72,
subtitleFontSize: 34,
authorFontSize: 26,
image: 'https://example.com/jane.jpg',
template: 'dark',
})Download PNG directly
Pass download: true to receive an ArrayBuffer instead of a URL. TypeScript narrows the return type automatically.
const buffer = await og.blog({ title: 'My Post', download: true })
// buffer is ArrayBuffer — write to disk, pipe to response, etc.Error handling
import { OgAwesome, OgAwesomeError } from 'og-awesome'
try {
const { url } = await og.blog({ title: 'My Post' })
} catch (err) {
if (err instanceof OgAwesomeError) {
console.error(err.status, err.body)
// e.g. 401, { error: 'Invalid API key' }
}
throw err
}Next.js generateMetadata
// app/blog/[slug]/page.tsx
import { OgAwesome } from 'og-awesome'
import type { Metadata } from 'next'
const og = new OgAwesome({ apiKey: process.env.OG_API_KEY })
export async function generateMetadata({ params }): Promise<Metadata> {
const post = await getPost(params.slug)
const { url } = await og.blog({
title: post.title,
subtitle: post.excerpt,
author: post.authorName,
siteName: 'My Blog',
template: 'dark',
})
return {
openGraph: { images: [{ url, width: 1200, height: 630 }] },
twitter: { card: 'summary_large_image', images: [url] },
}
}baseUrl and fetch), and the complete README are available on npmjs.com/package/og-awesome.Endpoints
Each theme has its own endpoint. All require x-api-key and a JSON body.
Default Theme — /og
General-purpose OG cards. Supports 10 background templates.
Parameters
| Field | Required | Default | Description |
|---|---|---|---|
| title | — | Main heading. Max 100 chars. | |
| subtitle | No | "" | Subheading / description. Alias: desc. Max 200 chars. |
| author | No | "" | Author or site name shown at bottom. Max 40 chars. |
| titleFontSize | No | theme-based | Title font size. Range: 12–160. |
| subtitleFontSize | No | theme-based | Subtitle font size. Range: 12–160. |
| authorFontSize | No | theme-based | Author font size. Range: 12–160. |
| template | No | gradient | Background template key. See list below. |
| font | No | Roboto | Font key. See Fonts section. |
| weight | No | 400 | "400" for regular, "700" for bold (if font supports it). |
| style | No | normal | "normal" or "italic" (if font supports it). |
| download | No | false | true → returns raw PNG binary instead of { url }. |
Templates
gradientIndigo → Purple (default)
indigoFlat indigo
sunsetOrange → Pink
oceanSky → Indigo
auroraTeal & Violet glows
crimsonDeep red
midnightDeep navy
roseRose → Deep rose
darkDark (near-black)
lightWhite / light
Blog Theme — /og/blog
Designed for articles and blog posts. Displays title, excerpt, author name, avatar, and site name.
Parameters
| Field | Required | Default | Description |
|---|---|---|---|
| title | — | Post title. Max 100 chars. | |
| subtitle | No | "" | Excerpt / description. Alias: desc. Max 200 chars. |
| author | No | "" | Author name. Max 40 chars. |
| siteName | No | "" | Site / publication name shown at top. Max 40 chars. |
| titleFontSize | No | theme-based | Title font size. Range: 12–160. |
| subtitleFontSize | No | theme-based | Subtitle font size. Range: 12–160. |
| authorFontSize | No | theme-based | Author font size. Range: 12–160. |
| siteNameFontSize | No | theme-based | Site name font size. Range: 12–160. |
| authorImage | No | "" | Author avatar URL (https://). Shown in classic & dark templates. |
| template | No | classic | "classic" | "dark" | "minimal" |
| font | No | Roboto | Font key. See Fonts section. |
| weight | No | 400 | "400" or "700". |
| style | No | normal | "normal" or "italic". |
| download | No | false | true → returns raw PNG binary. |
Templates
classicWhite bg, gradient accent bar, author avatar
darkNear-black bg, indigo accent, author avatar
minimalClean white, large typography, author line
Example
curl -X POST https://ogawesome.com/og/blog \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_API_KEY" \
-d '{
"title": "10 Tips for Better TypeScript",
"subtitle": "Level up your type safety with these practical patterns.",
"author": "Jane Doe",
"siteName": "My Dev Blog",
"titleFontSize": 68,
"subtitleFontSize": 34,
"authorFontSize": 24,
"siteNameFontSize": 20,
"authorImage": "https://example.com/avatar.jpg",
"template": "dark",
"font": "FunnelSans"
}'Product Theme — /og/product
Showcase your product with name, tagline, brand, and product image. The image field is required.
Parameters
| Field | Required | Default | Description |
|---|---|---|---|
| productName | — | Product name. Max 100 chars. | |
| tagline | No | "" | Tagline / description. Max 200 chars. |
| brandName | No | "" | Brand / company name. Max 40 chars. |
| titleFontSize | No | theme-based | Product name font size. Range: 12–160. |
| subtitleFontSize | No | theme-based | Tagline font size. Range: 12–160. |
| authorFontSize | No | theme-based | Brand name font size. Range: 12–160. |
| image | — | Product image. https:// URL or data:image/ base64. | |
| template | No | split | "split" | "feature" | "card" |
| font | No | Roboto | Font key. See Fonts section. |
| weight | No | 400 | "400" or "700". |
| style | No | normal | "normal" or "italic". |
| download | No | false | true → returns raw PNG binary. |
Templates
splitText left, product image right (default)
featureDark bg, full right-half image, text on left
cardCentered card with image above title
Example
curl -X POST https://ogawesome.com/og/product \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_API_KEY" \
-d '{
"productName": "Acme Widget Pro",
"tagline": "The fastest widget on the market.",
"brandName": "Acme Corp",
"titleFontSize": 72,
"subtitleFontSize": 34,
"authorFontSize": 28,
"image": "https://example.com/product.png",
"template": "split",
"font": "SNPro",
"weight": "700"
}'Profile Theme — /og/profile
Personal or team member cards. Use name, jobTitle, and company as the canonical fields.
Parameters
| Field | Required | Default | Description |
|---|---|---|---|
| name | — | Person's full name. Max 100 chars. | |
| jobTitle | No | "" | Job title / role. Max 200 chars. |
| company | No | "" | Company / organisation name. Max 40 chars. |
| titleFontSize | No | theme-based | Name font size. Range: 12–160. |
| subtitleFontSize | No | theme-based | Job title font size. Range: 12–160. |
| authorFontSize | No | theme-based | Company font size. Range: 12–160. |
| image | No | "" | Profile photo. https:// URL. Falls back to initials avatar. |
| template | No | gradient | "gradient" | "dark" | "card" | "neon" | "minimal" |
| font | No | Roboto | Font key. See Fonts section. |
| weight | No | 400 | "400" or "700". |
| style | No | normal | "normal" or "italic". |
| download | No | false | true → returns raw PNG binary. |
Templates
gradientIndigo → purple gradient bg with avatar (default)
darkNear-black bg with gradient ring around avatar
cardLight card with subtle shadow
neonDark bg with neon accent lines
minimalClean white, large name, small job title
Example
curl -X POST https://ogawesome.com/og/profile \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_API_KEY" \
-d '{
"name": "Jane Doe",
"jobTitle": "Senior Engineer",
"company": "Acme Corp",
"titleFontSize": 72,
"subtitleFontSize": 34,
"authorFontSize": 26,
"image": "https://example.com/jane.jpg",
"template": "dark",
"font": "Roboto",
"weight": "700"
}'Fonts
Pass one of the following font keys to the font parameter. Available across all four endpoints.
| Key | Display Name | Bold | Italic |
|---|---|---|---|
| Alegreya | Alegreya | ||
| AlegreyaSans | Alegreya Sans | ||
| AoboshiOne | Aoboshi Oneーにほんご | — | — |
| ArchivoNarrow | Archivo Narrow | ||
| BioRhyme | BioRhyme | — | |
| BitcountPropDouble | Bitcount Prop | — | |
| BIZUDPGothic | BIZ UDP Gothicーにほんご | — | |
| Cardo | Cardo | — | |
| Chivo | Chivo | ||
| Cormorant | Cormorant | ||
| DelaGothicOne | Dela Gothic Oneーにほんご | — | — |
| DMSans | DM Sans | ||
| Eczar | Eczar | — | |
| FiraSans | Fira Sans | ||
| FunnelSans | Funnel Sans | ||
| HinaMincho | Hina Minchoーにほんご | — | — |
| IBMPlexSans | IBM Plex Sans | ||
| Inconsolata | Inconsolata | — | |
| InknutAntiqua | Inknut Antiqua | — | |
| KaiseiDecol | Kaisei Decolーにほんご | — | |
| KaiseiOpti | Kaisei Optiーにほんご | — | |
| Karla | Karla | ||
| KiwiMaru | Kiwi Maruーにほんご | — | — |
| KleeOne | Klee Oneーにほんご | — | |
| Kosugi | Kosugiーにほんご | — | — |
| KosugiMaru | Kosugi Maruーにほんご | — | — |
| Lato | Lato | ||
| LibreBaskerville | Libre Baskerville | — | — |
| LibreFranklin | Libre Franklin | ||
| Lora | Lora | ||
| Manrope | Manrope | — | |
| MeaCulpa | Mea Culpa | — | — |
| Merriweather | Merriweather | ||
| MochiyPopOne | Mochiy Pop Oneーにほんご | — | — |
| Montserrat | Montserrat | ||
| MPLUS1p | M PLUS 1pーにほんご | — | |
| MPLUSRounded1c | M PLUS Rounded 1cーにほんご | — | |
| Neuton | Neuton | — | |
| NotoSansJP | Noto Sans JPーにほんご | — | |
| NotoSerifJP | Noto Serif JPーにほんご | — | |
| OpenSans | Open Sans | ||
| Pacifico | Pacifico | — | — |
| PirataOne | Pirata One | — | — |
| PlayfairDisplay | Playfair Display | ||
| Poppins | Poppins | ||
| ProzaLibre | Proza Libre | ||
| PTSans | PT Sans | ||
| PTSerif | PT Serif | ||
| Raleway | Raleway | ||
| Roboto | Roboto | ||
| Rubik | Rubik | ||
| SawarabiGothic | Sawarabi Gothicーにほんご | — | — |
| SawarabiMincho | Sawarabi Minchoーにほんご | — | — |
| ShipporiMincho | Shippori Minchoーにほんご | — | |
| SNPro | SN Pro | ||
| SourceSans3 | Source Sans 3 | ||
| SourceSerif4 | Source Serif 4 | ||
| SpaceGrotesk | Space Grotesk | — | |
| SpaceMono | Space Mono | ||
| Spectral | Spectral | ||
| Syne | Syne | — | |
| WorkSans | Work Sans | ||
| Yomogi | Yomogiーにほんご | — | — |
| YuseiMagic | Yusei Magicーにほんご | — | — |
| ZenKakuGothicNew | Zen Kaku Gothic Newーにほんご | — | |
| ZenKurenaido | Zen Kurenaidoーにほんご | — | — |
| ZenMaruGothic | Zen Maru Gothicーにほんご | — | |
| ZenOldMincho | Zen Old Minchoーにほんご | — |
If a font file for the requested weight/style is not found, the server silently falls back to the Regular variant.
Authentication
All API requests require a Pro subscription and a valid API key passed in the x-api-key request header.
POST https://ogawesome.com/og
Content-Type: application/json
x-api-key: ogas_xxxxxxxxxxxx
{ "title": "My Title" }To create an API key:
- Subscribe to a Pro plan at Pricing
- Go to Dashboard → API Keys
- Click Create new key and copy the key (shown only once)
Plans & Limits
| Feature | Free | Pro / Pro Annual |
|---|---|---|
| Web generator | ||
| Wordpress plugin | ||
| API access (all 4 endpoints) | ||
| All themes & templates | Default only | |
| Watermark | (shown) | (removed) |
| CDN cached images | ||
| Image history (Dashboard) | — |
Code Examples
SDK — Default theme
import { OgAwesome } from 'og-awesome'
const og = new OgAwesome({ apiKey: process.env.OG_API_KEY })
const { url } = await og.default({
title: 'My Post Title',
subtitle: 'Short description here',
titleFontSize: 72,
subtitleFontSize: 34,
template: 'gradient',
font: 'FunnelSans',
weight: '700',
})
// => url: "https://...cloudfront.net/og-images/abc123.png"SDK — Next.js generateMetadata (Blog theme)
// app/blog/[slug]/page.tsx
import { OgAwesome } from 'og-awesome'
import type { Metadata } from 'next'
const og = new OgAwesome({ apiKey: process.env.OG_API_KEY })
export async function generateMetadata({ params }): Promise<Metadata> {
const post = await getPost(params.slug)
const { url } = await og.blog({
title: post.title,
subtitle: post.excerpt,
author: post.authorName,
siteName: 'My Blog',
titleFontSize: 68,
subtitleFontSize: 34,
authorFontSize: 24,
siteNameFontSize: 20,
authorImage: post.authorAvatarUrl,
template: 'dark',
font: 'FunnelSans',
})
return {
openGraph: { images: [{ url, width: 1200, height: 630 }] },
twitter: { card: 'summary_large_image', images: [url] },
}
}SDK — Product theme
const { url } = await og.product({
productName: 'Acme Widget Pro',
tagline: 'The fastest widget on the market.',
brandName: 'Acme Corp',
titleFontSize: 72,
subtitleFontSize: 34,
authorFontSize: 28,
image: product.imageUrl, // required
template: 'split',
font: 'SNPro',
weight: '700',
})SDK — Profile theme
const { url } = await og.profile({
name: 'Jane Doe',
jobTitle: 'Senior Engineer',
company: 'Acme Corp',
titleFontSize: 72,
subtitleFontSize: 34,
authorFontSize: 26,
image: 'https://example.com/jane.jpg',
template: 'dark',
})SDK — Download PNG directly
// download: true → returns ArrayBuffer (TypeScript narrows automatically)
const buffer = await og.blog({ title: 'My Post', download: true })
// buffer instanceof ArrayBuffer === truecurl — Default theme (raw API)
curl -X POST https://ogawesome.com/og \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_API_KEY" \
-d '{
"title": "My Post Title",
"subtitle": "Short description here",
"template": "gradient",
"font": "FunnelSans",
"weight": "700"
}'
# => { "url": "https://./og-images/abc123.png" }fetch — Blog theme (raw API)
const res = await fetch('https://ogawesome.com/og/blog', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': process.env.OG_API_KEY,
},
body: JSON.stringify({
title: 'My Post',
template: 'dark',
download: true,
}),
})
// res.headers['Content-Type'] => 'image/png'
// res.body => raw PNG binaryError Codes
| Status | Message | Cause |
|---|---|---|
| 400 | Invalid JSON body | Request body is not valid JSON |
| 400 | Invalid title | title is missing or exceeds 100 characters |
| 400 | Invalid subtitle | subtitle exceeds 200 characters |
| 400 | Invalid author | author exceeds 40 characters |
| 400 | image is required (product only) | /og/product — image field missing or invalid URL |
| 401 | Missing API key | x-api-key header not provided |
| 401 | Invalid API key | x-api-key does not match any active key |
| 403 | Pro subscription required | Account does not have an active Pro subscription |
| 422 | Failed to load product image | /og/product — could not fetch the provided image URL |
| 502 | Failed to upload image to storage | S3 upload failed (contact support) |
| 503 | Service unavailable | CDN / S3 not configured on the server |