Skip to content

Developer docs

Resources

Register what you have — knowledge, links, ad and store accounts, data sources, integrations — and plug it into products so the AI marketer can use it.

A resource (자산) is something the workspace owns: a brand guide, a Notion page, a GA4 property, a database, an API key, an MCP server, a Claude Code setup, a webhook. You plug resources into products; one resource can serve several products, and a product can have many. The AI marketer reads the knowledge resources of the product it is working on, and connected accounts become the product's channels.

CategoryKinds
KNOWLEDGETEXT (notes, brand guide, FAQ) · LINK (Notion, Google Docs, Figma, YouTube…) · FILE
ACCOUNTAd and social accounts — META_ADS, GOOGLE_ADS, NAVER_SEARCH_ADS, INSTAGRAM, YOUTUBE, … (the same kinds as channels)
DATAGA4, FIREBASE, APPSFLYER, MIXPANEL, AMPLITUDE, DATABASE, Google Sheets
INTEGRATIONAPI_KEY, MCP_SERVER, CLAUDE_CODE, WEBHOOK

Endpoints

EndpointBody / query → result
GET /v1/resources?workspaceId=&category=&q=ResourceDto[] — every resource of the workspace with productIds[], connection status and a text preview
GET /v1/resources/graph?workspaceId=&productId={ products, resources, links } — the whole map in one call
POST /v1/resources{ workspaceId, input?, kind?, title?, summary?, body?, url?, secret?, meta?, tags?, productIds? } → ResourceDto
GET /v1/resources/{id}ResourceDetailDto — plus the full body and products[] (how each one is linked: explicit link or via a connected channel)
PATCH /v1/resources/{id}{ title?, summary?, body?, url?, secret?, meta?, tags? }. secret: null removes a stored secret
DELETE /v1/resources/{id}Members for knowledge; admin for a connected account
POST /v1/resources/{id}/products{ productId, role?, note? } — plug in (role: context · channel · source)
DELETE /v1/resources/{id}/products/{productId}Unplug
GET /v1/products/{id}/resourcesResources of one product

Paste anything

Pass whatever the user pasted as input and leave kind out: Poremu detects a URL (and the site — Notion, Google Docs, GitHub, Figma, YouTube…), a database connection string, an API token (OpenAI, GitHub, Slack, Google, Meta, AWS, Stripe… prefixes) or plain text, and files the right kind. Secrets are stored encrypted and never returned — the DTO only carries hasSecret and a masked secretHint.

bash
curl https://api.poremu.ai/v1/resources \
  -H "Authorization: Bearer $POREMU_API_KEY" -H "Content-Type: application/json" \
  -d '{"workspaceId":"my-workspace","input":"https://www.notion.so/lumo/Brand-guide-3f1…","productIds":["PRODUCT_ID"]}'
json
{ "id": "…", "category": "KNOWLEDGE", "kind": "LINK", "title": "Brand guide", "url": "https://www.notion.so/…", "meta": { "site": "notion" }, "hasSecret": false, "productIds": ["PRODUCT_ID"], "status": null }

A longer text goes in body (markdown, up to 200,000 characters) — the AI marketer reads up to 12,000 characters of it per call, so put the essentials first.

Connected accounts

Ad and analytics accounts are resources too, but they are created through the connector flow — GET /v1/connectors, the OAuth start URL or POST /v1/connections — and appear here with their connectionId, status (CONNECTED · NEEDS_REAUTH · ERROR), lastSyncAt and lastError. Plugging one into a product creates the product channel. See Marketing API → Channels.

Revenue sources

To see ROAS on real revenue instead of what the ad platforms attribute to themselves, create a resource with kind: "REVENUE" and plug it into the product. The response's revenueHookUrl is its webhook URL. It is shown only this once. Have your shop, payments or Zapier post each order there. No auth header is needed, because the token is the credential.

EndpointBody / query → result
POST /v1/hooks/{token}One order { orderId, amount, occurredAt? } or { events: [...] } → { ok, action: "REVENUE", count }
POST /v1/resources/{id}/revenueWith an API key: { events: [{ externalId?, amount, currency?, occurredAt?, orders?, productId?, refund?, note? }] } (max 500) → { ok, count }
GET /v1/resources/{id}/revenue?from=&to=Period total, daily rows, latest 50 rows, webhook status
POST /v1/resources/{id}/revenue/hookNew webhook URL (the old one stops at once)
DELETE /v1/resources/{id}/revenue/{eventId}Delete a row

The same externalId (also read from orderId, order_id, id) overwrites, so retries are safe. A bare YYYY-MM-DD in occurredAt records a daily total for that day (Korea time), and orders carries the order count. Send refunds as a negative amount or refund: true. Currencies are not converted.

bash
curl -X POST https://api.poremu.ai/v1/resources/RESOURCE_ID/revenue \
  -H "Authorization: Bearer $POREMU_API_KEY" -H "Content-Type: application/json" \
  -d '{"events":[{"orderId":"A-1001","amount":129000},{"date":"2026-11-04","amount":3200000,"orders":42}]}'

Products with a revenue source plugged in compute home revenue, orders and ROAS from these rows. Platform-reported revenue stays as ad_revenue.

Over MCP

list_resources, get_resource and add_resource give an assistant the same view. add_resource only accepts text and links: an assistant must never collect a key or password — ask the user to register it in the app, where it is encrypted on arrival.