Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .actor/actor.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"actorSpecification": 1,
"name": "actor-openrouter-proxy",
"title": "OpenRouter Proxy",
"description": "Proxy with pay per event pricing",
"version": "0.0",
"name": "openrouter",
"title": "OpenRouter",
"description": "You can use any AI LLM model without accounts in AI providers. Use this Actor as a proxy for all requests. Use pay-per-event pricing to pay only for the real credit used.",
"version": "1.0",
"buildTag": "latest",
"usesStandbyMode": true,
"meta": {
Expand Down
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ This Apify Actor creates a proxy for the Open Router API, allowing you to access
- **Transparent billing**: Charges are applied to your Apify account at the same rates as Open Router
- **Full feature support**: Supports both streaming and non-streaming responses
- **No API key management**: Uses your Apify token for authentication - no need to manage separate Open Router API keys
- **Standby mode**: Actor runs in standby mode only and has a static URL address, like a standard web server.

## Pricing

This Actor uses a pay-per-event pricing model through Apify. Each API request counts as one event. The underlying Open Router API costs are included in the per-event pricing, plus a 10% fee to cover the cost of running the proxy server.
This Actor uses a pay-per-event pricing model through Apify. Each API request counts as one event, and no additional fees are applied beyond the standard Apify event pricing.

## Quick start

Expand All @@ -28,7 +29,7 @@ npm install openai
import OpenAI from 'openai';

const openai = new OpenAI({
baseURL: 'https://michal-kalita--openrouter-proxy.apify.actor/api/v1',
baseURL: 'https:/openrouter.apify.actor/api/v1',
apiKey: 'no-key-required-but-must-not-be-empty', // Any non-empty string works; do NOT use a real API key.
defaultHeaders: {
Authorization: `Bearer ${process.env.APIFY_TOKEN}`, // Apify token is loaded automatically in runtime
Expand Down Expand Up @@ -74,6 +75,7 @@ for await (const chunk of stream) {
## Available models

This proxy supports all models available through Open Router from providers including:

- OpenAI
- Anthropic
- Google
Expand Down
9 changes: 5 additions & 4 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ server.register(FastifyProxy, {
}

let jsonString;
const isStream = response.startsWith('data:') || response.startsWith(': OPENROUTER PROCESSING');
// Stream must start with 'data:', but it's allowd to send just ":" to keep the connection alive
const isStream = response.startsWith('data:') || response.startsWith(':');
if (isStream) {
request.log.info('Stream response mode');
const lines = response.split('\n').filter((line) => line.trim());
Expand All @@ -109,9 +110,9 @@ server.register(FastifyProxy, {
return;
}

const costWithFee = cost * 1.1; // Add 10% fee
const count = Math.max(Math.round(costWithFee / 0.0001), 1);
request.log.info({ originalCost: cost, costWithFee }, `Charging $0.0001 x ${count} times`);
// The Apify platform doesn't have a function for dynamic pricing. The price is calculated as a count of $0.0001 charges.
const count = Math.max(Math.round(cost / 0.0001), 1);
request.log.info({ cost }, `Charging $0.0001 x ${count} times`);

await Actor.charge({ eventName: 'credit-0-0001', count });
},
Expand Down
Loading