OutLayer Documentation

HTTPS API

Call OutLayer projects via simple HTTP requests without NEAR transactions. Authentication uses Payment Keys with prepaid USD stablecoin balance.

Overview#

NEAR Transactions

  • Payment: NEAR tokens
  • Latency: ~2-3 seconds
  • Response: callback to contract

HTTPS API

  • Payment: USD stablecoins
  • Latency: instant (sync mode)
  • Response: HTTP response body
# Simple example
curl -X POST https://api.outlayer.io/call/alice.near/my-assistant \
  -H "X-Payment-Key: bob.near:0:K7xR2mN9pQs5vW3yZ8bF..." \
  -H "Content-Type: application/json" \
  -d '{"input": {"prompt": "Hello!"}}'

Request Format#

Endpoint#

POST https://api.outlayer.io/call/{project_owner}/{project_name}

Example: POST https://api.outlayer.io/call/alice.near/weather-api

Request Headers#

HeaderRequiredDefaultDescription
X-Payment-KeyYes-Format: owner:nonce:secret
Authentication for the API call
X-Compute-LimitNo10000Max compute budget in USD micro-units
10000 = $0.01, 100000 = $0.10
X-Attached-DepositNo0Payment to project author in USD micro-units
1000000 = $1.00. Goes to author's earnings.
Content-TypeNoapplication/jsonRequest body format

X-Attached-Deposit vs X-Compute-Limit:

  • X-Compute-Limit - pays for infrastructure (OutLayer), refunded if unused
  • X-Attached-Deposit - pays the project author, charged immediately

Request Body#

{
  "input": {                    // Required - passed to WASM as stdin
    "prompt": "Hello, AI!",
    "temperature": 0.7
  },
  "resource_limits": {          // Optional - override project defaults
    "max_instructions": 10000000000,
    "max_memory_mb": 128,
    "max_execution_seconds": 60
  },
  "async": false                // Optional - sync (default) or async mode
}
FieldTypeRequiredDescription
inputobjectYesPassed to WASM code as JSON via stdin
resource_limitsobjectNoOverride project's default limits
asyncbooleanNofalse = wait for result, true = return call_id immediately

Resource Limits#

LimitDefaultMaximumDescription
max_instructions1 billion500 billionWASM instructions to execute
max_memory_mb128 MB512 MBMemory available to WASM
max_execution_seconds60 sec180 secWall-clock timeout

Response Format#

Synchronous Response (default)#

When async: false (default), the request waits until execution completes:

// Success
{
  "call_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "completed",
  "output": "Here's the weather forecast for...",
  "compute_cost": "45000",
  "job_id": 12345,
  "attestation_url": "https://outlayer.io/attestations/12345"
}

// Failure
{
  "call_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "failed",
  "error": "Execution timeout after 60 seconds",
  "compute_cost": "100000",
  "job_id": 12345
}

Asynchronous Response#

When async: true, the request returns immediately with a call_id for polling:

// Initial response
{
  "call_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "pending",
  "poll_url": "https://api.outlayer.io/calls/550e8400-e29b-41d4-a716-446655440000"
}

Poll the result using GET /calls/{call_id}:

curl -H "X-Payment-Key: bob.near:0:..." \
  https://api.outlayer.io/calls/550e8400-e29b-41d4-a716-446655440000

Response Fields#

FieldTypeDescription
call_idUUIDUnique identifier for this API call
statusstring"pending", "completed", or "failed"
outputanyWASM stdout (only when completed)
errorstringError message (only when failed)
compute_coststringActual USD cost in micro-units (e.g., "45000" = $0.045). Charged even on failure.
job_idnumberInternal job ID for attestation lookup
attestation_urlstringLink to TEE attestation (completed only)

Environment Variables in WASM#

Your WASM code can detect the execution context and access payment information via environment variables. Values differ between NEAR transactions and HTTPS API calls:

VariableNEARHTTPS
OUTLAYER_EXECUTION_TYPE"NEAR""HTTPS"
NEAR_SENDER_IDTransaction signerPayment Key owner
USD_PAYMENT"0"X-Attached-Deposit value
NEAR_PAYMENT_YOCTOAttached NEAR"0"
OUTLAYER_CALL_ID""call_id UUID
NEAR_TRANSACTION_HASHTransaction hash""
NEAR_BLOCK_HEIGHTBlock number""
NEAR_BLOCK_TIMESTAMPBlock timestamp""
OUTLAYER_PROJECT_IDowner/name (same for both)

Detecting Execution Mode#

let execution_type = std::env::var("OUTLAYER_EXECUTION_TYPE")
    .unwrap_or_else(|_| "NEAR".to_string());

match execution_type.as_str() {
    "HTTPS" => {
        // HTTPS API call
        let usd_payment: u64 = std::env::var("USD_PAYMENT")
            .unwrap_or_else(|_| "0".to_string())
            .parse()
            .unwrap_or(0);

        let call_id = std::env::var("OUTLAYER_CALL_ID").unwrap_or_default();
        let cost = usd_payment as f64 / 1_000_000.0;
        println!("HTTPS call {}: paid {} USD", call_id, cost);
    }
    "NEAR" => {
        // NEAR transaction
        let near_payment: u128 = std::env::var("NEAR_PAYMENT_YOCTO")
            .unwrap_or_else(|_| "0".to_string())
            .parse()
            .unwrap_or(0);

        let tx_hash = std::env::var("NEAR_TRANSACTION_HASH").unwrap_or_default();
        println!("NEAR tx {}: paid {} yoctoNEAR", tx_hash, near_payment);
    }
    _ => {}
}

Checking Payment (USD)#

// USD_PAYMENT is in micro-units: 1000000 = $1.00
let usd_payment: u64 = std::env::var("USD_PAYMENT")
    .unwrap_or_else(|_| "0".to_string())
    .parse()
    .unwrap_or(0);

// Require $0.10 minimum for premium features
const MIN_PREMIUM_USD: u64 = 100_000; // $0.10

if usd_payment >= MIN_PREMIUM_USD {
    // Premium feature
    expensive_ai_analysis();
} else if usd_payment > 0 {
    // Basic paid feature
    basic_analysis();
} else {
    // Free tier
    simple_response();
}

Error Codes#

CodeStatusDescription
400Bad RequestInvalid request body or headers
401UnauthorizedInvalid or missing Payment Key
402Payment RequiredInsufficient balance on Payment Key
403ForbiddenProject not allowed for this key
404Not FoundProject does not exist
429Too Many RequestsRate limit exceeded (IP or key)
500Internal ErrorServer error during execution
504Gateway TimeoutExecution timeout (300s max)

Code Examples#

cURL#

# Basic call
curl -X POST https://api.outlayer.io/call/alice.near/weather-api \
  -H "X-Payment-Key: bob.near:0:K7xR2mN9pQs5vW3yZ8bF..." \
  -H "Content-Type: application/json" \
  -d '{"input": {"city": "Tokyo"}}'

# With compute limit and author payment
curl -X POST https://api.outlayer.io/call/alice.near/premium-api \
  -H "X-Payment-Key: bob.near:0:K7xR2mN9pQs5vW3yZ8bF..." \
  -H "X-Compute-Limit: 500000" \
  -H "X-Attached-Deposit: 100000" \
  -H "Content-Type: application/json" \
  -d '{"input": {"query": "complex analysis"}}'

# Async mode
curl -X POST https://api.outlayer.io/call/alice.near/long-running \
  -H "X-Payment-Key: bob.near:0:K7xR2mN9pQs5vW3yZ8bF..." \
  -H "Content-Type: application/json" \
  -d '{"input": {...}, "async": true}'

JavaScript / TypeScript#

async function callOutLayer(projectId: string, input: object) {
  const response = await fetch(`https://api.outlayer.io/call/${projectId}`, {
    method: 'POST',
    headers: {
      'X-Payment-Key': process.env.OUTLAYER_PAYMENT_KEY!,
      'X-Compute-Limit': '100000', // $0.10 max
      'X-Attached-Deposit': '50000', // $0.05 to author
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ input }),
  });

  if (!response.ok) {
    throw new Error(`OutLayer error: ${response.status}`);
  }

  const result = await response.json();

  if (result.status === 'failed') {
    throw new Error(`Execution failed: ${result.error}`);
  }

  const costUsd = Number(result.compute_cost) / 1_000_000;
  console.log('Cost:', costUsd, 'USD');
  return result.output;
}

// Usage
const weather = await callOutLayer('alice.near/weather-api', { city: 'Tokyo' });

Python#

import os
import requests

def call_outlayer(project_id: str, input_data: dict) -> dict:
    """Call an OutLayer project via HTTPS API."""
    response = requests.post(
        f"https://api.outlayer.io/call/{project_id}",
        headers={
            "X-Payment-Key": os.environ["OUTLAYER_PAYMENT_KEY"],
            "X-Compute-Limit": "100000",  # $0.10 max
            "X-Attached-Deposit": "50000",  # $0.05 to author
            "Content-Type": "application/json",
        },
        json={"input": input_data},
    )
    response.raise_for_status()

    result = response.json()
    if result["status"] == "failed":
        raise Exception(f"Execution failed: {result['error']}")

    cost = int(result['compute_cost']) / 1_000_000
    print(f"Cost: {cost} USD")
    return result["output"]

# Usage
weather = call_outlayer("alice.near/weather-api", {"city": "Tokyo"})

Pricing#

HTTPS API calls are charged in USD stablecoins based on actual resource consumption:

compute_cost = base_fee_usd
  + (instructions / 1M) × per_million_instructions_usd
  + execution_time_ms × per_ms_usd
  + compile_time_ms × per_compile_ms_usd

See Pricing & Limits for current rates. Key points:

  • compute_cost - charged based on actual resources used
  • X-Attached-Deposit - charged immediately, goes to project author
  • Minimum: X-Compute-Limit must be at least $0.001 (1000)
  • Failures: you still pay for resources used before the failure

Related Documentation