API Reference

Webhooks

Webhooks let your application receive real-time HTTP callbacks when events occur in your Outfame account. Instead of polling the API, register a URL and Outfame will send a POST request with event data as it happens.

Scope requiredwebhooks:manage


Events

EventDescriptionTrigger
account.growth_milestoneAccount reached a follower milestone (100, 500, 1K, 5K, 10K, etc.).Follower count crosses a milestone threshold.
account.status_changedAccount status transitioned (e.g., setup to active, active to paused).Any status change on a connected account.
account.flaggedAccount was flagged for unusual activity or a potential issue.Outfame detects a risk that requires attention.
engagement.daily_summaryEnd-of-day summary of all engagement actions performed.Sent daily at 23:55 UTC for each active account.
targeting.suggestions_readyNew AI targeting suggestions are available.AI model generates new recommendations (typically weekly).
billing.payment_succeededA subscription payment was processed successfully.Recurring or one-time payment completes.
billing.payment_failedA payment attempt failed.Card declined, insufficient funds, etc.

Create a webhook

POST /v1/webhooks

Body parameters

ParameterTypeRequiredDescription
urlstringYesThe HTTPS endpoint to receive webhook events.
eventsstring[]YesArray of event types to subscribe to. Use ["*"] for all events.
descriptionstringNoHuman-readable description for this webhook.
metadataobjectNoArbitrary key-value pairs for your reference.

Request

curl -X POST https://api.outfame.com/v1/webhooks \
  -H "Authorization: Bearer sk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://yourapp.com/webhooks/outfame",
    "events": [
      "account.growth_milestone",
      "engagement.daily_summary",
      "account.flagged"
    ],
    "description": "Production growth notifications"
  }'

Response 201 Created

{
  "id": "wh_4nRtYuIo",
  "url": "https://yourapp.com/webhooks/outfame",
  "events": [
    "account.growth_milestone",
    "engagement.daily_summary",
    "account.flagged"
  ],
  "description": "Production growth notifications",
  "signing_secret": "whsec_5f8a2b3c4d5e6f7g8h9i0j...",
  "active": true,
  "created_at": "2026-02-09T14:30:00Z"
}

Important — The signing_secret is only returned on creation. Store it securely; you will need it to verify webhook signatures.


List webhooks

GET /v1/webhooks

Request

curl https://api.outfame.com/v1/webhooks \
  -H "Authorization: Bearer sk_live_your_api_key"

Response

{
  "data": [
    {
      "id": "wh_4nRtYuIo",
      "url": "https://yourapp.com/webhooks/outfame",
      "events": ["account.growth_milestone", "engagement.daily_summary", "account.flagged"],
      "description": "Production growth notifications",
      "active": true,
      "last_delivery_at": "2026-02-09T12:00:00Z",
      "last_delivery_status": 200,
      "created_at": "2026-02-09T14:30:00Z"
    }
  ]
}

Delete a webhook

DELETE /v1/webhooks/:id

Request

curl -X DELETE https://api.outfame.com/v1/webhooks/wh_4nRtYuIo \
  -H "Authorization: Bearer sk_live_your_api_key"

Response 200 OK

{
  "id": "wh_4nRtYuIo",
  "deleted": true
}

Webhook payload

Every webhook delivery is a POST request with a JSON body following this structure:

{
  "id": "evt_xYz789AbC",
  "type": "account.growth_milestone",
  "created_at": "2026-02-09T14:30:00Z",
  "data": {
    "account_id": "acc_7Gx2kLm9Qr",
    "instagram_username": "yourhandle",
    "milestone": 15000,
    "previous_milestone": 10000,
    "current_followers": 15023,
    "days_since_last_milestone": 42
  }
}

Event-specific payloads

engagement.daily_summary

{
  "id": "evt_aBc123DeF",
  "type": "engagement.daily_summary",
  "created_at": "2026-02-09T23:55:00Z",
  "data": {
    "account_id": "acc_7Gx2kLm9Qr",
    "date": "2026-02-09",
    "actions": {
      "likes": 148,
      "follows": 58,
      "comments": 19,
      "story_views": 195
    },
    "total_actions": 420,
    "new_followers": 47,
    "new_unfollowers": 3,
    "net_growth": 44,
    "engagement_rate": 4.21,
    "avg_quality_score": 0.86
  }
}

account.flagged

{
  "id": "evt_gHi456JkL",
  "type": "account.flagged",
  "created_at": "2026-02-09T10:15:00Z",
  "data": {
    "account_id": "acc_7Gx2kLm9Qr",
    "flag_type": "unusual_activity",
    "severity": "warning",
    "message": "Higher than normal unfollow rate detected. Engagement has been automatically reduced.",
    "recommended_action": "Review your targeting configuration and consider narrowing filters."
  }
}

Signature verification

Every webhook request includes an X-Outfame-Signature header containing an HMAC-SHA256 signature. Always verify this signature to ensure the request is genuine.

Verification algorithm

  1. Extract the X-Outfame-Signature header value.
  2. Extract the X-Outfame-Timestamp header value.
  3. Concatenate: timestamp + "." + raw_body
  4. Compute HMAC-SHA256 using your webhook's signing_secret.
  5. Compare the computed signature with the header value (use constant-time comparison).

Node.js

import crypto from "crypto";

function verifyWebhookSignature(payload, signature, timestamp, secret) {
  const signedPayload = timestamp + "." + payload;
  const expected = crypto
    .createHmac("sha256", secret)
    .update(signedPayload)
    .digest("hex");

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

// In your webhook handler
app.post("/webhooks/outfame", (req, res) => {
  const signature = req.headers["x-outfame-signature"];
  const timestamp = req.headers["x-outfame-timestamp"];
  const isValid = verifyWebhookSignature(
    JSON.stringify(req.body),
    signature,
    timestamp,
    process.env.OUTFAME_WEBHOOK_SECRET
  );

  if (!isValid) {
    return res.status(401).json({ error: "Invalid signature" });
  }

  // Process the event
  const event = req.body;
  console.log("Received:", event.type);

  res.status(200).json({ received: true });
});

Python

import hmac
import hashlib

def verify_signature(payload: str, signature: str, timestamp: str, secret: str) -> bool:
    signed_payload = f"{timestamp}.{payload}"
    expected = hmac.new(
        secret.encode(),
        signed_payload.encode(),
        hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(signature, expected)

Retry policy

If your endpoint returns a non-2xx status code or times out, Outfame retries the delivery using exponential backoff.

AttemptDelay after failure
1st retry1 minute
2nd retry5 minutes
3rd retry30 minutes

After 3 failed attempts, the delivery is marked as failed. You can view failed deliveries in the dashboard under Settings → Webhooks → Delivery history.

If an endpoint fails consistently (10+ consecutive failures across any events), the webhook is automatically disabled and you receive an email notification.


Best practices

  • Respond quickly — Return a 200 within 5 seconds. Process the event asynchronously.
  • Handle duplicates — Use the id field to deduplicate. Events may be delivered more than once.
  • Verify signatures — Always validate X-Outfame-Signature before processing.
  • Check timestamps — Reject events with timestamps older than 5 minutes to prevent replay attacks.
  • Use HTTPS — Webhook URLs must use HTTPS. HTTP endpoints are rejected.

Error codes

StatusCodeDescription
400invalid_urlURL must be a valid HTTPS endpoint.
400invalid_eventsOne or more event types are not recognized.
409duplicate_urlA webhook with this URL already exists.
403webhook_limit_reachedMaximum webhook limit reached for your plan (Basic: 2, Pro: 10, Turbo: 50).