ROI and value

Embed
Preview of the card
<a href="https://referalli.com/docs/ref-roi-and-value"><img src="https://referalli.com/docs/_api/public/orgs/07f432f4-34b9-46a7-aaad-c0e395d2e4f9/spaces/2bf4f614-3630-4fbf-85f9-5ecafa6b7d97/pages/27770594-206f-4856-b9c8-3a3cf2cbbd94/social-card.svg?v=3e7ae33eec8b" alt="ROI and value" width="600" height="315"></a>
GEThttps://referalli.com/v1/profitability/settings
Get profitability settings

The economics credit ROI is computed with: reporting currency, default margin, how a credit's cost is modelled, how credit use is inferred, attribution and churn windows, target ROI and more. With programId, the program's overrides merged over the org's.

Auth: an API key with analytics:read (or full), or a session of any role.

Parameters
programIdstringquery
x-org-idstringheader
With a session: the org to act in (the user must be a member). Not used with API keys, which belong to one org.
referalli-modestringheader
test runs a session request against the org's test data. With an API key it must match the key's mode (400 mode_mismatch otherwise). The header name from before the rename is still accepted.
live | test
Code samples
cURL
curl -X GET "https://referalli.com/v1/profitability/settings?programId=" \
  -H "x-org-id: <value>" \
  -H "referalli-mode: <value>"
TypeScript
const res = await fetch('https://referalli.com/v1/profitability/settings?programId=', {
  method: 'GET',
  headers: {
    'x-org-id': '<value>',
    'referalli-mode': '<value>',
  },
});
const data = await res.json();
Python
import requests

res = requests.request(
    "GET",
    "https://referalli.com/v1/profitability/settings?programId=",
    headers={
    "x-org-id": "<value>",
    "referalli-mode": "<value>",
    },
)
data = res.json()
Go
package main

import (
	"fmt"
	"io"
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://referalli.com/v1/profitability/settings?programId=", nil)
	req.Header.Set("x-org-id", "<value>")
	req.Header.Set("referalli-mode", "<value>")
	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)
	fmt.Println(string(body))
}
PHP
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://referalli.com/v1/profitability/settings?programId=');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['x-org-id: <value>', 'referalli-mode: <value>']);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
Ruby
require 'net/http'
require 'uri'

uri = URI('https://referalli.com/v1/profitability/settings?programId=')
req = Net::HTTP::Get.new(uri)
req['x-org-id'] = '<value>'
req['referalli-mode'] = '<value>'
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
  http.request(req)
end
puts res.body
Java
import java.net.URI;
import java.net.http.*;
import java.net.http.HttpRequest.BodyPublishers;

HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://referalli.com/v1/profitability/settings?programId="))
    .header("x-org-id", "<value>")
    .header("referalli-mode", "<value>")
    .GET()
    .build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
Responses
200 OK
Example
{
  "reportingCurrency": "string",
  "defaultMarginBps": 0,
  "creditCostModel": "face",
  "creditCostRatioBps": 0,
  "inference": "fifo_next_payments",
  "creditDraw": "grants_first",
  "windowDays": 0,
  "churnWindowDays": 0,
  "countReferrerSpend": true,
  "costToServeMinorPerMonth": 0,
  "taxFeesReduceProfit": true,
  "valuePatternWeight": 0,
  "targetRoiBps": 0
}
Schema
reportingCurrencystringrequired
defaultMarginBpsintegerrequired
creditCostModelstringrequired
face | margin | fixed_ratio
creditCostRatioBpsinteger
inferencestringrequired
fifo_next_payments | report_only | on_grant
creditDrawstringrequired
grants_first | pro_rata
windowDaysnumberrequired
churnWindowDaysintegerrequired
countReferrerSpendbooleanrequired
costToServeMinorPerMonthinteger
taxFeesReduceProfitbooleanrequired
valuePatternWeightnumberrequired
targetRoiBpsinteger
Target ROI as a multiple in bps (20000 = 2.0x); unset or null = no target.
400 The request is invalid. error.code is one of:
Example
{
  "error": {
    "code": "validation_error",
    "message": "the body or query failed validation, an unknown field was sent, the body is not valid json, or a session call has no `x-org-id`",
    "details": [
      {
        "code": "invalid_format",
        "path": [
          "destinationUrl"
        ],
        "message": "Invalid URL"
      }
    ],
    "docs_url": "https://referalli.com/docs/errors-and-limits#validation_error"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
401 Missing or invalid credentials. error.code is one of:
Example
{
  "error": {
    "code": "unauthorized",
    "message": "no credentials, an unknown, revoked or expired api key or session, or a signature that did not verify",
    "docs_url": "https://referalli.com/docs/errors-and-limits#unauthorized"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
403 Authenticated, but not allowed. error.code is one of:
Example
{
  "error": {
    "code": "forbidden",
    "message": "the wrong role, a key without the needed scope (the message names it), not a member, a suspended org, or a publishable key from an origin it does not allow",
    "docs_url": "https://referalli.com/docs/errors-and-limits#forbidden"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
404 No such resource. error.code is one of:
Example
{
  "error": {
    "code": "not_found",
    "message": "the resource does not exist in this org (ids from other orgs look the same), a referenced id does not exist, a list cursor is not in the list, or the endpoint does not exist",
    "docs_url": "https://referalli.com/docs/errors-and-limits#not_found"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
429 Rate limited. error.code is one of:
Example
{
  "error": {
    "code": "rate_limited",
    "message": "an endpoint limit or the per-key quota was exceeded",
    "docs_url": "https://referalli.com/docs/errors-and-limits#rate_limited"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
500 Unexpected server error. error.code is one of:
Example
{
  "error": {
    "code": "internal_error",
    "message": "retry with backoff",
    "requestId": "req_8f2c1d4e5a6b7c8d",
    "docs_url": "https://referalli.com/docs/errors-and-limits#internal_error"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
default Any other error, in the same envelope.
Example
{
  "error": {
    "code": "string",
    "message": "string",
    "details": {},
    "requestId": "string",
    "docs_url": "string"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
PUThttps://referalli.com/v1/profitability/settings
Update profitability settings

Changes the org's economics settings, or with programId that program's overrides (a program can't override org-only fields such as the reporting currency). Returns the resolved settings. Re-run POST /v1/profitability/rebuild to apply changes to past figures. Audited.

Auth: an API key with analytics:write (or full), or a session with role owner, admin.

Parameters
Idempotency-Keystringheader
Any unique string up to 255 printable ASCII characters (a UUID). A retry with the same key within 24 hours gets the first response again (with idempotent-replayed: true) and nothing runs twice. The same key on a different request is 422 idempotency_key_reused; while the first is still running, 409 idempotency_in_progress.
x-org-idstringheader
With a session: the org to act in (the user must be a member). Not used with API keys, which belong to one org.
referalli-modestringheader
test runs a session request against the org's test data. With an API key it must match the key's mode (400 mode_mismatch otherwise). The header name from before the rename is still accepted.
live | test
Request body application/json
reportingCurrencystring
defaultMarginBpsinteger
creditCostModelstring
face | margin | fixed_ratio
creditCostRatioBpsinteger
inferencestring
fifo_next_payments | report_only | on_grant
creditDrawstring
grants_first | pro_rata
windowDaysnumber
churnWindowDaysinteger
countReferrerSpendboolean
costToServeMinorPerMonthinteger
taxFeesReduceProfitboolean
valuePatternWeightnumber
= 0
targetRoiBpsinteger
programIdstring
{
  "reportingCurrency": "string",
  "defaultMarginBps": 0,
  "creditCostModel": "face",
  "creditCostRatioBps": 0,
  "inference": "fifo_next_payments",
  "creditDraw": "grants_first",
  "windowDays": 0,
  "churnWindowDays": 0,
  "countReferrerSpend": true,
  "costToServeMinorPerMonth": 0,
  "taxFeesReduceProfit": true,
  "valuePatternWeight": 0,
  "targetRoiBps": 0,
  "programId": "string"
}
Code samples
cURL
curl -X PUT "https://referalli.com/v1/profitability/settings" \
  -H "Idempotency-Key: <value>" \
  -H "x-org-id: <value>" \
  -H "referalli-mode: <value>" \
  -H "Content-Type: application/json" \
  -d '{"reportingCurrency":"string","defaultMarginBps":0,"creditCostModel":"face","creditCostRatioBps":0,"inference":"fifo_next_payments","creditDraw":"grants_first","windowDays":0,"churnWindowDays":0,"countReferrerSpend":true,"costToServeMinorPerMonth":0,"taxFeesReduceProfit":true,"valuePatternWeight":0,"targetRoiBps":0,"programId":"string"}'
TypeScript
const res = await fetch('https://referalli.com/v1/profitability/settings', {
  method: 'PUT',
  headers: {
    'Idempotency-Key': '<value>',
    'x-org-id': '<value>',
    'referalli-mode': '<value>',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({"reportingCurrency":"string","defaultMarginBps":0,"creditCostModel":"face","creditCostRatioBps":0,"inference":"fifo_next_payments","creditDraw":"grants_first","windowDays":0,"churnWindowDays":0,"countReferrerSpend":true,"costToServeMinorPerMonth":0,"taxFeesReduceProfit":true,"valuePatternWeight":0,"targetRoiBps":0,"programId":"string"}),
});
const data = await res.json();
Python
import requests

res = requests.request(
    "PUT",
    "https://referalli.com/v1/profitability/settings",
    headers={
    "Idempotency-Key": "<value>",
    "x-org-id": "<value>",
    "referalli-mode": "<value>",
    "Content-Type": "application/json",
    },
    json={"reportingCurrency": "string", "defaultMarginBps": 0, "creditCostModel": "face", "creditCostRatioBps": 0, "inference": "fifo_next_payments", "creditDraw": "grants_first", "windowDays": 0, "churnWindowDays": 0, "countReferrerSpend": True, "costToServeMinorPerMonth": 0, "taxFeesReduceProfit": True, "valuePatternWeight": 0, "targetRoiBps": 0, "programId": "string"},
)
data = res.json()
Go
package main

import (
	"fmt"
	"io"
	"net/http"
	"strings"
)

func main() {
	req, _ := http.NewRequest("PUT", "https://referalli.com/v1/profitability/settings", strings.NewReader(`{"reportingCurrency":"string","defaultMarginBps":0,"creditCostModel":"face","creditCostRatioBps":0,"inference":"fifo_next_payments","creditDraw":"grants_first","windowDays":0,"churnWindowDays":0,"countReferrerSpend":true,"costToServeMinorPerMonth":0,"taxFeesReduceProfit":true,"valuePatternWeight":0,"targetRoiBps":0,"programId":"string"}`))
	req.Header.Set("Idempotency-Key", "<value>")
	req.Header.Set("x-org-id", "<value>")
	req.Header.Set("referalli-mode", "<value>")
	req.Header.Set("Content-Type", "application/json")
	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)
	fmt.Println(string(body))
}
PHP
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://referalli.com/v1/profitability/settings');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Idempotency-Key: <value>', 'x-org-id: <value>', 'referalli-mode: <value>', 'Content-Type: application/json']);
curl_setopt($ch, CURLOPT_POSTFIELDS, '{"reportingCurrency":"string","defaultMarginBps":0,"creditCostModel":"face","creditCostRatioBps":0,"inference":"fifo_next_payments","creditDraw":"grants_first","windowDays":0,"churnWindowDays":0,"countReferrerSpend":true,"costToServeMinorPerMonth":0,"taxFeesReduceProfit":true,"valuePatternWeight":0,"targetRoiBps":0,"programId":"string"}');
$response = curl_exec($ch);
curl_close($ch);
echo $response;
Ruby
require 'net/http'
require 'uri'

uri = URI('https://referalli.com/v1/profitability/settings')
req = Net::HTTP::Put.new(uri)
req['Idempotency-Key'] = '<value>'
req['x-org-id'] = '<value>'
req['referalli-mode'] = '<value>'
req['Content-Type'] = 'application/json'
req.body = '{"reportingCurrency":"string","defaultMarginBps":0,"creditCostModel":"face","creditCostRatioBps":0,"inference":"fifo_next_payments","creditDraw":"grants_first","windowDays":0,"churnWindowDays":0,"countReferrerSpend":true,"costToServeMinorPerMonth":0,"taxFeesReduceProfit":true,"valuePatternWeight":0,"targetRoiBps":0,"programId":"string"}'
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
  http.request(req)
end
puts res.body
Java
import java.net.URI;
import java.net.http.*;
import java.net.http.HttpRequest.BodyPublishers;

HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://referalli.com/v1/profitability/settings"))
    .header("Idempotency-Key", "<value>")
    .header("x-org-id", "<value>")
    .header("referalli-mode", "<value>")
    .header("Content-Type", "application/json")
    .method("PUT", BodyPublishers.ofString("{\"reportingCurrency\":\"string\",\"defaultMarginBps\":0,\"creditCostModel\":\"face\",\"creditCostRatioBps\":0,\"inference\":\"fifo_next_payments\",\"creditDraw\":\"grants_first\",\"windowDays\":0,\"churnWindowDays\":0,\"countReferrerSpend\":true,\"costToServeMinorPerMonth\":0,\"taxFeesReduceProfit\":true,\"valuePatternWeight\":0,\"targetRoiBps\":0,\"programId\":\"string\"}"))
    .build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
Responses
200 The resolved settings after the change. Stored ROI figures are not recomputed: grants and referrals pick the change up on their next value refresh, so run POST /v1/profitability/rebuild to apply it to past ones.
Example
{
  "reportingCurrency": "string",
  "defaultMarginBps": 0,
  "creditCostModel": "face",
  "creditCostRatioBps": 0,
  "inference": "fifo_next_payments",
  "creditDraw": "grants_first",
  "windowDays": 0,
  "churnWindowDays": 0,
  "countReferrerSpend": true,
  "costToServeMinorPerMonth": 0,
  "taxFeesReduceProfit": true,
  "valuePatternWeight": 0,
  "targetRoiBps": 0
}
Schema
reportingCurrencystringrequired
defaultMarginBpsintegerrequired
creditCostModelstringrequired
face | margin | fixed_ratio
creditCostRatioBpsinteger
inferencestringrequired
fifo_next_payments | report_only | on_grant
creditDrawstringrequired
grants_first | pro_rata
windowDaysnumberrequired
churnWindowDaysintegerrequired
countReferrerSpendbooleanrequired
costToServeMinorPerMonthinteger
taxFeesReduceProfitbooleanrequired
valuePatternWeightnumberrequired
targetRoiBpsinteger
Target ROI as a multiple in bps (20000 = 2.0x); unset or null = no target.
400 The request is invalid. error.code is one of:
Example
{
  "error": {
    "code": "validation_error",
    "message": "the body or query failed validation, an unknown field was sent, the body is not valid json, or a session call has no `x-org-id`",
    "details": [
      {
        "code": "invalid_format",
        "path": [
          "destinationUrl"
        ],
        "message": "Invalid URL"
      }
    ],
    "docs_url": "https://referalli.com/docs/errors-and-limits#validation_error"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
401 Missing or invalid credentials. error.code is one of:
Example
{
  "error": {
    "code": "unauthorized",
    "message": "no credentials, an unknown, revoked or expired api key or session, or a signature that did not verify",
    "docs_url": "https://referalli.com/docs/errors-and-limits#unauthorized"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
403 Authenticated, but not allowed. error.code is one of:
Example
{
  "error": {
    "code": "forbidden",
    "message": "the wrong role, a key without the needed scope (the message names it), not a member, a suspended org, or a publishable key from an origin it does not allow",
    "docs_url": "https://referalli.com/docs/errors-and-limits#forbidden"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
404 No such resource. error.code is one of:
Example
{
  "error": {
    "code": "not_found",
    "message": "the resource does not exist in this org (ids from other orgs look the same), a referenced id does not exist, a list cursor is not in the list, or the endpoint does not exist",
    "docs_url": "https://referalli.com/docs/errors-and-limits#not_found"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
409 The request conflicts with the current state. error.code is one of:
Example
{
  "error": {
    "code": "conflict",
    "message": "a unique value is taken, or the action would break a rule (the message says which)",
    "docs_url": "https://referalli.com/docs/errors-and-limits#conflict"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
422 The request cannot be processed as sent. error.code is one of:
Example
{
  "error": {
    "code": "idempotency_key_reused",
    "message": "the `idempotency-key` was used for a different request",
    "docs_url": "https://referalli.com/docs/errors-and-limits#idempotency_key_reused"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
429 Rate limited. error.code is one of:
Example
{
  "error": {
    "code": "rate_limited",
    "message": "an endpoint limit or the per-key quota was exceeded",
    "docs_url": "https://referalli.com/docs/errors-and-limits#rate_limited"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
500 Unexpected server error. error.code is one of:
Example
{
  "error": {
    "code": "internal_error",
    "message": "retry with backoff",
    "requestId": "req_8f2c1d4e5a6b7c8d",
    "docs_url": "https://referalli.com/docs/errors-and-limits#internal_error"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
default Any other error, in the same envelope.
Example
{
  "error": {
    "code": "string",
    "message": "string",
    "details": {},
    "requestId": "string",
    "docs_url": "string"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
GEThttps://referalli.com/v1/profitability/products
List product margins

The margin catalog: per product, a margin (bps) or a unit cost, used to turn revenue into profit.

Auth: an API key with analytics:read (or full), or a session of any role.

Parameters
x-org-idstringheader
With a session: the org to act in (the user must be a member). Not used with API keys, which belong to one org.
referalli-modestringheader
test runs a session request against the org's test data. With an API key it must match the key's mode (400 mode_mismatch otherwise). The header name from before the rename is still accepted.
live | test
Code samples
cURL
curl -X GET "https://referalli.com/v1/profitability/products" \
  -H "x-org-id: <value>" \
  -H "referalli-mode: <value>"
TypeScript
const res = await fetch('https://referalli.com/v1/profitability/products', {
  method: 'GET',
  headers: {
    'x-org-id': '<value>',
    'referalli-mode': '<value>',
  },
});
const data = await res.json();
Python
import requests

res = requests.request(
    "GET",
    "https://referalli.com/v1/profitability/products",
    headers={
    "x-org-id": "<value>",
    "referalli-mode": "<value>",
    },
)
data = res.json()
Go
package main

import (
	"fmt"
	"io"
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://referalli.com/v1/profitability/products", nil)
	req.Header.Set("x-org-id", "<value>")
	req.Header.Set("referalli-mode", "<value>")
	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)
	fmt.Println(string(body))
}
PHP
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://referalli.com/v1/profitability/products');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['x-org-id: <value>', 'referalli-mode: <value>']);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
Ruby
require 'net/http'
require 'uri'

uri = URI('https://referalli.com/v1/profitability/products')
req = Net::HTTP::Get.new(uri)
req['x-org-id'] = '<value>'
req['referalli-mode'] = '<value>'
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
  http.request(req)
end
puts res.body
Java
import java.net.URI;
import java.net.http.*;
import java.net.http.HttpRequest.BodyPublishers;

HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://referalli.com/v1/profitability/products"))
    .header("x-org-id", "<value>")
    .header("referalli-mode", "<value>")
    .GET()
    .build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
Responses
200 OK
Example
{
  "data": [
    {
      "productRef": "string",
      "marginBps": 0,
      "unitCostMinor": 0,
      "currency": "string",
      "updatedAt": "2024-01-01T00:00:00Z"
    }
  ]
}
Schema
dataGetProfitabilityProductsProductRefResponse[]required
Show child parameters
productRefstringrequired
marginBpsintegerrequired
unitCostMinorintegerrequired
currencystringrequired
updatedAtstringrequired
400 The request is invalid. error.code is one of:
Example
{
  "error": {
    "code": "validation_error",
    "message": "the body or query failed validation, an unknown field was sent, the body is not valid json, or a session call has no `x-org-id`",
    "details": [
      {
        "code": "invalid_format",
        "path": [
          "destinationUrl"
        ],
        "message": "Invalid URL"
      }
    ],
    "docs_url": "https://referalli.com/docs/errors-and-limits#validation_error"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
401 Missing or invalid credentials. error.code is one of:
Example
{
  "error": {
    "code": "unauthorized",
    "message": "no credentials, an unknown, revoked or expired api key or session, or a signature that did not verify",
    "docs_url": "https://referalli.com/docs/errors-and-limits#unauthorized"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
403 Authenticated, but not allowed. error.code is one of:
Example
{
  "error": {
    "code": "forbidden",
    "message": "the wrong role, a key without the needed scope (the message names it), not a member, a suspended org, or a publishable key from an origin it does not allow",
    "docs_url": "https://referalli.com/docs/errors-and-limits#forbidden"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
404 No such resource. error.code is one of:
Example
{
  "error": {
    "code": "not_found",
    "message": "the resource does not exist in this org (ids from other orgs look the same), a referenced id does not exist, a list cursor is not in the list, or the endpoint does not exist",
    "docs_url": "https://referalli.com/docs/errors-and-limits#not_found"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
429 Rate limited. error.code is one of:
Example
{
  "error": {
    "code": "rate_limited",
    "message": "an endpoint limit or the per-key quota was exceeded",
    "docs_url": "https://referalli.com/docs/errors-and-limits#rate_limited"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
500 Unexpected server error. error.code is one of:
Example
{
  "error": {
    "code": "internal_error",
    "message": "retry with backoff",
    "requestId": "req_8f2c1d4e5a6b7c8d",
    "docs_url": "https://referalli.com/docs/errors-and-limits#internal_error"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
default Any other error, in the same envelope.
Example
{
  "error": {
    "code": "string",
    "message": "string",
    "details": {},
    "requestId": "string",
    "docs_url": "string"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
GEThttps://referalli.com/v1/profitability/products/{productRef}
Get a product margin

One product of the margin catalog.

Auth: an API key with analytics:read (or full), or a session of any role.

Parameters
productRefstringpathrequired
x-org-idstringheader
With a session: the org to act in (the user must be a member). Not used with API keys, which belong to one org.
referalli-modestringheader
test runs a session request against the org's test data. With an API key it must match the key's mode (400 mode_mismatch otherwise). The header name from before the rename is still accepted.
live | test
Code samples
cURL
curl -X GET "https://referalli.com/v1/profitability/products/{productRef}" \
  -H "x-org-id: <value>" \
  -H "referalli-mode: <value>"
TypeScript
const res = await fetch('https://referalli.com/v1/profitability/products/{productRef}', {
  method: 'GET',
  headers: {
    'x-org-id': '<value>',
    'referalli-mode': '<value>',
  },
});
const data = await res.json();
Python
import requests

res = requests.request(
    "GET",
    "https://referalli.com/v1/profitability/products/{productRef}",
    headers={
    "x-org-id": "<value>",
    "referalli-mode": "<value>",
    },
)
data = res.json()
Go
package main

import (
	"fmt"
	"io"
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://referalli.com/v1/profitability/products/{productRef}", nil)
	req.Header.Set("x-org-id", "<value>")
	req.Header.Set("referalli-mode", "<value>")
	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)
	fmt.Println(string(body))
}
PHP
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://referalli.com/v1/profitability/products/{productRef}');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['x-org-id: <value>', 'referalli-mode: <value>']);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
Ruby
require 'net/http'
require 'uri'

uri = URI('https://referalli.com/v1/profitability/products/{productRef}')
req = Net::HTTP::Get.new(uri)
req['x-org-id'] = '<value>'
req['referalli-mode'] = '<value>'
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
  http.request(req)
end
puts res.body
Java
import java.net.URI;
import java.net.http.*;
import java.net.http.HttpRequest.BodyPublishers;

HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://referalli.com/v1/profitability/products/{productRef}"))
    .header("x-org-id", "<value>")
    .header("referalli-mode", "<value>")
    .GET()
    .build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
Responses
200 OK
Example
{
  "productRef": "string",
  "marginBps": 0,
  "unitCostMinor": 0,
  "currency": "string",
  "updatedAt": "2024-01-01T00:00:00Z"
}
Schema
productRefstringrequired
marginBpsintegerrequired
unitCostMinorintegerrequired
currencystringrequired
updatedAtstringrequired
400 The request is invalid. error.code is one of:
Example
{
  "error": {
    "code": "validation_error",
    "message": "the body or query failed validation, an unknown field was sent, the body is not valid json, or a session call has no `x-org-id`",
    "details": [
      {
        "code": "invalid_format",
        "path": [
          "destinationUrl"
        ],
        "message": "Invalid URL"
      }
    ],
    "docs_url": "https://referalli.com/docs/errors-and-limits#validation_error"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
401 Missing or invalid credentials. error.code is one of:
Example
{
  "error": {
    "code": "unauthorized",
    "message": "no credentials, an unknown, revoked or expired api key or session, or a signature that did not verify",
    "docs_url": "https://referalli.com/docs/errors-and-limits#unauthorized"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
403 Authenticated, but not allowed. error.code is one of:
Example
{
  "error": {
    "code": "forbidden",
    "message": "the wrong role, a key without the needed scope (the message names it), not a member, a suspended org, or a publishable key from an origin it does not allow",
    "docs_url": "https://referalli.com/docs/errors-and-limits#forbidden"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
404 No such resource. error.code is one of:
Example
{
  "error": {
    "code": "not_found",
    "message": "the resource does not exist in this org (ids from other orgs look the same), a referenced id does not exist, a list cursor is not in the list, or the endpoint does not exist",
    "docs_url": "https://referalli.com/docs/errors-and-limits#not_found"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
429 Rate limited. error.code is one of:
Example
{
  "error": {
    "code": "rate_limited",
    "message": "an endpoint limit or the per-key quota was exceeded",
    "docs_url": "https://referalli.com/docs/errors-and-limits#rate_limited"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
500 Unexpected server error. error.code is one of:
Example
{
  "error": {
    "code": "internal_error",
    "message": "retry with backoff",
    "requestId": "req_8f2c1d4e5a6b7c8d",
    "docs_url": "https://referalli.com/docs/errors-and-limits#internal_error"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
default Any other error, in the same envelope.
Example
{
  "error": {
    "code": "string",
    "message": "string",
    "details": {},
    "requestId": "string",
    "docs_url": "string"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
PUThttps://referalli.com/v1/profitability/products/{productRef}
Set a product margin

Sets a product's margin (marginBps) or unit cost (unitCostMinor, in currency, default the reporting currency); exactly one of the two. Audited.

Auth: an API key with analytics:write (or full), or a session with role owner, admin.

Parameters
productRefstringpathrequired
Idempotency-Keystringheader
Any unique string up to 255 printable ASCII characters (a UUID). A retry with the same key within 24 hours gets the first response again (with idempotent-replayed: true) and nothing runs twice. The same key on a different request is 422 idempotency_key_reused; while the first is still running, 409 idempotency_in_progress.
x-org-idstringheader
With a session: the org to act in (the user must be a member). Not used with API keys, which belong to one org.
referalli-modestringheader
test runs a session request against the org's test data. With an API key it must match the key's mode (400 mode_mismatch otherwise). The header name from before the rename is still accepted.
live | test
Request body application/json
marginBpsinteger
unitCostMinorinteger
currencystring
{
  "marginBps": 0,
  "unitCostMinor": 0,
  "currency": "string"
}
Code samples
cURL
curl -X PUT "https://referalli.com/v1/profitability/products/{productRef}" \
  -H "Idempotency-Key: <value>" \
  -H "x-org-id: <value>" \
  -H "referalli-mode: <value>" \
  -H "Content-Type: application/json" \
  -d '{"marginBps":0,"unitCostMinor":0,"currency":"string"}'
TypeScript
const res = await fetch('https://referalli.com/v1/profitability/products/{productRef}', {
  method: 'PUT',
  headers: {
    'Idempotency-Key': '<value>',
    'x-org-id': '<value>',
    'referalli-mode': '<value>',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({"marginBps":0,"unitCostMinor":0,"currency":"string"}),
});
const data = await res.json();
Python
import requests

res = requests.request(
    "PUT",
    "https://referalli.com/v1/profitability/products/{productRef}",
    headers={
    "Idempotency-Key": "<value>",
    "x-org-id": "<value>",
    "referalli-mode": "<value>",
    "Content-Type": "application/json",
    },
    json={"marginBps": 0, "unitCostMinor": 0, "currency": "string"},
)
data = res.json()
Go
package main

import (
	"fmt"
	"io"
	"net/http"
	"strings"
)

func main() {
	req, _ := http.NewRequest("PUT", "https://referalli.com/v1/profitability/products/{productRef}", strings.NewReader(`{"marginBps":0,"unitCostMinor":0,"currency":"string"}`))
	req.Header.Set("Idempotency-Key", "<value>")
	req.Header.Set("x-org-id", "<value>")
	req.Header.Set("referalli-mode", "<value>")
	req.Header.Set("Content-Type", "application/json")
	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)
	fmt.Println(string(body))
}
PHP
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://referalli.com/v1/profitability/products/{productRef}');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Idempotency-Key: <value>', 'x-org-id: <value>', 'referalli-mode: <value>', 'Content-Type: application/json']);
curl_setopt($ch, CURLOPT_POSTFIELDS, '{"marginBps":0,"unitCostMinor":0,"currency":"string"}');
$response = curl_exec($ch);
curl_close($ch);
echo $response;
Ruby
require 'net/http'
require 'uri'

uri = URI('https://referalli.com/v1/profitability/products/{productRef}')
req = Net::HTTP::Put.new(uri)
req['Idempotency-Key'] = '<value>'
req['x-org-id'] = '<value>'
req['referalli-mode'] = '<value>'
req['Content-Type'] = 'application/json'
req.body = '{"marginBps":0,"unitCostMinor":0,"currency":"string"}'
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
  http.request(req)
end
puts res.body
Java
import java.net.URI;
import java.net.http.*;
import java.net.http.HttpRequest.BodyPublishers;

HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://referalli.com/v1/profitability/products/{productRef}"))
    .header("Idempotency-Key", "<value>")
    .header("x-org-id", "<value>")
    .header("referalli-mode", "<value>")
    .header("Content-Type", "application/json")
    .method("PUT", BodyPublishers.ofString("{\"marginBps\":0,\"unitCostMinor\":0,\"currency\":\"string\"}"))
    .build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
Responses
200 OK
Example
{
  "productRef": "string",
  "marginBps": 0,
  "unitCostMinor": 0,
  "currency": "string",
  "updatedAt": "2024-01-01T00:00:00Z"
}
Schema
productRefstringrequired
marginBpsintegerrequired
unitCostMinorintegerrequired
currencystringrequired
updatedAtstringrequired
400 The request is invalid. error.code is one of:
Example
{
  "error": {
    "code": "validation_error",
    "message": "the body or query failed validation, an unknown field was sent, the body is not valid json, or a session call has no `x-org-id`",
    "details": [
      {
        "code": "invalid_format",
        "path": [
          "destinationUrl"
        ],
        "message": "Invalid URL"
      }
    ],
    "docs_url": "https://referalli.com/docs/errors-and-limits#validation_error"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
401 Missing or invalid credentials. error.code is one of:
Example
{
  "error": {
    "code": "unauthorized",
    "message": "no credentials, an unknown, revoked or expired api key or session, or a signature that did not verify",
    "docs_url": "https://referalli.com/docs/errors-and-limits#unauthorized"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
403 Authenticated, but not allowed. error.code is one of:
Example
{
  "error": {
    "code": "forbidden",
    "message": "the wrong role, a key without the needed scope (the message names it), not a member, a suspended org, or a publishable key from an origin it does not allow",
    "docs_url": "https://referalli.com/docs/errors-and-limits#forbidden"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
404 No such resource. error.code is one of:
Example
{
  "error": {
    "code": "not_found",
    "message": "the resource does not exist in this org (ids from other orgs look the same), a referenced id does not exist, a list cursor is not in the list, or the endpoint does not exist",
    "docs_url": "https://referalli.com/docs/errors-and-limits#not_found"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
409 The request conflicts with the current state. error.code is one of:
Example
{
  "error": {
    "code": "conflict",
    "message": "a unique value is taken, or the action would break a rule (the message says which)",
    "docs_url": "https://referalli.com/docs/errors-and-limits#conflict"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
422 The request cannot be processed as sent. error.code is one of:
Example
{
  "error": {
    "code": "idempotency_key_reused",
    "message": "the `idempotency-key` was used for a different request",
    "docs_url": "https://referalli.com/docs/errors-and-limits#idempotency_key_reused"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
429 Rate limited. error.code is one of:
Example
{
  "error": {
    "code": "rate_limited",
    "message": "an endpoint limit or the per-key quota was exceeded",
    "docs_url": "https://referalli.com/docs/errors-and-limits#rate_limited"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
500 Unexpected server error. error.code is one of:
Example
{
  "error": {
    "code": "internal_error",
    "message": "retry with backoff",
    "requestId": "req_8f2c1d4e5a6b7c8d",
    "docs_url": "https://referalli.com/docs/errors-and-limits#internal_error"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
default Any other error, in the same envelope.
Example
{
  "error": {
    "code": "string",
    "message": "string",
    "details": {},
    "requestId": "string",
    "docs_url": "string"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
DELETEhttps://referalli.com/v1/profitability/products/{productRef}
Delete a product margin

Removes a product from the margin catalog; its payments fall back to the program or org margin. Audited.

Auth: an API key with analytics:write (or full), or a session with role owner, admin.

Parameters
productRefstringpathrequired
Idempotency-Keystringheader
Any unique string up to 255 printable ASCII characters (a UUID). A retry with the same key within 24 hours gets the first response again (with idempotent-replayed: true) and nothing runs twice. The same key on a different request is 422 idempotency_key_reused; while the first is still running, 409 idempotency_in_progress.
x-org-idstringheader
With a session: the org to act in (the user must be a member). Not used with API keys, which belong to one org.
referalli-modestringheader
test runs a session request against the org's test data. With an API key it must match the key's mode (400 mode_mismatch otherwise). The header name from before the rename is still accepted.
live | test
Code samples
cURL
curl -X DELETE "https://referalli.com/v1/profitability/products/{productRef}" \
  -H "Idempotency-Key: <value>" \
  -H "x-org-id: <value>" \
  -H "referalli-mode: <value>"
TypeScript
const res = await fetch('https://referalli.com/v1/profitability/products/{productRef}', {
  method: 'DELETE',
  headers: {
    'Idempotency-Key': '<value>',
    'x-org-id': '<value>',
    'referalli-mode': '<value>',
  },
});
const data = await res.json();
Python
import requests

res = requests.request(
    "DELETE",
    "https://referalli.com/v1/profitability/products/{productRef}",
    headers={
    "Idempotency-Key": "<value>",
    "x-org-id": "<value>",
    "referalli-mode": "<value>",
    },
)
data = res.json()
Go
package main

import (
	"fmt"
	"io"
	"net/http"
)

func main() {
	req, _ := http.NewRequest("DELETE", "https://referalli.com/v1/profitability/products/{productRef}", nil)
	req.Header.Set("Idempotency-Key", "<value>")
	req.Header.Set("x-org-id", "<value>")
	req.Header.Set("referalli-mode", "<value>")
	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)
	fmt.Println(string(body))
}
PHP
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://referalli.com/v1/profitability/products/{productRef}');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Idempotency-Key: <value>', 'x-org-id: <value>', 'referalli-mode: <value>']);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
Ruby
require 'net/http'
require 'uri'

uri = URI('https://referalli.com/v1/profitability/products/{productRef}')
req = Net::HTTP::Delete.new(uri)
req['Idempotency-Key'] = '<value>'
req['x-org-id'] = '<value>'
req['referalli-mode'] = '<value>'
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
  http.request(req)
end
puts res.body
Java
import java.net.URI;
import java.net.http.*;
import java.net.http.HttpRequest.BodyPublishers;

HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://referalli.com/v1/profitability/products/{productRef}"))
    .header("Idempotency-Key", "<value>")
    .header("x-org-id", "<value>")
    .header("referalli-mode", "<value>")
    .method("DELETE", BodyPublishers.noBody())
    .build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
Responses
200 OK
Example
{
  "ok": true,
  "status": "string"
}
Schema
okbooleanrequired
statusstringrequired
400 The request is invalid. error.code is one of:
Example
{
  "error": {
    "code": "validation_error",
    "message": "the body or query failed validation, an unknown field was sent, the body is not valid json, or a session call has no `x-org-id`",
    "details": [
      {
        "code": "invalid_format",
        "path": [
          "destinationUrl"
        ],
        "message": "Invalid URL"
      }
    ],
    "docs_url": "https://referalli.com/docs/errors-and-limits#validation_error"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
401 Missing or invalid credentials. error.code is one of:
Example
{
  "error": {
    "code": "unauthorized",
    "message": "no credentials, an unknown, revoked or expired api key or session, or a signature that did not verify",
    "docs_url": "https://referalli.com/docs/errors-and-limits#unauthorized"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
403 Authenticated, but not allowed. error.code is one of:
Example
{
  "error": {
    "code": "forbidden",
    "message": "the wrong role, a key without the needed scope (the message names it), not a member, a suspended org, or a publishable key from an origin it does not allow",
    "docs_url": "https://referalli.com/docs/errors-and-limits#forbidden"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
404 No such resource. error.code is one of:
Example
{
  "error": {
    "code": "not_found",
    "message": "the resource does not exist in this org (ids from other orgs look the same), a referenced id does not exist, a list cursor is not in the list, or the endpoint does not exist",
    "docs_url": "https://referalli.com/docs/errors-and-limits#not_found"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
409 The request conflicts with the current state. error.code is one of:
Example
{
  "error": {
    "code": "conflict",
    "message": "a unique value is taken, or the action would break a rule (the message says which)",
    "docs_url": "https://referalli.com/docs/errors-and-limits#conflict"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
422 The request cannot be processed as sent. error.code is one of:
Example
{
  "error": {
    "code": "idempotency_key_reused",
    "message": "the `idempotency-key` was used for a different request",
    "docs_url": "https://referalli.com/docs/errors-and-limits#idempotency_key_reused"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
429 Rate limited. error.code is one of:
Example
{
  "error": {
    "code": "rate_limited",
    "message": "an endpoint limit or the per-key quota was exceeded",
    "docs_url": "https://referalli.com/docs/errors-and-limits#rate_limited"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
500 Unexpected server error. error.code is one of:
Example
{
  "error": {
    "code": "internal_error",
    "message": "retry with backoff",
    "requestId": "req_8f2c1d4e5a6b7c8d",
    "docs_url": "https://referalli.com/docs/errors-and-limits#internal_error"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
default Any other error, in the same envelope.
Example
{
  "error": {
    "code": "string",
    "message": "string",
    "details": {},
    "requestId": "string",
    "docs_url": "string"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
POSThttps://referalli.com/v1/profitability/rebuild
Rebuild ROI figures

Recomputes every stored ROI figure from the value events with the current settings and mappings, in the background. Returns a jobId to poll; while one rebuild is running, the same job is returned. Audited.

Auth: an API key with analytics:write (or full), or a session with role owner, admin.

Parameters
Idempotency-Keystringheader
Any unique string up to 255 printable ASCII characters (a UUID). A retry with the same key within 24 hours gets the first response again (with idempotent-replayed: true) and nothing runs twice. The same key on a different request is 422 idempotency_key_reused; while the first is still running, 409 idempotency_in_progress.
x-org-idstringheader
With a session: the org to act in (the user must be a member). Not used with API keys, which belong to one org.
referalli-modestringheader
test runs a session request against the org's test data. With an API key it must match the key's mode (400 mode_mismatch otherwise). The header name from before the rename is still accepted.
live | test
Code samples
cURL
curl -X POST "https://referalli.com/v1/profitability/rebuild" \
  -H "Idempotency-Key: <value>" \
  -H "x-org-id: <value>" \
  -H "referalli-mode: <value>"
TypeScript
const res = await fetch('https://referalli.com/v1/profitability/rebuild', {
  method: 'POST',
  headers: {
    'Idempotency-Key': '<value>',
    'x-org-id': '<value>',
    'referalli-mode': '<value>',
  },
});
const data = await res.json();
Python
import requests

res = requests.request(
    "POST",
    "https://referalli.com/v1/profitability/rebuild",
    headers={
    "Idempotency-Key": "<value>",
    "x-org-id": "<value>",
    "referalli-mode": "<value>",
    },
)
data = res.json()
Go
package main

import (
	"fmt"
	"io"
	"net/http"
)

func main() {
	req, _ := http.NewRequest("POST", "https://referalli.com/v1/profitability/rebuild", nil)
	req.Header.Set("Idempotency-Key", "<value>")
	req.Header.Set("x-org-id", "<value>")
	req.Header.Set("referalli-mode", "<value>")
	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)
	fmt.Println(string(body))
}
PHP
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://referalli.com/v1/profitability/rebuild');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Idempotency-Key: <value>', 'x-org-id: <value>', 'referalli-mode: <value>']);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
Ruby
require 'net/http'
require 'uri'

uri = URI('https://referalli.com/v1/profitability/rebuild')
req = Net::HTTP::Post.new(uri)
req['Idempotency-Key'] = '<value>'
req['x-org-id'] = '<value>'
req['referalli-mode'] = '<value>'
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
  http.request(req)
end
puts res.body
Java
import java.net.URI;
import java.net.http.*;
import java.net.http.HttpRequest.BodyPublishers;

HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://referalli.com/v1/profitability/rebuild"))
    .header("Idempotency-Key", "<value>")
    .header("x-org-id", "<value>")
    .header("referalli-mode", "<value>")
    .method("POST", BodyPublishers.noBody())
    .build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
Responses
200 OK
Example
{
  "jobId": "string"
}
Schema
jobIdstringrequired
400 The request is invalid. error.code is one of:
Example
{
  "error": {
    "code": "validation_error",
    "message": "the body or query failed validation, an unknown field was sent, the body is not valid json, or a session call has no `x-org-id`",
    "details": [
      {
        "code": "invalid_format",
        "path": [
          "destinationUrl"
        ],
        "message": "Invalid URL"
      }
    ],
    "docs_url": "https://referalli.com/docs/errors-and-limits#validation_error"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
401 Missing or invalid credentials. error.code is one of:
Example
{
  "error": {
    "code": "unauthorized",
    "message": "no credentials, an unknown, revoked or expired api key or session, or a signature that did not verify",
    "docs_url": "https://referalli.com/docs/errors-and-limits#unauthorized"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
403 Authenticated, but not allowed. error.code is one of:
Example
{
  "error": {
    "code": "forbidden",
    "message": "the wrong role, a key without the needed scope (the message names it), not a member, a suspended org, or a publishable key from an origin it does not allow",
    "docs_url": "https://referalli.com/docs/errors-and-limits#forbidden"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
404 No such resource. error.code is one of:
Example
{
  "error": {
    "code": "not_found",
    "message": "the resource does not exist in this org (ids from other orgs look the same), a referenced id does not exist, a list cursor is not in the list, or the endpoint does not exist",
    "docs_url": "https://referalli.com/docs/errors-and-limits#not_found"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
409 The request conflicts with the current state. error.code is one of:
Example
{
  "error": {
    "code": "conflict",
    "message": "a unique value is taken, or the action would break a rule (the message says which)",
    "docs_url": "https://referalli.com/docs/errors-and-limits#conflict"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
422 The request cannot be processed as sent. error.code is one of:
Example
{
  "error": {
    "code": "idempotency_key_reused",
    "message": "the `idempotency-key` was used for a different request",
    "docs_url": "https://referalli.com/docs/errors-and-limits#idempotency_key_reused"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
429 Rate limited. error.code is one of:
Example
{
  "error": {
    "code": "rate_limited",
    "message": "an endpoint limit or the per-key quota was exceeded",
    "docs_url": "https://referalli.com/docs/errors-and-limits#rate_limited"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
500 Unexpected server error. error.code is one of:
Example
{
  "error": {
    "code": "internal_error",
    "message": "retry with backoff",
    "requestId": "req_8f2c1d4e5a6b7c8d",
    "docs_url": "https://referalli.com/docs/errors-and-limits#internal_error"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
default Any other error, in the same envelope.
Example
{
  "error": {
    "code": "string",
    "message": "string",
    "details": {},
    "requestId": "string",
    "docs_url": "string"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
GEThttps://referalli.com/v1/profitability/rebuild/{jobId}
Get a rebuild job

Progress of a rebuild: queued, running, done or failed (a job untouched for an hour reports failed with error: "stale"), with processed and total counts.

Auth: an API key with analytics:read (or full), or a session of any role.

Parameters
jobIdstringpathrequired
x-org-idstringheader
With a session: the org to act in (the user must be a member). Not used with API keys, which belong to one org.
referalli-modestringheader
test runs a session request against the org's test data. With an API key it must match the key's mode (400 mode_mismatch otherwise). The header name from before the rename is still accepted.
live | test
Code samples
cURL
curl -X GET "https://referalli.com/v1/profitability/rebuild/{jobId}" \
  -H "x-org-id: <value>" \
  -H "referalli-mode: <value>"
TypeScript
const res = await fetch('https://referalli.com/v1/profitability/rebuild/{jobId}', {
  method: 'GET',
  headers: {
    'x-org-id': '<value>',
    'referalli-mode': '<value>',
  },
});
const data = await res.json();
Python
import requests

res = requests.request(
    "GET",
    "https://referalli.com/v1/profitability/rebuild/{jobId}",
    headers={
    "x-org-id": "<value>",
    "referalli-mode": "<value>",
    },
)
data = res.json()
Go
package main

import (
	"fmt"
	"io"
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://referalli.com/v1/profitability/rebuild/{jobId}", nil)
	req.Header.Set("x-org-id", "<value>")
	req.Header.Set("referalli-mode", "<value>")
	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)
	fmt.Println(string(body))
}
PHP
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://referalli.com/v1/profitability/rebuild/{jobId}');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['x-org-id: <value>', 'referalli-mode: <value>']);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
Ruby
require 'net/http'
require 'uri'

uri = URI('https://referalli.com/v1/profitability/rebuild/{jobId}')
req = Net::HTTP::Get.new(uri)
req['x-org-id'] = '<value>'
req['referalli-mode'] = '<value>'
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
  http.request(req)
end
puts res.body
Java
import java.net.URI;
import java.net.http.*;
import java.net.http.HttpRequest.BodyPublishers;

HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://referalli.com/v1/profitability/rebuild/{jobId}"))
    .header("x-org-id", "<value>")
    .header("referalli-mode", "<value>")
    .GET()
    .build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
Responses
200 OK
Example
{
  "status": "queued",
  "processed": 0,
  "total": 0,
  "error": "string"
}
Schema
statusstringrequired
queued | running | done | failed
processedintegerrequired
totalintegerrequired
errorstring
400 The request is invalid. error.code is one of:
Example
{
  "error": {
    "code": "validation_error",
    "message": "the body or query failed validation, an unknown field was sent, the body is not valid json, or a session call has no `x-org-id`",
    "details": [
      {
        "code": "invalid_format",
        "path": [
          "destinationUrl"
        ],
        "message": "Invalid URL"
      }
    ],
    "docs_url": "https://referalli.com/docs/errors-and-limits#validation_error"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
401 Missing or invalid credentials. error.code is one of:
Example
{
  "error": {
    "code": "unauthorized",
    "message": "no credentials, an unknown, revoked or expired api key or session, or a signature that did not verify",
    "docs_url": "https://referalli.com/docs/errors-and-limits#unauthorized"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
403 Authenticated, but not allowed. error.code is one of:
Example
{
  "error": {
    "code": "forbidden",
    "message": "the wrong role, a key without the needed scope (the message names it), not a member, a suspended org, or a publishable key from an origin it does not allow",
    "docs_url": "https://referalli.com/docs/errors-and-limits#forbidden"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
404 No such resource. error.code is one of:
Example
{
  "error": {
    "code": "not_found",
    "message": "the resource does not exist in this org (ids from other orgs look the same), a referenced id does not exist, a list cursor is not in the list, or the endpoint does not exist",
    "docs_url": "https://referalli.com/docs/errors-and-limits#not_found"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
429 Rate limited. error.code is one of:
Example
{
  "error": {
    "code": "rate_limited",
    "message": "an endpoint limit or the per-key quota was exceeded",
    "docs_url": "https://referalli.com/docs/errors-and-limits#rate_limited"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
500 Unexpected server error. error.code is one of:
Example
{
  "error": {
    "code": "internal_error",
    "message": "retry with backoff",
    "requestId": "req_8f2c1d4e5a6b7c8d",
    "docs_url": "https://referalli.com/docs/errors-and-limits#internal_error"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
default Any other error, in the same envelope.
Example
{
  "error": {
    "code": "string",
    "message": "string",
    "details": {},
    "requestId": "string",
    "docs_url": "string"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
GEThttps://referalli.com/v1/roi/summary
Get the ROI summary

Credit ROI for the grants in view: credit cost, cash and profit from the recipients after each grant, net, ROI, payback share and median days, outstanding credit and how much of it is measured rather than inferred. With programId, also status against the program's target ROI. model=incremental adds the lift against the program's holdout group; includeProjection=true adds the expected payback of open grants. from/to select grants by grant date (a date covers its whole UTC day), programId and partnerId narrow them, windowDays overrides each program's attribution window (30, 90, 180, 365, or 0 for lifetime), and currency views one native currency instead of the reporting currency. format=csv returns the same as a CSV file.

Auth: an API key with analytics:read (or full), or a session of any role.

Parameters
fromstringquery
Grants (or referrals) from this instant or date, inclusive.
tostringquery
Up to this instant, or through the end of this date (UTC), inclusive.
programIdstringquery
partnerIdstringquery
The grant's partner: the referrer, or the partner of the referee's referral.
windowDaysintegerquery
Attribution window; default each program's setting. 0 = lifetime.
currencystringquery
Default the reporting currency (converted); another code gives that currency only.
formatstringquery
json | csv
modelstringquery
naive (default): ROI of every grant. incremental: also incremental, the program's credit-caused lift against its recorded holdout (requires programId; reporting currency; from/to select referrals by first qualifying payment).
naive | incremental
includeProjectionstringquery
true: also projection, the expected payback of the open grants in view from their program-and-role cohort's median curve (labelled 'projection'; needs 50 closed grants per cohort).
true | false
x-org-idstringheader
With a session: the org to act in (the user must be a member). Not used with API keys, which belong to one org.
referalli-modestringheader
test runs a session request against the org's test data. With an API key it must match the key's mode (400 mode_mismatch otherwise). The header name from before the rename is still accepted.
live | test
Code samples
cURL
curl -X GET "https://referalli.com/v1/roi/summary?from=&to=&programId=&partnerId=&windowDays=&currency=&format=&model=&includeProjection=" \
  -H "x-org-id: <value>" \
  -H "referalli-mode: <value>"
TypeScript
const res = await fetch('https://referalli.com/v1/roi/summary?from=&to=&programId=&partnerId=&windowDays=&currency=&format=&model=&includeProjection=', {
  method: 'GET',
  headers: {
    'x-org-id': '<value>',
    'referalli-mode': '<value>',
  },
});
const data = await res.json();
Python
import requests

res = requests.request(
    "GET",
    "https://referalli.com/v1/roi/summary?from=&to=&programId=&partnerId=&windowDays=&currency=&format=&model=&includeProjection=",
    headers={
    "x-org-id": "<value>",
    "referalli-mode": "<value>",
    },
)
data = res.json()
Go
package main

import (
	"fmt"
	"io"
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://referalli.com/v1/roi/summary?from=&to=&programId=&partnerId=&windowDays=&currency=&format=&model=&includeProjection=", nil)
	req.Header.Set("x-org-id", "<value>")
	req.Header.Set("referalli-mode", "<value>")
	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)
	fmt.Println(string(body))
}
PHP
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://referalli.com/v1/roi/summary?from=&to=&programId=&partnerId=&windowDays=&currency=&format=&model=&includeProjection=');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['x-org-id: <value>', 'referalli-mode: <value>']);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
Ruby
require 'net/http'
require 'uri'

uri = URI('https://referalli.com/v1/roi/summary?from=&to=&programId=&partnerId=&windowDays=&currency=&format=&model=&includeProjection=')
req = Net::HTTP::Get.new(uri)
req['x-org-id'] = '<value>'
req['referalli-mode'] = '<value>'
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
  http.request(req)
end
puts res.body
Java
import java.net.URI;
import java.net.http.*;
import java.net.http.HttpRequest.BodyPublishers;

HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://referalli.com/v1/roi/summary?from=&to=&programId=&partnerId=&windowDays=&currency=&format=&model=&includeProjection="))
    .header("x-org-id", "<value>")
    .header("referalli-mode", "<value>")
    .GET()
    .build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
Responses
200 JSON by default; text/csv with ?format=csv.
Example
{
  "currency": "string",
  "creditCostMinor": 0,
  "cashAfterMinor": 0,
  "profitAfterMinor": 0,
  "netMinor": 0,
  "roi": 0,
  "paidBackShareBps": 0,
  "medianPaybackDays": 0,
  "grants": 0,
  "profitSources": {},
  "coverage": {
    "creditAppliedReportedBps": 0,
    "marginCoveredBps": 0,
    "inferredShareBps": 0
  },
  "outstandingCreditMinor": 0,
  "outstandingCostIfUsedMinor": 0,
  "currencies": [
    "string"
  ],
  "incremental": {
    "currency": "string",
    "windowDays": 0,
    "holdoutBps": 0,
    "treatment": {
      "n": 0,
      "cashAfterPerReferralMinor": 0,
      "profitAfterPerReferralMinor": 0
    },
    "control": {
      "n": 0,
      "cashAfterPerReferralMinor": 0,
      "profitAfterPerReferralMinor": 0
    },
    "liftMinorPerReferral": 0,
    "liftProfitMinorPerReferral": 0,
    "creditCostPerReferralMinor": 0,
    "incrementalRoi": 0,
    "eligible": true,
    "reason": "no_holdout",
    "unrecordedReferrals": 0,
    "excludedReferrals": {
      "unrecorded": 0,
      "treatmentWithoutCredit": 0,
      "controlWithCredit": 0
    },
    "excluded": [
      {
        "eventId": "string",
        "currency": "string",
        "reason": "string"
      }
    ]
  },
  "projection": {
    "label": "string",
    "eligible": true,
    "reason": "string",
    "closedGrants": 0,
    "openGrants": 0,
    "projectedGrants": 0,
    "expectedPaidBackShareBps": 0,
    "medianExpectedPaybackDays": 0,
    "cohorts": [
      {
        "programId": null,
        "role": "referee",
        "eligible": true,
        "reason": "string",
        "closedGrants": 0,
        "openGrants": 0,
        "medianCrossingDay": null,
        "curveThroughDay": 0,
        "noCrossingReason": "cohort_not_paid_back",
        "behindCohort": 0
      }
    ]
  },
  "target": {
    "targetRoiBps": 0,
    "status": "on_track"
  }
}
Schema
currencystringrequired
creditCostMinorintegerrequired
Integer minor units (cents).
cashAfterMinorintegerrequired
Integer minor units (cents).
profitAfterMinorintegerrequired
netMinorintegerrequired
roinumberrequired
Profit after ÷ cost, 4 decimals; null with no cost or unknown profit.
paidBackShareBpsintegerrequired
Basis points (10000 = 100%); null when there is nothing to divide by.
medianPaybackDaysnumberrequired
grantsintegerrequired
profitSourcesobjectrequired
coverageobjectrequired
Show child parameters
creditAppliedReportedBpsintegerrequired
Basis points (10000 = 100%); null when there is nothing to divide by.
marginCoveredBpsintegerrequired
Basis points (10000 = 100%); null when there is nothing to divide by.
inferredShareBpsintegerrequired
Basis points (10000 = 100%); null when there is nothing to divide by.
outstandingCreditMinorintegerrequired
Face not yet used, expired or revoked, in the reporting currency.
outstandingCostIfUsedMinorintegerrequired
Outstanding credit priced by each grant's cost model; null when a model needs a margin and none is known.
currenciesstring[]required
Native currencies of the grants in scope (ignoring the currency filter), most grants first.
incrementalobject
Present with model=incremental.
Show child parameters
currencystringrequired
windowDaysintegerrequired
holdoutBpsintegerrequired
treatmentobjectrequired
Recorded treatment referrals that got referee credit.
Show child parameters
nintegerrequired
cashAfterPerReferralMinorintegerrequired
Integer minor units (cents).
profitAfterPerReferralMinorintegerrequired
controlobjectrequired
Recorded control (holdout) referrals: no credit.
Show child parameters
nintegerrequired
cashAfterPerReferralMinorintegerrequired
Integer minor units (cents).
profitAfterPerReferralMinorintegerrequired
liftMinorPerReferralintegerrequired
Treatment minus control cash after the first qualifying payment, per referral.
liftProfitMinorPerReferralintegerrequired
creditCostPerReferralMinorintegerrequired
Referee credit cost per treatment referral. Only credit: control referrals also earn no commission, and that withheld commission is not counted here.
incrementalRoinumberrequired
Lift profit ÷ credit cost per referral; null when not eligible, no margin or no cost. The denominator is referee credit only: the commission withheld from control referrals is not in it, so the lift also reflects that commission difference.
eligiblebooleanrequired
reasonstring
no_holdout | too_few | no_recorded_groups
unrecordedReferralsintegerrequired
Referrals from before groups were recorded: naive ROI only.
excludedReferralsobjectrequired
Referrals in range left out of both groups, by reason.
Show child parameters
unrecordedintegerrequired
treatmentWithoutCreditintegerrequired
controlWithCreditintegerrequired
excludedobject[]required
Show child parameters
eventIdstringrequired
currencystringrequired
reasonstringrequired
projectionobject
Present with includeProjection=true.
Show child parameters
labelstringrequired
Always "projection": expected figures, never actuals.
eligiblebooleanrequired
reasonstring
closedGrantsintegerrequired
openGrantsintegerrequired
projectedGrantsintegerrequired
Open grants in cohorts with at least 50 closed grants.
expectedPaidBackShareBpsintegerrequired
Share of projected open grants expected to pay back (already paid back included).
medianExpectedPaybackDaysintegerrequired
cohortsobject[]required
Show child parameters
programIdstringrequired
rolestringrequired
referee | referrer
eligiblebooleanrequired
reasonstring
closedGrantsintegerrequired
openGrantsintegerrequired
medianCrossingDayinteger
First day the cohort's median profit/cost ratio reaches 1.0; null when it doesn't within the window.
curveThroughDayinteger
Last day with at least 50 closed grants observed that far: the curve stops there.
noCrossingReasonstring
cohort_not_paid_back | insufficient_horizon
behindCohortinteger
Open grants past the crossing day without paying back.
targetobject
With programId: status against the program's targetRoiBps (unknown when ROI is null); null when it sets no target.
Show child parameters
targetRoiBpsintegerrequired
statusstringrequired
on_track | below | unknown
400 The request is invalid. error.code is one of:
Example
{
  "error": {
    "code": "validation_error",
    "message": "the body or query failed validation, an unknown field was sent, the body is not valid json, or a session call has no `x-org-id`",
    "details": [
      {
        "code": "invalid_format",
        "path": [
          "destinationUrl"
        ],
        "message": "Invalid URL"
      }
    ],
    "docs_url": "https://referalli.com/docs/errors-and-limits#validation_error"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
401 Missing or invalid credentials. error.code is one of:
Example
{
  "error": {
    "code": "unauthorized",
    "message": "no credentials, an unknown, revoked or expired api key or session, or a signature that did not verify",
    "docs_url": "https://referalli.com/docs/errors-and-limits#unauthorized"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
403 Authenticated, but not allowed. error.code is one of:
Example
{
  "error": {
    "code": "forbidden",
    "message": "the wrong role, a key without the needed scope (the message names it), not a member, a suspended org, or a publishable key from an origin it does not allow",
    "docs_url": "https://referalli.com/docs/errors-and-limits#forbidden"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
404 No such resource. error.code is one of:
Example
{
  "error": {
    "code": "not_found",
    "message": "the resource does not exist in this org (ids from other orgs look the same), a referenced id does not exist, a list cursor is not in the list, or the endpoint does not exist",
    "docs_url": "https://referalli.com/docs/errors-and-limits#not_found"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
429 Rate limited. error.code is one of:
Example
{
  "error": {
    "code": "rate_limited",
    "message": "an endpoint limit or the per-key quota was exceeded",
    "docs_url": "https://referalli.com/docs/errors-and-limits#rate_limited"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
500 Unexpected server error. error.code is one of:
Example
{
  "error": {
    "code": "internal_error",
    "message": "retry with backoff",
    "requestId": "req_8f2c1d4e5a6b7c8d",
    "docs_url": "https://referalli.com/docs/errors-and-limits#internal_error"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
default Any other error, in the same envelope.
Example
{
  "error": {
    "code": "string",
    "message": "string",
    "details": {},
    "requestId": "string",
    "docs_url": "string"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
GEThttps://referalli.com/v1/roi/breakdown
Get the ROI breakdown

The summary figures grouped by program, partner, cohort (grant month), source or role, best ROI first (cohorts in date order). Partner and program rows also carry their referrals' combined figures. from/to select grants by grant date (a date covers its whole UTC day), programId and partnerId narrow them, windowDays overrides each program's attribution window (30, 90, 180, 365, or 0 for lifetime), and currency views one native currency instead of the reporting currency. format=csv returns the same as a CSV file.

Auth: an API key with analytics:read (or full), or a session of any role.

Parameters
fromstringquery
Grants (or referrals) from this instant or date, inclusive.
tostringquery
Up to this instant, or through the end of this date (UTC), inclusive.
programIdstringquery
partnerIdstringquery
The grant's partner: the referrer, or the partner of the referee's referral.
windowDaysintegerquery
Attribution window; default each program's setting. 0 = lifetime.
currencystringquery
Default the reporting currency (converted); another code gives that currency only.
formatstringquery
json | csv
bystringqueryrequired
program | partner | cohort | source | role
limitintegerquery
Items per page, 1 to 100 (default 50). From API version 2026-11-01; ignored under 2026-10-21, where lists are a capped plain array.
= 50
starting_afterstringquery
A cursor: the id of an item (the previous page's next_cursor); returns the items after it. From API version 2026-11-01; ignored under 2026-10-21, where lists are a capped plain array.
ending_beforestringquery
A cursor: returns the items before this item id (the previous page). Not with starting_after. From API version 2026-11-01; ignored under 2026-10-21, where lists are a capped plain array.
created[gte]stringquery
Only items created at or after this time (ISO 8601), on lists of timestamped records. From API version 2026-11-01; ignored under 2026-10-21, where lists are a capped plain array.
created[lte]stringquery
Only items created at or before this time (ISO 8601), on lists of timestamped records. From API version 2026-11-01; ignored under 2026-10-21, where lists are a capped plain array.
referalli-versionstringheader
The API version to run the request under (2026-10-21, 2026-11-01). Default: the API key's pinned version, else 2026-10-21. The header name from before the rename is still accepted; this name wins when both are sent.
2026-10-21 | 2026-11-01
x-org-idstringheader
With a session: the org to act in (the user must be a member). Not used with API keys, which belong to one org.
referalli-modestringheader
test runs a session request against the org's test data. With an API key it must match the key's mode (400 mode_mismatch otherwise). The header name from before the rename is still accepted.
live | test
Code samples
cURL
curl -X GET "https://referalli.com/v1/roi/breakdown?from=&to=&programId=&partnerId=&windowDays=&currency=&format=&by=&limit=&starting_after=&ending_before=&created%5Bgte%5D=&created%5Blte%5D=" \
  -H "referalli-version: <value>" \
  -H "x-org-id: <value>" \
  -H "referalli-mode: <value>"
TypeScript
const res = await fetch('https://referalli.com/v1/roi/breakdown?from=&to=&programId=&partnerId=&windowDays=&currency=&format=&by=&limit=&starting_after=&ending_before=&created%5Bgte%5D=&created%5Blte%5D=', {
  method: 'GET',
  headers: {
    'referalli-version': '<value>',
    'x-org-id': '<value>',
    'referalli-mode': '<value>',
  },
});
const data = await res.json();
Python
import requests

res = requests.request(
    "GET",
    "https://referalli.com/v1/roi/breakdown?from=&to=&programId=&partnerId=&windowDays=&currency=&format=&by=&limit=&starting_after=&ending_before=&created%5Bgte%5D=&created%5Blte%5D=",
    headers={
    "referalli-version": "<value>",
    "x-org-id": "<value>",
    "referalli-mode": "<value>",
    },
)
data = res.json()
Go
package main

import (
	"fmt"
	"io"
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://referalli.com/v1/roi/breakdown?from=&to=&programId=&partnerId=&windowDays=&currency=&format=&by=&limit=&starting_after=&ending_before=&created%5Bgte%5D=&created%5Blte%5D=", nil)
	req.Header.Set("referalli-version", "<value>")
	req.Header.Set("x-org-id", "<value>")
	req.Header.Set("referalli-mode", "<value>")
	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)
	fmt.Println(string(body))
}
PHP
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://referalli.com/v1/roi/breakdown?from=&to=&programId=&partnerId=&windowDays=&currency=&format=&by=&limit=&starting_after=&ending_before=&created%5Bgte%5D=&created%5Blte%5D=');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['referalli-version: <value>', 'x-org-id: <value>', 'referalli-mode: <value>']);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
Ruby
require 'net/http'
require 'uri'

uri = URI('https://referalli.com/v1/roi/breakdown?from=&to=&programId=&partnerId=&windowDays=&currency=&format=&by=&limit=&starting_after=&ending_before=&created%5Bgte%5D=&created%5Blte%5D=')
req = Net::HTTP::Get.new(uri)
req['referalli-version'] = '<value>'
req['x-org-id'] = '<value>'
req['referalli-mode'] = '<value>'
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
  http.request(req)
end
puts res.body
Java
import java.net.URI;
import java.net.http.*;
import java.net.http.HttpRequest.BodyPublishers;

HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://referalli.com/v1/roi/breakdown?from=&to=&programId=&partnerId=&windowDays=&currency=&format=&by=&limit=&starting_after=&ending_before=&created%5Bgte%5D=&created%5Blte%5D="))
    .header("referalli-version", "<value>")
    .header("x-org-id", "<value>")
    .header("referalli-mode", "<value>")
    .GET()
    .build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
Responses
200 JSON by default; text/csv with ?format=csv.
Example
{
  "object": "string",
  "data": [
    {
      "currency": "string",
      "creditCostMinor": 0,
      "cashAfterMinor": 0,
      "profitAfterMinor": 0,
      "netMinor": 0,
      "roi": 0,
      "paidBackShareBps": 0,
      "medianPaybackDays": 0,
      "grants": 0,
      "profitSources": {},
      "coverage": {
        "creditAppliedReportedBps": null,
        "marginCoveredBps": null,
        "inferredShareBps": null
      },
      "outstandingCreditMinor": 0,
      "outstandingCostIfUsedMinor": 0,
      "key": "string",
      "label": "string",
      "referrals": {
        "count": 0,
        "costMinor": 0,
        "cashCommissionMinor": 0,
        "netMinor": null,
        "roi": null
      }
    }
  ],
  "has_more": true,
  "next_cursor": "string"
}
Schema
objectstringrequired
dataobject[]required
Show child parameters
currencystringrequired
creditCostMinorintegerrequired
Integer minor units (cents).
cashAfterMinorintegerrequired
Integer minor units (cents).
profitAfterMinorintegerrequired
netMinorintegerrequired
roinumberrequired
Profit after ÷ cost, 4 decimals; null with no cost or unknown profit.
paidBackShareBpsintegerrequired
Basis points (10000 = 100%); null when there is nothing to divide by.
medianPaybackDaysnumberrequired
grantsintegerrequired
profitSourcesobjectrequired
coverageobjectrequired
Show child parameters
creditAppliedReportedBpsintegerrequired
Basis points (10000 = 100%); null when there is nothing to divide by.
marginCoveredBpsintegerrequired
Basis points (10000 = 100%); null when there is nothing to divide by.
inferredShareBpsintegerrequired
Basis points (10000 = 100%); null when there is nothing to divide by.
outstandingCreditMinorintegerrequired
Face not yet used, expired or revoked, in the reporting currency.
outstandingCostIfUsedMinorintegerrequired
Outstanding credit priced by each grant's cost model; null when a model needs a margin and none is known.
keystringrequired
labelstringrequired
referralsobject
Partner and program rows: their referrals, both sides, commissions included.
Show child parameters
countintegerrequired
costMinorintegerrequired
Integer minor units (cents).
cashCommissionMinorintegerrequired
Integer minor units (cents).
netMinorintegerrequired
roinumberrequired
Profit after ÷ cost, 4 decimals; null with no cost or unknown profit.
has_morebooleanrequired
Whether another page follows; pass next_cursor as starting_after to get it.
next_cursorstringrequired
400 The request is invalid. error.code is one of:
Example
{
  "error": {
    "code": "validation_error",
    "message": "the body or query failed validation, an unknown field was sent, the body is not valid json, or a session call has no `x-org-id`",
    "details": [
      {
        "code": "invalid_format",
        "path": [
          "destinationUrl"
        ],
        "message": "Invalid URL"
      }
    ],
    "docs_url": "https://referalli.com/docs/errors-and-limits#validation_error"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
401 Missing or invalid credentials. error.code is one of:
Example
{
  "error": {
    "code": "unauthorized",
    "message": "no credentials, an unknown, revoked or expired api key or session, or a signature that did not verify",
    "docs_url": "https://referalli.com/docs/errors-and-limits#unauthorized"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
403 Authenticated, but not allowed. error.code is one of:
Example
{
  "error": {
    "code": "forbidden",
    "message": "the wrong role, a key without the needed scope (the message names it), not a member, a suspended org, or a publishable key from an origin it does not allow",
    "docs_url": "https://referalli.com/docs/errors-and-limits#forbidden"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
404 No such resource. error.code is one of:
Example
{
  "error": {
    "code": "not_found",
    "message": "the resource does not exist in this org (ids from other orgs look the same), a referenced id does not exist, a list cursor is not in the list, or the endpoint does not exist",
    "docs_url": "https://referalli.com/docs/errors-and-limits#not_found"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
429 Rate limited. error.code is one of:
Example
{
  "error": {
    "code": "rate_limited",
    "message": "an endpoint limit or the per-key quota was exceeded",
    "docs_url": "https://referalli.com/docs/errors-and-limits#rate_limited"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
500 Unexpected server error. error.code is one of:
Example
{
  "error": {
    "code": "internal_error",
    "message": "retry with backoff",
    "requestId": "req_8f2c1d4e5a6b7c8d",
    "docs_url": "https://referalli.com/docs/errors-and-limits#internal_error"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
default Any other error, in the same envelope.
Example
{
  "error": {
    "code": "string",
    "message": "string",
    "details": {},
    "requestId": "string",
    "docs_url": "string"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
GEThttps://referalli.com/v1/roi/grants
List credit grants

Each credit grant in view with its status (open, used, expired, revoked) and figures, newest first. Filter by status, role (referee or referrer) and paidBack. from/to select grants by grant date (a date covers its whole UTC day), programId and partnerId narrow them, windowDays overrides each program's attribution window (30, 90, 180, 365, or 0 for lifetime), and currency views one native currency instead of the reporting currency. format=csv returns the same as a CSV file. CSV returns every grant, unpaged.

Auth: an API key with analytics:read (or full), or a session of any role.

Parameters
fromstringquery
Grants (or referrals) from this instant or date, inclusive.
tostringquery
Up to this instant, or through the end of this date (UTC), inclusive.
programIdstringquery
partnerIdstringquery
The grant's partner: the referrer, or the partner of the referee's referral.
windowDaysintegerquery
Attribution window; default each program's setting. 0 = lifetime.
currencystringquery
Default the reporting currency (converted); another code gives that currency only.
formatstringquery
json | csv
statusstringquery
open | used | expired | revoked
rolestringquery
referee | referrer
paidBackstringquery
true | false
limitintegerquery
Items per page, 1 to 100 (default 50). From API version 2026-11-01; ignored under 2026-10-21, where lists are a capped plain array.
= 50
starting_afterstringquery
A cursor: the id of an item (the previous page's next_cursor); returns the items after it. From API version 2026-11-01; ignored under 2026-10-21, where lists are a capped plain array.
ending_beforestringquery
A cursor: returns the items before this item id (the previous page). Not with starting_after. From API version 2026-11-01; ignored under 2026-10-21, where lists are a capped plain array.
created[gte]stringquery
Only items created at or after this time (ISO 8601), on lists of timestamped records. From API version 2026-11-01; ignored under 2026-10-21, where lists are a capped plain array.
created[lte]stringquery
Only items created at or before this time (ISO 8601), on lists of timestamped records. From API version 2026-11-01; ignored under 2026-10-21, where lists are a capped plain array.
referalli-versionstringheader
The API version to run the request under (2026-10-21, 2026-11-01). Default: the API key's pinned version, else 2026-10-21. The header name from before the rename is still accepted; this name wins when both are sent.
2026-10-21 | 2026-11-01
x-org-idstringheader
With a session: the org to act in (the user must be a member). Not used with API keys, which belong to one org.
referalli-modestringheader
test runs a session request against the org's test data. With an API key it must match the key's mode (400 mode_mismatch otherwise). The header name from before the rename is still accepted.
live | test
Code samples
cURL
curl -X GET "https://referalli.com/v1/roi/grants?from=&to=&programId=&partnerId=&windowDays=&currency=&format=&status=&role=&paidBack=&limit=&starting_after=&ending_before=&created%5Bgte%5D=&created%5Blte%5D=" \
  -H "referalli-version: <value>" \
  -H "x-org-id: <value>" \
  -H "referalli-mode: <value>"
TypeScript
const res = await fetch('https://referalli.com/v1/roi/grants?from=&to=&programId=&partnerId=&windowDays=&currency=&format=&status=&role=&paidBack=&limit=&starting_after=&ending_before=&created%5Bgte%5D=&created%5Blte%5D=', {
  method: 'GET',
  headers: {
    'referalli-version': '<value>',
    'x-org-id': '<value>',
    'referalli-mode': '<value>',
  },
});
const data = await res.json();
Python
import requests

res = requests.request(
    "GET",
    "https://referalli.com/v1/roi/grants?from=&to=&programId=&partnerId=&windowDays=&currency=&format=&status=&role=&paidBack=&limit=&starting_after=&ending_before=&created%5Bgte%5D=&created%5Blte%5D=",
    headers={
    "referalli-version": "<value>",
    "x-org-id": "<value>",
    "referalli-mode": "<value>",
    },
)
data = res.json()
Go
package main

import (
	"fmt"
	"io"
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://referalli.com/v1/roi/grants?from=&to=&programId=&partnerId=&windowDays=&currency=&format=&status=&role=&paidBack=&limit=&starting_after=&ending_before=&created%5Bgte%5D=&created%5Blte%5D=", nil)
	req.Header.Set("referalli-version", "<value>")
	req.Header.Set("x-org-id", "<value>")
	req.Header.Set("referalli-mode", "<value>")
	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)
	fmt.Println(string(body))
}
PHP
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://referalli.com/v1/roi/grants?from=&to=&programId=&partnerId=&windowDays=&currency=&format=&status=&role=&paidBack=&limit=&starting_after=&ending_before=&created%5Bgte%5D=&created%5Blte%5D=');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['referalli-version: <value>', 'x-org-id: <value>', 'referalli-mode: <value>']);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
Ruby
require 'net/http'
require 'uri'

uri = URI('https://referalli.com/v1/roi/grants?from=&to=&programId=&partnerId=&windowDays=&currency=&format=&status=&role=&paidBack=&limit=&starting_after=&ending_before=&created%5Bgte%5D=&created%5Blte%5D=')
req = Net::HTTP::Get.new(uri)
req['referalli-version'] = '<value>'
req['x-org-id'] = '<value>'
req['referalli-mode'] = '<value>'
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
  http.request(req)
end
puts res.body
Java
import java.net.URI;
import java.net.http.*;
import java.net.http.HttpRequest.BodyPublishers;

HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://referalli.com/v1/roi/grants?from=&to=&programId=&partnerId=&windowDays=&currency=&format=&status=&role=&paidBack=&limit=&starting_after=&ending_before=&created%5Bgte%5D=&created%5Blte%5D="))
    .header("referalli-version", "<value>")
    .header("x-org-id", "<value>")
    .header("referalli-mode", "<value>")
    .GET()
    .build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
Responses
200 Newest grant first. Pages with limit / starting_after / ending_before; created[gte|lte] filter on the grant date. JSON by default; text/csv with ?format=csv returns every grant in scope, unpaged.
Example
{
  "object": "string",
  "data": [
    {
      "id": "string",
      "source": "referee_reward",
      "role": "referee",
      "status": "open",
      "customerRef": "string",
      "partnerId": "string",
      "referralId": "string",
      "programId": "string",
      "grantCurrency": "string",
      "grantedAt": "2024-01-01T00:00:00Z",
      "expiresAt": "2024-01-01T00:00:00Z",
      "currency": "string",
      "faceMinor": 0,
      "usedMinor": 0,
      "costMinor": 0,
      "cashAfterMinor": 0,
      "profitAfterMinor": 0,
      "netMinor": 0,
      "roi": 0,
      "paidBack": true,
      "paybackDays": 0,
      "profitSource": "event",
      "inferredShareBps": 0,
      "windowDays": 0
    }
  ],
  "has_more": true,
  "next_cursor": "string"
}
Schema
objectstringrequired
dataRoiGrant[]required
Show child parameters
idstringrequired
sourcestringrequired
referee_reward | commission_credit | external | manual
rolestringrequired
referee | referrer
statusstringrequired
open | used | expired | revoked
customerRefstringrequired
partnerIdstringrequired
referralIdstringrequired
programIdstringrequired
grantCurrencystringrequired
grantedAtstringrequired
expiresAtstringrequired
currencystringrequired
faceMinorintegerrequired
Integer minor units (cents).
usedMinorintegerrequired
Integer minor units (cents).
costMinorintegerrequired
Integer minor units (cents).
cashAfterMinorintegerrequired
Integer minor units (cents).
profitAfterMinorintegerrequired
netMinorintegerrequired
roinumberrequired
Profit after ÷ cost, 4 decimals; null with no cost or unknown profit.
paidBackbooleanrequired
paybackDaysintegerrequired
profitSourcestringrequired
event | cost_events | catalog | program | org | none | mixed
inferredShareBpsintegerrequired
windowDaysintegerrequired
has_morebooleanrequired
Whether another page follows; pass next_cursor as starting_after to get it.
next_cursorstringrequired
400 The request is invalid. error.code is one of:
Example
{
  "error": {
    "code": "validation_error",
    "message": "the body or query failed validation, an unknown field was sent, the body is not valid json, or a session call has no `x-org-id`",
    "details": [
      {
        "code": "invalid_format",
        "path": [
          "destinationUrl"
        ],
        "message": "Invalid URL"
      }
    ],
    "docs_url": "https://referalli.com/docs/errors-and-limits#validation_error"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
401 Missing or invalid credentials. error.code is one of:
Example
{
  "error": {
    "code": "unauthorized",
    "message": "no credentials, an unknown, revoked or expired api key or session, or a signature that did not verify",
    "docs_url": "https://referalli.com/docs/errors-and-limits#unauthorized"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
403 Authenticated, but not allowed. error.code is one of:
Example
{
  "error": {
    "code": "forbidden",
    "message": "the wrong role, a key without the needed scope (the message names it), not a member, a suspended org, or a publishable key from an origin it does not allow",
    "docs_url": "https://referalli.com/docs/errors-and-limits#forbidden"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
404 No such resource. error.code is one of:
Example
{
  "error": {
    "code": "not_found",
    "message": "the resource does not exist in this org (ids from other orgs look the same), a referenced id does not exist, a list cursor is not in the list, or the endpoint does not exist",
    "docs_url": "https://referalli.com/docs/errors-and-limits#not_found"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
429 Rate limited. error.code is one of:
Example
{
  "error": {
    "code": "rate_limited",
    "message": "an endpoint limit or the per-key quota was exceeded",
    "docs_url": "https://referalli.com/docs/errors-and-limits#rate_limited"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
500 Unexpected server error. error.code is one of:
Example
{
  "error": {
    "code": "internal_error",
    "message": "retry with backoff",
    "requestId": "req_8f2c1d4e5a6b7c8d",
    "docs_url": "https://referalli.com/docs/errors-and-limits#internal_error"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
default Any other error, in the same envelope.
Example
{
  "error": {
    "code": "string",
    "message": "string",
    "details": {},
    "requestId": "string",
    "docs_url": "string"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
GEThttps://referalli.com/v1/roi/trace/{customerRef}
Trace a customer's value

Every value event of a customer (and the identities linked to them) in order, with the running net, to see exactly how their ROI was computed. format=csv for a file.

Auth: an API key with analytics:read (or full), or a session of any role.

Parameters
customerRefstringpathrequired
windowDaysintegerquery
Attribution window; default each program's setting. 0 = lifetime.
formatstringquery
json | csv
x-org-idstringheader
With a session: the org to act in (the user must be a member). Not used with API keys, which belong to one org.
referalli-modestringheader
test runs a session request against the org's test data. With an API key it must match the key's mode (400 mode_mismatch otherwise). The header name from before the rename is still accepted.
live | test
Code samples
cURL
curl -X GET "https://referalli.com/v1/roi/trace/{customerRef}?windowDays=&format=" \
  -H "x-org-id: <value>" \
  -H "referalli-mode: <value>"
TypeScript
const res = await fetch('https://referalli.com/v1/roi/trace/{customerRef}?windowDays=&format=', {
  method: 'GET',
  headers: {
    'x-org-id': '<value>',
    'referalli-mode': '<value>',
  },
});
const data = await res.json();
Python
import requests

res = requests.request(
    "GET",
    "https://referalli.com/v1/roi/trace/{customerRef}?windowDays=&format=",
    headers={
    "x-org-id": "<value>",
    "referalli-mode": "<value>",
    },
)
data = res.json()
Go
package main

import (
	"fmt"
	"io"
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://referalli.com/v1/roi/trace/{customerRef}?windowDays=&format=", nil)
	req.Header.Set("x-org-id", "<value>")
	req.Header.Set("referalli-mode", "<value>")
	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)
	fmt.Println(string(body))
}
PHP
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://referalli.com/v1/roi/trace/{customerRef}?windowDays=&format=');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['x-org-id: <value>', 'referalli-mode: <value>']);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
Ruby
require 'net/http'
require 'uri'

uri = URI('https://referalli.com/v1/roi/trace/{customerRef}?windowDays=&format=')
req = Net::HTTP::Get.new(uri)
req['x-org-id'] = '<value>'
req['referalli-mode'] = '<value>'
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
  http.request(req)
end
puts res.body
Java
import java.net.URI;
import java.net.http.*;
import java.net.http.HttpRequest.BodyPublishers;

HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://referalli.com/v1/roi/trace/{customerRef}?windowDays=&format="))
    .header("x-org-id", "<value>")
    .header("referalli-mode", "<value>")
    .GET()
    .build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
Responses
200 JSON by default; text/csv with ?format=csv.
Example
{
  "subject": {
    "type": "customer",
    "id": "string",
    "customerRefs": [
      "string"
    ],
    "partnerId": "string"
  },
  "events": [
    {
      "id": "string",
      "kind": "string",
      "occurredAt": "2024-01-01T00:00:00Z",
      "amounts": {},
      "confidence": "reported",
      "source": "string",
      "superseded": true,
      "links": {}
    }
  ],
  "grants": [
    {
      "grantId": "string",
      "role": "referee",
      "currency": "string",
      "faceMinor": 0,
      "usedMinor": 0,
      "costMinor": 0,
      "cashAfterMinor": 0,
      "profitAfterMinor": 0,
      "netMinor": 0,
      "roi": 0,
      "paidBack": true,
      "paybackDays": 0,
      "profitSource": "event",
      "inferredShareBps": 0,
      "windowDays": 0,
      "excluded": [
        {
          "eventId": null,
          "currency": null,
          "reason": null
        }
      ]
    }
  ],
  "runningNet": [
    {
      "at": "2024-01-01T00:00:00Z",
      "netMinor": 0
    }
  ],
  "excluded": [
    {
      "eventId": "string",
      "currency": "string",
      "reason": "string"
    }
  ]
}
Schema
subjectobjectrequired
Show child parameters
typestringrequired
customer | partner
idstringrequired
customerRefsstring[]required
partnerIdstringrequired
eventsobject[]required
Show child parameters
idstringrequired
kindstringrequired
occurredAtstringrequired
amountsobjectrequired
currency plus the minor-unit amounts this kind carries.
confidencestringrequired
reported | extracted | inferred
sourcestringrequired
supersededbooleanrequired
linksobjectrequired
grantsRoiGrantMetrics[]required
Show child parameters
grantIdstringrequired
rolestringrequired
referee | referrer
currencystringrequired
faceMinorintegerrequired
Integer minor units (cents).
usedMinorintegerrequired
Integer minor units (cents).
costMinorintegerrequired
Integer minor units (cents).
cashAfterMinorintegerrequired
Integer minor units (cents).
profitAfterMinorintegerrequired
netMinorintegerrequired
roinumberrequired
Profit after ÷ cost, 4 decimals; null with no cost or unknown profit.
paidBackbooleanrequired
paybackDaysintegerrequired
profitSourcestringrequired
event | cost_events | catalog | program | org | none | mixed
inferredShareBpsintegerrequired
windowDaysintegerrequired
excludedobject[]required
Show child parameters
eventIdstringrequired
currencystringrequired
reasonstringrequired
runningNetobject[]required
One point per event: cumulative credit net (profit after − credit cost) in the reporting currency. Commissions are not in it.
Show child parameters
atstringrequired
netMinorintegerrequired
excludedobject[]required
Rows left out of runningNet: no fx rate into the reporting currency on their date.
Show child parameters
eventIdstringrequired
currencystringrequired
reasonstringrequired
400 The request is invalid. error.code is one of:
Example
{
  "error": {
    "code": "validation_error",
    "message": "the body or query failed validation, an unknown field was sent, the body is not valid json, or a session call has no `x-org-id`",
    "details": [
      {
        "code": "invalid_format",
        "path": [
          "destinationUrl"
        ],
        "message": "Invalid URL"
      }
    ],
    "docs_url": "https://referalli.com/docs/errors-and-limits#validation_error"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
401 Missing or invalid credentials. error.code is one of:
Example
{
  "error": {
    "code": "unauthorized",
    "message": "no credentials, an unknown, revoked or expired api key or session, or a signature that did not verify",
    "docs_url": "https://referalli.com/docs/errors-and-limits#unauthorized"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
403 Authenticated, but not allowed. error.code is one of:
Example
{
  "error": {
    "code": "forbidden",
    "message": "the wrong role, a key without the needed scope (the message names it), not a member, a suspended org, or a publishable key from an origin it does not allow",
    "docs_url": "https://referalli.com/docs/errors-and-limits#forbidden"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
404 No such resource. error.code is one of:
Example
{
  "error": {
    "code": "not_found",
    "message": "the resource does not exist in this org (ids from other orgs look the same), a referenced id does not exist, a list cursor is not in the list, or the endpoint does not exist",
    "docs_url": "https://referalli.com/docs/errors-and-limits#not_found"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
429 Rate limited. error.code is one of:
Example
{
  "error": {
    "code": "rate_limited",
    "message": "an endpoint limit or the per-key quota was exceeded",
    "docs_url": "https://referalli.com/docs/errors-and-limits#rate_limited"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
500 Unexpected server error. error.code is one of:
Example
{
  "error": {
    "code": "internal_error",
    "message": "retry with backoff",
    "requestId": "req_8f2c1d4e5a6b7c8d",
    "docs_url": "https://referalli.com/docs/errors-and-limits#internal_error"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
default Any other error, in the same envelope.
Example
{
  "error": {
    "code": "string",
    "message": "string",
    "details": {},
    "requestId": "string",
    "docs_url": "string"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
GEThttps://referalli.com/v1/roi/partners/{id}/trace
Trace a partner's value

The same trace for a partner's own customer identity (through their externalRef).

Auth: an API key with analytics:read (or full), or a session of any role.

Parameters
idstringpathrequired
windowDaysintegerquery
Attribution window; default each program's setting. 0 = lifetime.
formatstringquery
json | csv
x-org-idstringheader
With a session: the org to act in (the user must be a member). Not used with API keys, which belong to one org.
referalli-modestringheader
test runs a session request against the org's test data. With an API key it must match the key's mode (400 mode_mismatch otherwise). The header name from before the rename is still accepted.
live | test
Code samples
cURL
curl -X GET "https://referalli.com/v1/roi/partners/{id}/trace?windowDays=&format=" \
  -H "x-org-id: <value>" \
  -H "referalli-mode: <value>"
TypeScript
const res = await fetch('https://referalli.com/v1/roi/partners/{id}/trace?windowDays=&format=', {
  method: 'GET',
  headers: {
    'x-org-id': '<value>',
    'referalli-mode': '<value>',
  },
});
const data = await res.json();
Python
import requests

res = requests.request(
    "GET",
    "https://referalli.com/v1/roi/partners/{id}/trace?windowDays=&format=",
    headers={
    "x-org-id": "<value>",
    "referalli-mode": "<value>",
    },
)
data = res.json()
Go
package main

import (
	"fmt"
	"io"
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://referalli.com/v1/roi/partners/{id}/trace?windowDays=&format=", nil)
	req.Header.Set("x-org-id", "<value>")
	req.Header.Set("referalli-mode", "<value>")
	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)
	fmt.Println(string(body))
}
PHP
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://referalli.com/v1/roi/partners/{id}/trace?windowDays=&format=');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['x-org-id: <value>', 'referalli-mode: <value>']);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
Ruby
require 'net/http'
require 'uri'

uri = URI('https://referalli.com/v1/roi/partners/{id}/trace?windowDays=&format=')
req = Net::HTTP::Get.new(uri)
req['x-org-id'] = '<value>'
req['referalli-mode'] = '<value>'
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
  http.request(req)
end
puts res.body
Java
import java.net.URI;
import java.net.http.*;
import java.net.http.HttpRequest.BodyPublishers;

HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://referalli.com/v1/roi/partners/{id}/trace?windowDays=&format="))
    .header("x-org-id", "<value>")
    .header("referalli-mode", "<value>")
    .GET()
    .build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
Responses
200 JSON by default; text/csv with ?format=csv.
Example
{
  "subject": {
    "type": "customer",
    "id": "string",
    "customerRefs": [
      "string"
    ],
    "partnerId": "string"
  },
  "events": [
    {
      "id": "string",
      "kind": "string",
      "occurredAt": "2024-01-01T00:00:00Z",
      "amounts": {},
      "confidence": "reported",
      "source": "string",
      "superseded": true,
      "links": {}
    }
  ],
  "grants": [
    {
      "grantId": "string",
      "role": "referee",
      "currency": "string",
      "faceMinor": 0,
      "usedMinor": 0,
      "costMinor": 0,
      "cashAfterMinor": 0,
      "profitAfterMinor": 0,
      "netMinor": 0,
      "roi": 0,
      "paidBack": true,
      "paybackDays": 0,
      "profitSource": "event",
      "inferredShareBps": 0,
      "windowDays": 0,
      "excluded": [
        {
          "eventId": null,
          "currency": null,
          "reason": null
        }
      ]
    }
  ],
  "runningNet": [
    {
      "at": "2024-01-01T00:00:00Z",
      "netMinor": 0
    }
  ],
  "excluded": [
    {
      "eventId": "string",
      "currency": "string",
      "reason": "string"
    }
  ]
}
Schema
subjectobjectrequired
Show child parameters
typestringrequired
customer | partner
idstringrequired
customerRefsstring[]required
partnerIdstringrequired
eventsobject[]required
Show child parameters
idstringrequired
kindstringrequired
occurredAtstringrequired
amountsobjectrequired
currency plus the minor-unit amounts this kind carries.
confidencestringrequired
reported | extracted | inferred
sourcestringrequired
supersededbooleanrequired
linksobjectrequired
grantsRoiGrantMetrics[]required
Show child parameters
grantIdstringrequired
rolestringrequired
referee | referrer
currencystringrequired
faceMinorintegerrequired
Integer minor units (cents).
usedMinorintegerrequired
Integer minor units (cents).
costMinorintegerrequired
Integer minor units (cents).
cashAfterMinorintegerrequired
Integer minor units (cents).
profitAfterMinorintegerrequired
netMinorintegerrequired
roinumberrequired
Profit after ÷ cost, 4 decimals; null with no cost or unknown profit.
paidBackbooleanrequired
paybackDaysintegerrequired
profitSourcestringrequired
event | cost_events | catalog | program | org | none | mixed
inferredShareBpsintegerrequired
windowDaysintegerrequired
excludedobject[]required
Show child parameters
eventIdstringrequired
currencystringrequired
reasonstringrequired
runningNetobject[]required
One point per event: cumulative credit net (profit after − credit cost) in the reporting currency. Commissions are not in it.
Show child parameters
atstringrequired
netMinorintegerrequired
excludedobject[]required
Rows left out of runningNet: no fx rate into the reporting currency on their date.
Show child parameters
eventIdstringrequired
currencystringrequired
reasonstringrequired
400 The request is invalid. error.code is one of:
Example
{
  "error": {
    "code": "validation_error",
    "message": "the body or query failed validation, an unknown field was sent, the body is not valid json, or a session call has no `x-org-id`",
    "details": [
      {
        "code": "invalid_format",
        "path": [
          "destinationUrl"
        ],
        "message": "Invalid URL"
      }
    ],
    "docs_url": "https://referalli.com/docs/errors-and-limits#validation_error"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
401 Missing or invalid credentials. error.code is one of:
Example
{
  "error": {
    "code": "unauthorized",
    "message": "no credentials, an unknown, revoked or expired api key or session, or a signature that did not verify",
    "docs_url": "https://referalli.com/docs/errors-and-limits#unauthorized"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
403 Authenticated, but not allowed. error.code is one of:
Example
{
  "error": {
    "code": "forbidden",
    "message": "the wrong role, a key without the needed scope (the message names it), not a member, a suspended org, or a publishable key from an origin it does not allow",
    "docs_url": "https://referalli.com/docs/errors-and-limits#forbidden"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
404 No such resource. error.code is one of:
Example
{
  "error": {
    "code": "not_found",
    "message": "the resource does not exist in this org (ids from other orgs look the same), a referenced id does not exist, a list cursor is not in the list, or the endpoint does not exist",
    "docs_url": "https://referalli.com/docs/errors-and-limits#not_found"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
429 Rate limited. error.code is one of:
Example
{
  "error": {
    "code": "rate_limited",
    "message": "an endpoint limit or the per-key quota was exceeded",
    "docs_url": "https://referalli.com/docs/errors-and-limits#rate_limited"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
500 Unexpected server error. error.code is one of:
Example
{
  "error": {
    "code": "internal_error",
    "message": "retry with backoff",
    "requestId": "req_8f2c1d4e5a6b7c8d",
    "docs_url": "https://referalli.com/docs/errors-and-limits#internal_error"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
default Any other error, in the same envelope.
Example
{
  "error": {
    "code": "string",
    "message": "string",
    "details": {},
    "requestId": "string",
    "docs_url": "string"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
GEThttps://referalli.com/v1/roi/patterns
List value patterns

Every value pattern from one detection run, with the matching subjects: credit_only (a referee used their credit and paid no cash after within the window), churn_at_exhaustion (used it up, paid, then stopped), bonus_collector (a partner holding commission credit who never spends their own cash) and negative_partner (a partner whose referrals net below zero). Matches wait until the evidence is in, so young customers are never flagged.

Auth: an API key with analytics:read (or full), or a session of any role.

Parameters
x-org-idstringheader
With a session: the org to act in (the user must be a member). Not used with API keys, which belong to one org.
referalli-modestringheader
test runs a session request against the org's test data. With an API key it must match the key's mode (400 mode_mismatch otherwise). The header name from before the rename is still accepted.
live | test
Code samples
cURL
curl -X GET "https://referalli.com/v1/roi/patterns" \
  -H "x-org-id: <value>" \
  -H "referalli-mode: <value>"
TypeScript
const res = await fetch('https://referalli.com/v1/roi/patterns', {
  method: 'GET',
  headers: {
    'x-org-id': '<value>',
    'referalli-mode': '<value>',
  },
});
const data = await res.json();
Python
import requests

res = requests.request(
    "GET",
    "https://referalli.com/v1/roi/patterns",
    headers={
    "x-org-id": "<value>",
    "referalli-mode": "<value>",
    },
)
data = res.json()
Go
package main

import (
	"fmt"
	"io"
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://referalli.com/v1/roi/patterns", nil)
	req.Header.Set("x-org-id", "<value>")
	req.Header.Set("referalli-mode", "<value>")
	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)
	fmt.Println(string(body))
}
PHP
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://referalli.com/v1/roi/patterns');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['x-org-id: <value>', 'referalli-mode: <value>']);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
Ruby
require 'net/http'
require 'uri'

uri = URI('https://referalli.com/v1/roi/patterns')
req = Net::HTTP::Get.new(uri)
req['x-org-id'] = '<value>'
req['referalli-mode'] = '<value>'
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
  http.request(req)
end
puts res.body
Java
import java.net.URI;
import java.net.http.*;
import java.net.http.HttpRequest.BodyPublishers;

HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://referalli.com/v1/roi/patterns"))
    .header("x-org-id", "<value>")
    .header("referalli-mode", "<value>")
    .GET()
    .build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
Responses
200 OK
Example
{
  "patterns": {
    "credit_only": [
      {
        "subject": {
          "customerRef": null,
          "partnerId": null
        },
        "programId": null,
        "detail": {}
      }
    ],
    "churn_at_exhaustion": [
      {
        "subject": {
          "customerRef": null,
          "partnerId": null
        },
        "programId": null,
        "detail": {}
      }
    ],
    "bonus_collector": [
      {
        "subject": {
          "customerRef": null,
          "partnerId": null
        },
        "programId": null,
        "detail": {}
      }
    ],
    "negative_partner": [
      {
        "subject": {
          "customerRef": null,
          "partnerId": null
        },
        "programId": null,
        "detail": {}
      }
    ]
  }
}
Schema
patternsobjectrequired
Show child parameters
credit_onlyRoiPatternEntry[]required
Show child parameters
subjectobjectrequired
programIdstringrequired
detailobjectrequired
The key numbers behind the match; the keys depend on the pattern.
churn_at_exhaustionRoiPatternEntry[]required
Show child parameters
subjectobjectrequired
programIdstringrequired
detailobjectrequired
The key numbers behind the match; the keys depend on the pattern.
bonus_collectorRoiPatternEntry[]required
Show child parameters
subjectobjectrequired
programIdstringrequired
detailobjectrequired
The key numbers behind the match; the keys depend on the pattern.
negative_partnerRoiPatternEntry[]required
Show child parameters
subjectobjectrequired
programIdstringrequired
detailobjectrequired
The key numbers behind the match; the keys depend on the pattern.
400 The request is invalid. error.code is one of:
Example
{
  "error": {
    "code": "validation_error",
    "message": "the body or query failed validation, an unknown field was sent, the body is not valid json, or a session call has no `x-org-id`",
    "details": [
      {
        "code": "invalid_format",
        "path": [
          "destinationUrl"
        ],
        "message": "Invalid URL"
      }
    ],
    "docs_url": "https://referalli.com/docs/errors-and-limits#validation_error"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
401 Missing or invalid credentials. error.code is one of:
Example
{
  "error": {
    "code": "unauthorized",
    "message": "no credentials, an unknown, revoked or expired api key or session, or a signature that did not verify",
    "docs_url": "https://referalli.com/docs/errors-and-limits#unauthorized"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
403 Authenticated, but not allowed. error.code is one of:
Example
{
  "error": {
    "code": "forbidden",
    "message": "the wrong role, a key without the needed scope (the message names it), not a member, a suspended org, or a publishable key from an origin it does not allow",
    "docs_url": "https://referalli.com/docs/errors-and-limits#forbidden"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
404 No such resource. error.code is one of:
Example
{
  "error": {
    "code": "not_found",
    "message": "the resource does not exist in this org (ids from other orgs look the same), a referenced id does not exist, a list cursor is not in the list, or the endpoint does not exist",
    "docs_url": "https://referalli.com/docs/errors-and-limits#not_found"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
429 Rate limited. error.code is one of:
Example
{
  "error": {
    "code": "rate_limited",
    "message": "an endpoint limit or the per-key quota was exceeded",
    "docs_url": "https://referalli.com/docs/errors-and-limits#rate_limited"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
500 Unexpected server error. error.code is one of:
Example
{
  "error": {
    "code": "internal_error",
    "message": "retry with backoff",
    "requestId": "req_8f2c1d4e5a6b7c8d",
    "docs_url": "https://referalli.com/docs/errors-and-limits#internal_error"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
default Any other error, in the same envelope.
Example
{
  "error": {
    "code": "string",
    "message": "string",
    "details": {},
    "requestId": "string",
    "docs_url": "string"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
GEThttps://referalli.com/v1/roi/patterns/{pattern}
Get a value pattern

The subjects currently matching one pattern, with the detail of each match.

Auth: an API key with analytics:read (or full), or a session of any role.

Parameters
patternstringpathrequired
limitintegerquery
Items per page, 1 to 100 (default 50). From API version 2026-11-01; ignored under 2026-10-21, where lists are a capped plain array.
= 50
starting_afterstringquery
A cursor: the id of an item (the previous page's next_cursor); returns the items after it. From API version 2026-11-01; ignored under 2026-10-21, where lists are a capped plain array.
ending_beforestringquery
A cursor: returns the items before this item id (the previous page). Not with starting_after. From API version 2026-11-01; ignored under 2026-10-21, where lists are a capped plain array.
created[gte]stringquery
Only items created at or after this time (ISO 8601), on lists of timestamped records. From API version 2026-11-01; ignored under 2026-10-21, where lists are a capped plain array.
created[lte]stringquery
Only items created at or before this time (ISO 8601), on lists of timestamped records. From API version 2026-11-01; ignored under 2026-10-21, where lists are a capped plain array.
referalli-versionstringheader
The API version to run the request under (2026-10-21, 2026-11-01). Default: the API key's pinned version, else 2026-10-21. The header name from before the rename is still accepted; this name wins when both are sent.
2026-10-21 | 2026-11-01
x-org-idstringheader
With a session: the org to act in (the user must be a member). Not used with API keys, which belong to one org.
referalli-modestringheader
test runs a session request against the org's test data. With an API key it must match the key's mode (400 mode_mismatch otherwise). The header name from before the rename is still accepted.
live | test
Code samples
cURL
curl -X GET "https://referalli.com/v1/roi/patterns/{pattern}?limit=&starting_after=&ending_before=&created%5Bgte%5D=&created%5Blte%5D=" \
  -H "referalli-version: <value>" \
  -H "x-org-id: <value>" \
  -H "referalli-mode: <value>"
TypeScript
const res = await fetch('https://referalli.com/v1/roi/patterns/{pattern}?limit=&starting_after=&ending_before=&created%5Bgte%5D=&created%5Blte%5D=', {
  method: 'GET',
  headers: {
    'referalli-version': '<value>',
    'x-org-id': '<value>',
    'referalli-mode': '<value>',
  },
});
const data = await res.json();
Python
import requests

res = requests.request(
    "GET",
    "https://referalli.com/v1/roi/patterns/{pattern}?limit=&starting_after=&ending_before=&created%5Bgte%5D=&created%5Blte%5D=",
    headers={
    "referalli-version": "<value>",
    "x-org-id": "<value>",
    "referalli-mode": "<value>",
    },
)
data = res.json()
Go
package main

import (
	"fmt"
	"io"
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://referalli.com/v1/roi/patterns/{pattern}?limit=&starting_after=&ending_before=&created%5Bgte%5D=&created%5Blte%5D=", nil)
	req.Header.Set("referalli-version", "<value>")
	req.Header.Set("x-org-id", "<value>")
	req.Header.Set("referalli-mode", "<value>")
	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)
	fmt.Println(string(body))
}
PHP
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://referalli.com/v1/roi/patterns/{pattern}?limit=&starting_after=&ending_before=&created%5Bgte%5D=&created%5Blte%5D=');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['referalli-version: <value>', 'x-org-id: <value>', 'referalli-mode: <value>']);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
Ruby
require 'net/http'
require 'uri'

uri = URI('https://referalli.com/v1/roi/patterns/{pattern}?limit=&starting_after=&ending_before=&created%5Bgte%5D=&created%5Blte%5D=')
req = Net::HTTP::Get.new(uri)
req['referalli-version'] = '<value>'
req['x-org-id'] = '<value>'
req['referalli-mode'] = '<value>'
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
  http.request(req)
end
puts res.body
Java
import java.net.URI;
import java.net.http.*;
import java.net.http.HttpRequest.BodyPublishers;

HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://referalli.com/v1/roi/patterns/{pattern}?limit=&starting_after=&ending_before=&created%5Bgte%5D=&created%5Blte%5D="))
    .header("referalli-version", "<value>")
    .header("x-org-id", "<value>")
    .header("referalli-mode", "<value>")
    .GET()
    .build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
Responses
200 A page of the list. Under API version 2026-10-21 the body is the plain array instead.
Example
{
  "object": "string",
  "data": [
    {
      "subject": {
        "customerRef": "string",
        "partnerId": "string"
      },
      "programId": "string",
      "detail": {}
    }
  ],
  "has_more": true,
  "next_cursor": "string"
}
Schema
objectstringrequired
dataRoiPatternEntry[]required
Show child parameters
subjectobjectrequired
Show child parameters
customerRefstring
partnerIdstring
programIdstringrequired
detailobjectrequired
The key numbers behind the match; the keys depend on the pattern.
has_morebooleanrequired
Whether another page follows; pass next_cursor as starting_after to get it.
next_cursorstringrequired
400 The request is invalid. error.code is one of:
Example
{
  "error": {
    "code": "validation_error",
    "message": "the body or query failed validation, an unknown field was sent, the body is not valid json, or a session call has no `x-org-id`",
    "details": [
      {
        "code": "invalid_format",
        "path": [
          "destinationUrl"
        ],
        "message": "Invalid URL"
      }
    ],
    "docs_url": "https://referalli.com/docs/errors-and-limits#validation_error"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
401 Missing or invalid credentials. error.code is one of:
Example
{
  "error": {
    "code": "unauthorized",
    "message": "no credentials, an unknown, revoked or expired api key or session, or a signature that did not verify",
    "docs_url": "https://referalli.com/docs/errors-and-limits#unauthorized"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
403 Authenticated, but not allowed. error.code is one of:
Example
{
  "error": {
    "code": "forbidden",
    "message": "the wrong role, a key without the needed scope (the message names it), not a member, a suspended org, or a publishable key from an origin it does not allow",
    "docs_url": "https://referalli.com/docs/errors-and-limits#forbidden"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
404 No such resource. error.code is one of:
Example
{
  "error": {
    "code": "not_found",
    "message": "the resource does not exist in this org (ids from other orgs look the same), a referenced id does not exist, a list cursor is not in the list, or the endpoint does not exist",
    "docs_url": "https://referalli.com/docs/errors-and-limits#not_found"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
429 Rate limited. error.code is one of:
Example
{
  "error": {
    "code": "rate_limited",
    "message": "an endpoint limit or the per-key quota was exceeded",
    "docs_url": "https://referalli.com/docs/errors-and-limits#rate_limited"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
500 Unexpected server error. error.code is one of:
Example
{
  "error": {
    "code": "internal_error",
    "message": "retry with backoff",
    "requestId": "req_8f2c1d4e5a6b7c8d",
    "docs_url": "https://referalli.com/docs/errors-and-limits#internal_error"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
default Any other error, in the same envelope.
Example
{
  "error": {
    "code": "string",
    "message": "string",
    "details": {},
    "requestId": "string",
    "docs_url": "string"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
POSThttps://referalli.com/v1/roi/patterns/{pattern}/review
Open a review for a pattern match

Turns one live pattern match (by customerRef and/or partnerId, optionally programId) into a value_pattern fraud case against its partner, or returns the open case for the same match. Publishes fraud.case_opened. 404 when no such match exists. Audited.

Auth: an API key with analytics:write (or full), or a session with role owner, admin.

Parameters
patternstringpathrequired
Idempotency-Keystringheader
Any unique string up to 255 printable ASCII characters (a UUID). A retry with the same key within 24 hours gets the first response again (with idempotent-replayed: true) and nothing runs twice. The same key on a different request is 422 idempotency_key_reused; while the first is still running, 409 idempotency_in_progress.
x-org-idstringheader
With a session: the org to act in (the user must be a member). Not used with API keys, which belong to one org.
referalli-modestringheader
test runs a session request against the org's test data. With an API key it must match the key's mode (400 mode_mismatch otherwise). The header name from before the rename is still accepted.
live | test
Request body application/json
customerRefstring
partnerIdstring
programIdstring
{
  "customerRef": "string",
  "partnerId": "string",
  "programId": "string"
}
Code samples
cURL
curl -X POST "https://referalli.com/v1/roi/patterns/{pattern}/review" \
  -H "Idempotency-Key: <value>" \
  -H "x-org-id: <value>" \
  -H "referalli-mode: <value>" \
  -H "Content-Type: application/json" \
  -d '{"customerRef":"string","partnerId":"string","programId":"string"}'
TypeScript
const res = await fetch('https://referalli.com/v1/roi/patterns/{pattern}/review', {
  method: 'POST',
  headers: {
    'Idempotency-Key': '<value>',
    'x-org-id': '<value>',
    'referalli-mode': '<value>',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({"customerRef":"string","partnerId":"string","programId":"string"}),
});
const data = await res.json();
Python
import requests

res = requests.request(
    "POST",
    "https://referalli.com/v1/roi/patterns/{pattern}/review",
    headers={
    "Idempotency-Key": "<value>",
    "x-org-id": "<value>",
    "referalli-mode": "<value>",
    "Content-Type": "application/json",
    },
    json={"customerRef": "string", "partnerId": "string", "programId": "string"},
)
data = res.json()
Go
package main

import (
	"fmt"
	"io"
	"net/http"
	"strings"
)

func main() {
	req, _ := http.NewRequest("POST", "https://referalli.com/v1/roi/patterns/{pattern}/review", strings.NewReader(`{"customerRef":"string","partnerId":"string","programId":"string"}`))
	req.Header.Set("Idempotency-Key", "<value>")
	req.Header.Set("x-org-id", "<value>")
	req.Header.Set("referalli-mode", "<value>")
	req.Header.Set("Content-Type", "application/json")
	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)
	fmt.Println(string(body))
}
PHP
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://referalli.com/v1/roi/patterns/{pattern}/review');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Idempotency-Key: <value>', 'x-org-id: <value>', 'referalli-mode: <value>', 'Content-Type: application/json']);
curl_setopt($ch, CURLOPT_POSTFIELDS, '{"customerRef":"string","partnerId":"string","programId":"string"}');
$response = curl_exec($ch);
curl_close($ch);
echo $response;
Ruby
require 'net/http'
require 'uri'

uri = URI('https://referalli.com/v1/roi/patterns/{pattern}/review')
req = Net::HTTP::Post.new(uri)
req['Idempotency-Key'] = '<value>'
req['x-org-id'] = '<value>'
req['referalli-mode'] = '<value>'
req['Content-Type'] = 'application/json'
req.body = '{"customerRef":"string","partnerId":"string","programId":"string"}'
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
  http.request(req)
end
puts res.body
Java
import java.net.URI;
import java.net.http.*;
import java.net.http.HttpRequest.BodyPublishers;

HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://referalli.com/v1/roi/patterns/{pattern}/review"))
    .header("Idempotency-Key", "<value>")
    .header("x-org-id", "<value>")
    .header("referalli-mode", "<value>")
    .header("Content-Type", "application/json")
    .method("POST", BodyPublishers.ofString("{\"customerRef\":\"string\",\"partnerId\":\"string\",\"programId\":\"string\"}"))
    .build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
Responses
200 OK
Example
{
  "id": "string",
  "partnerId": "string",
  "referralId": "string",
  "kind": "string",
  "status": "string",
  "evidence": {},
  "action": "string",
  "createdAt": "2024-01-01T00:00:00Z",
  "resolvedAt": "2024-01-01T00:00:00Z"
}
Schema
idstringrequired
partnerIdstringrequired
referralIdstringrequired
kindstringrequired
statusstringrequired
evidenceGetOpenapiJsonResponserequired
actionstringrequired
createdAtstringrequired
resolvedAtstringrequired
400 The request is invalid. error.code is one of:
Example
{
  "error": {
    "code": "validation_error",
    "message": "the body or query failed validation, an unknown field was sent, the body is not valid json, or a session call has no `x-org-id`",
    "details": [
      {
        "code": "invalid_format",
        "path": [
          "destinationUrl"
        ],
        "message": "Invalid URL"
      }
    ],
    "docs_url": "https://referalli.com/docs/errors-and-limits#validation_error"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
401 Missing or invalid credentials. error.code is one of:
Example
{
  "error": {
    "code": "unauthorized",
    "message": "no credentials, an unknown, revoked or expired api key or session, or a signature that did not verify",
    "docs_url": "https://referalli.com/docs/errors-and-limits#unauthorized"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
403 Authenticated, but not allowed. error.code is one of:
Example
{
  "error": {
    "code": "forbidden",
    "message": "the wrong role, a key without the needed scope (the message names it), not a member, a suspended org, or a publishable key from an origin it does not allow",
    "docs_url": "https://referalli.com/docs/errors-and-limits#forbidden"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
404 No such resource. error.code is one of:
Example
{
  "error": {
    "code": "not_found",
    "message": "the resource does not exist in this org (ids from other orgs look the same), a referenced id does not exist, a list cursor is not in the list, or the endpoint does not exist",
    "docs_url": "https://referalli.com/docs/errors-and-limits#not_found"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
409 The request conflicts with the current state. error.code is one of:
Example
{
  "error": {
    "code": "conflict",
    "message": "a unique value is taken, or the action would break a rule (the message says which)",
    "docs_url": "https://referalli.com/docs/errors-and-limits#conflict"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
422 The request cannot be processed as sent. error.code is one of:
Example
{
  "error": {
    "code": "idempotency_key_reused",
    "message": "the `idempotency-key` was used for a different request",
    "docs_url": "https://referalli.com/docs/errors-and-limits#idempotency_key_reused"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
429 Rate limited. error.code is one of:
Example
{
  "error": {
    "code": "rate_limited",
    "message": "an endpoint limit or the per-key quota was exceeded",
    "docs_url": "https://referalli.com/docs/errors-and-limits#rate_limited"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
500 Unexpected server error. error.code is one of:
Example
{
  "error": {
    "code": "internal_error",
    "message": "retry with backoff",
    "requestId": "req_8f2c1d4e5a6b7c8d",
    "docs_url": "https://referalli.com/docs/errors-and-limits#internal_error"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
default Any other error, in the same envelope.
Example
{
  "error": {
    "code": "string",
    "message": "string",
    "details": {},
    "requestId": "string",
    "docs_url": "string"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
GEThttps://referalli.com/v1/roi/data-quality
Get ROI data quality

How complete the inputs to ROI are over from/to: payments with credit-applied info, products with a margin, partners linked to their own customer id, events excluded for a missing FX rate, and a list of gaps with how to fix each.

Auth: an API key with analytics:read (or full), or a session of any role.

Parameters
fromstringquery
Grants (or referrals) from this instant or date, inclusive.
tostringquery
Up to this instant, or through the end of this date (UTC), inclusive.
formatstringquery
json | csv
x-org-idstringheader
With a session: the org to act in (the user must be a member). Not used with API keys, which belong to one org.
referalli-modestringheader
test runs a session request against the org's test data. With an API key it must match the key's mode (400 mode_mismatch otherwise). The header name from before the rename is still accepted.
live | test
Code samples
cURL
curl -X GET "https://referalli.com/v1/roi/data-quality?from=&to=&format=" \
  -H "x-org-id: <value>" \
  -H "referalli-mode: <value>"
TypeScript
const res = await fetch('https://referalli.com/v1/roi/data-quality?from=&to=&format=', {
  method: 'GET',
  headers: {
    'x-org-id': '<value>',
    'referalli-mode': '<value>',
  },
});
const data = await res.json();
Python
import requests

res = requests.request(
    "GET",
    "https://referalli.com/v1/roi/data-quality?from=&to=&format=",
    headers={
    "x-org-id": "<value>",
    "referalli-mode": "<value>",
    },
)
data = res.json()
Go
package main

import (
	"fmt"
	"io"
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://referalli.com/v1/roi/data-quality?from=&to=&format=", nil)
	req.Header.Set("x-org-id", "<value>")
	req.Header.Set("referalli-mode", "<value>")
	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)
	fmt.Println(string(body))
}
PHP
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://referalli.com/v1/roi/data-quality?from=&to=&format=');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['x-org-id: <value>', 'referalli-mode: <value>']);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
Ruby
require 'net/http'
require 'uri'

uri = URI('https://referalli.com/v1/roi/data-quality?from=&to=&format=')
req = Net::HTTP::Get.new(uri)
req['x-org-id'] = '<value>'
req['referalli-mode'] = '<value>'
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
  http.request(req)
end
puts res.body
Java
import java.net.URI;
import java.net.http.*;
import java.net.http.HttpRequest.BodyPublishers;

HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://referalli.com/v1/roi/data-quality?from=&to=&format="))
    .header("x-org-id", "<value>")
    .header("referalli-mode", "<value>")
    .GET()
    .build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
Responses
200 JSON by default; text/csv with ?format=csv.
Example
{
  "paymentsTotal": 0,
  "paymentsWithCreditInfo": 0,
  "productsWithMargin": 0,
  "productsSeen": 0,
  "partnersLinked": 0,
  "partnersTotal": 0,
  "excludedForFx": 0,
  "gaps": [
    {
      "code": "margin_missing",
      "count": 0,
      "fix": {
        "text": "string",
        "href": "string"
      }
    }
  ]
}
Schema
paymentsTotalintegerrequired
paymentsWithCreditInfointegerrequired
productsWithMarginintegerrequired
productsSeenintegerrequired
partnersLinkedintegerrequired
partnersTotalintegerrequired
excludedForFxintegerrequired
gapsobject[]required
Show child parameters
codestringrequired
margin_missing | credit_applied_unreported | partners_unlinked | fx_rate_missing
countintegerrequired
fixobjectrequired
Show child parameters
textstringrequired
hrefstringrequired
400 The request is invalid. error.code is one of:
Example
{
  "error": {
    "code": "validation_error",
    "message": "the body or query failed validation, an unknown field was sent, the body is not valid json, or a session call has no `x-org-id`",
    "details": [
      {
        "code": "invalid_format",
        "path": [
          "destinationUrl"
        ],
        "message": "Invalid URL"
      }
    ],
    "docs_url": "https://referalli.com/docs/errors-and-limits#validation_error"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
401 Missing or invalid credentials. error.code is one of:
Example
{
  "error": {
    "code": "unauthorized",
    "message": "no credentials, an unknown, revoked or expired api key or session, or a signature that did not verify",
    "docs_url": "https://referalli.com/docs/errors-and-limits#unauthorized"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
403 Authenticated, but not allowed. error.code is one of:
Example
{
  "error": {
    "code": "forbidden",
    "message": "the wrong role, a key without the needed scope (the message names it), not a member, a suspended org, or a publishable key from an origin it does not allow",
    "docs_url": "https://referalli.com/docs/errors-and-limits#forbidden"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
404 No such resource. error.code is one of:
Example
{
  "error": {
    "code": "not_found",
    "message": "the resource does not exist in this org (ids from other orgs look the same), a referenced id does not exist, a list cursor is not in the list, or the endpoint does not exist",
    "docs_url": "https://referalli.com/docs/errors-and-limits#not_found"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
429 Rate limited. error.code is one of:
Example
{
  "error": {
    "code": "rate_limited",
    "message": "an endpoint limit or the per-key quota was exceeded",
    "docs_url": "https://referalli.com/docs/errors-and-limits#rate_limited"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
500 Unexpected server error. error.code is one of:
Example
{
  "error": {
    "code": "internal_error",
    "message": "retry with backoff",
    "requestId": "req_8f2c1d4e5a6b7c8d",
    "docs_url": "https://referalli.com/docs/errors-and-limits#internal_error"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
default Any other error, in the same envelope.
Example
{
  "error": {
    "code": "string",
    "message": "string",
    "details": {},
    "requestId": "string",
    "docs_url": "string"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
POSThttps://referalli.com/v1/value/events
Record value events

Reports up to 500 value facts from your platform: payment, refund, credit_granted, credit_redeemed, credit_expired, credit_revoked, cost or adjustment. Each needs kind, currency, externalId (your stable id, which makes it idempotent) and occurredAt, plus the customer, partner (partnerId or partnerExternalRef), grant, program, product and amount fields (cashMinor, creditAppliedMinor, discountMinor, taxMinor, feesMinor, costMinor, faceMinor) that apply. Each event is validated and recorded on its own: results and errors are by index. A repeat of an externalId with new figures supersedes the earlier one.

Auth: an API key with analytics:write (or full), or a session of any role.

Parameters
Idempotency-Keystringheader
Any unique string up to 255 printable ASCII characters (a UUID). A retry with the same key within 24 hours gets the first response again (with idempotent-replayed: true) and nothing runs twice. The same key on a different request is 422 idempotency_key_reused; while the first is still running, 409 idempotency_in_progress.
x-org-idstringheader
With a session: the org to act in (the user must be a member). Not used with API keys, which belong to one org.
referalli-modestringheader
test runs a session request against the org's test data. With an API key it must match the key's mode (400 mode_mismatch otherwise). The header name from before the rename is still accepted.
live | test
Request body application/json

Up to 500 value events; each is validated and recorded on its own.

eventsobject[]required
{
  "events": [
    {}
  ]
}
Code samples
cURL
curl -X POST "https://referalli.com/v1/value/events" \
  -H "Idempotency-Key: <value>" \
  -H "x-org-id: <value>" \
  -H "referalli-mode: <value>" \
  -H "Content-Type: application/json" \
  -d '{"events":[{}]}'
TypeScript
const res = await fetch('https://referalli.com/v1/value/events', {
  method: 'POST',
  headers: {
    'Idempotency-Key': '<value>',
    'x-org-id': '<value>',
    'referalli-mode': '<value>',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({"events":[{}]}),
});
const data = await res.json();
Python
import requests

res = requests.request(
    "POST",
    "https://referalli.com/v1/value/events",
    headers={
    "Idempotency-Key": "<value>",
    "x-org-id": "<value>",
    "referalli-mode": "<value>",
    "Content-Type": "application/json",
    },
    json={"events": [{}]},
)
data = res.json()
Go
package main

import (
	"fmt"
	"io"
	"net/http"
	"strings"
)

func main() {
	req, _ := http.NewRequest("POST", "https://referalli.com/v1/value/events", strings.NewReader(`{"events":[{}]}`))
	req.Header.Set("Idempotency-Key", "<value>")
	req.Header.Set("x-org-id", "<value>")
	req.Header.Set("referalli-mode", "<value>")
	req.Header.Set("Content-Type", "application/json")
	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)
	fmt.Println(string(body))
}
PHP
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://referalli.com/v1/value/events');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Idempotency-Key: <value>', 'x-org-id: <value>', 'referalli-mode: <value>', 'Content-Type: application/json']);
curl_setopt($ch, CURLOPT_POSTFIELDS, '{"events":[{}]}');
$response = curl_exec($ch);
curl_close($ch);
echo $response;
Ruby
require 'net/http'
require 'uri'

uri = URI('https://referalli.com/v1/value/events')
req = Net::HTTP::Post.new(uri)
req['Idempotency-Key'] = '<value>'
req['x-org-id'] = '<value>'
req['referalli-mode'] = '<value>'
req['Content-Type'] = 'application/json'
req.body = '{"events":[{}]}'
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
  http.request(req)
end
puts res.body
Java
import java.net.URI;
import java.net.http.*;
import java.net.http.HttpRequest.BodyPublishers;

HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://referalli.com/v1/value/events"))
    .header("Idempotency-Key", "<value>")
    .header("x-org-id", "<value>")
    .header("referalli-mode", "<value>")
    .header("Content-Type", "application/json")
    .method("POST", BodyPublishers.ofString("{\"events\":[{}]}"))
    .build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
Responses
200 OK
Example
{
  "results": [
    {
      "index": 0,
      "id": "string",
      "created": true,
      "superseded": [
        "string"
      ]
    }
  ],
  "errors": [
    {
      "index": 0,
      "message": "string"
    }
  ]
}
Schema
resultsobject[]required
Show child parameters
indexintegerrequired
idstringrequired
createdbooleanrequired
supersededstring[]required
errorsobject[]required
Show child parameters
indexintegerrequired
messagestringrequired
400 The request is invalid. error.code is one of:
Example
{
  "error": {
    "code": "validation_error",
    "message": "the body or query failed validation, an unknown field was sent, the body is not valid json, or a session call has no `x-org-id`",
    "details": [
      {
        "code": "invalid_format",
        "path": [
          "destinationUrl"
        ],
        "message": "Invalid URL"
      }
    ],
    "docs_url": "https://referalli.com/docs/errors-and-limits#validation_error"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
401 Missing or invalid credentials. error.code is one of:
Example
{
  "error": {
    "code": "unauthorized",
    "message": "no credentials, an unknown, revoked or expired api key or session, or a signature that did not verify",
    "docs_url": "https://referalli.com/docs/errors-and-limits#unauthorized"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
403 Authenticated, but not allowed. error.code is one of:
Example
{
  "error": {
    "code": "forbidden",
    "message": "the wrong role, a key without the needed scope (the message names it), not a member, a suspended org, or a publishable key from an origin it does not allow",
    "docs_url": "https://referalli.com/docs/errors-and-limits#forbidden"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
404 No such resource. error.code is one of:
Example
{
  "error": {
    "code": "not_found",
    "message": "the resource does not exist in this org (ids from other orgs look the same), a referenced id does not exist, a list cursor is not in the list, or the endpoint does not exist",
    "docs_url": "https://referalli.com/docs/errors-and-limits#not_found"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
409 The request conflicts with the current state. error.code is one of:
Example
{
  "error": {
    "code": "conflict",
    "message": "a unique value is taken, or the action would break a rule (the message says which)",
    "docs_url": "https://referalli.com/docs/errors-and-limits#conflict"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
422 The request cannot be processed as sent. error.code is one of:
Example
{
  "error": {
    "code": "idempotency_key_reused",
    "message": "the `idempotency-key` was used for a different request",
    "docs_url": "https://referalli.com/docs/errors-and-limits#idempotency_key_reused"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
429 Rate limited. error.code is one of:
Example
{
  "error": {
    "code": "rate_limited",
    "message": "an endpoint limit or the per-key quota was exceeded",
    "docs_url": "https://referalli.com/docs/errors-and-limits#rate_limited"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
500 Unexpected server error. error.code is one of:
Example
{
  "error": {
    "code": "internal_error",
    "message": "retry with backoff",
    "requestId": "req_8f2c1d4e5a6b7c8d",
    "docs_url": "https://referalli.com/docs/errors-and-limits#internal_error"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
default Any other error, in the same envelope.
Example
{
  "error": {
    "code": "string",
    "message": "string",
    "details": {},
    "requestId": "string",
    "docs_url": "string"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
POSThttps://referalli.com/v1/value/import
Import value events from CSV

Imports value events from CSV text (up to 10,000 rows and 5 MB, else 413 payload_too_large) with a mapping from column names to event fields (money as <field>Minor or <field>Major). kind applies to every row unless a column maps to it. Up to 500 rows are recorded before the response; a larger file answers 202 with a jobId to poll. dryRun returns the first 20 parsed rows and every row error without recording.

Auth: an API key with analytics:write (or full), or a session of any role.

Parameters
Idempotency-Keystringheader
Any unique string up to 255 printable ASCII characters (a UUID). A retry with the same key within 24 hours gets the first response again (with idempotent-replayed: true) and nothing runs twice. The same key on a different request is 422 idempotency_key_reused; while the first is still running, 409 idempotency_in_progress.
x-org-idstringheader
With a session: the org to act in (the user must be a member). Not used with API keys, which belong to one org.
referalli-modestringheader
test runs a session request against the org's test data. With an API key it must match the key's mode (400 mode_mismatch otherwise). The header name from before the rename is still accepted.
live | test
Request body application/json

CSV text (up to 10000 rows / 5 MB) plus a column-to-field mapping. "kind" applies to every row unless a column maps to kind. Up to 500 rows are recorded before the response; a larger file answers 202 with a jobId to poll at GET /v1/value/import/{jobId}. A dry run is always immediate.

csvstringrequired
mappingobjectrequired
kindstring
payment | refund | credit_granted | credit_redeemed | credit_expired | credit_revoked | cost | adjustment
dryRunboolean
defaultCurrencystring
{
  "csv": "string",
  "mapping": {},
  "kind": "payment",
  "dryRun": true,
  "defaultCurrency": "string"
}
Code samples
cURL
curl -X POST "https://referalli.com/v1/value/import" \
  -H "Idempotency-Key: <value>" \
  -H "x-org-id: <value>" \
  -H "referalli-mode: <value>" \
  -H "Content-Type: application/json" \
  -d '{"csv":"string","mapping":{},"kind":"payment","dryRun":true,"defaultCurrency":"string"}'
TypeScript
const res = await fetch('https://referalli.com/v1/value/import', {
  method: 'POST',
  headers: {
    'Idempotency-Key': '<value>',
    'x-org-id': '<value>',
    'referalli-mode': '<value>',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({"csv":"string","mapping":{},"kind":"payment","dryRun":true,"defaultCurrency":"string"}),
});
const data = await res.json();
Python
import requests

res = requests.request(
    "POST",
    "https://referalli.com/v1/value/import",
    headers={
    "Idempotency-Key": "<value>",
    "x-org-id": "<value>",
    "referalli-mode": "<value>",
    "Content-Type": "application/json",
    },
    json={"csv": "string", "mapping": {}, "kind": "payment", "dryRun": True, "defaultCurrency": "string"},
)
data = res.json()
Go
package main

import (
	"fmt"
	"io"
	"net/http"
	"strings"
)

func main() {
	req, _ := http.NewRequest("POST", "https://referalli.com/v1/value/import", strings.NewReader(`{"csv":"string","mapping":{},"kind":"payment","dryRun":true,"defaultCurrency":"string"}`))
	req.Header.Set("Idempotency-Key", "<value>")
	req.Header.Set("x-org-id", "<value>")
	req.Header.Set("referalli-mode", "<value>")
	req.Header.Set("Content-Type", "application/json")
	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)
	fmt.Println(string(body))
}
PHP
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://referalli.com/v1/value/import');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Idempotency-Key: <value>', 'x-org-id: <value>', 'referalli-mode: <value>', 'Content-Type: application/json']);
curl_setopt($ch, CURLOPT_POSTFIELDS, '{"csv":"string","mapping":{},"kind":"payment","dryRun":true,"defaultCurrency":"string"}');
$response = curl_exec($ch);
curl_close($ch);
echo $response;
Ruby
require 'net/http'
require 'uri'

uri = URI('https://referalli.com/v1/value/import')
req = Net::HTTP::Post.new(uri)
req['Idempotency-Key'] = '<value>'
req['x-org-id'] = '<value>'
req['referalli-mode'] = '<value>'
req['Content-Type'] = 'application/json'
req.body = '{"csv":"string","mapping":{},"kind":"payment","dryRun":true,"defaultCurrency":"string"}'
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
  http.request(req)
end
puts res.body
Java
import java.net.URI;
import java.net.http.*;
import java.net.http.HttpRequest.BodyPublishers;

HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://referalli.com/v1/value/import"))
    .header("Idempotency-Key", "<value>")
    .header("x-org-id", "<value>")
    .header("referalli-mode", "<value>")
    .header("Content-Type", "application/json")
    .method("POST", BodyPublishers.ofString("{\"csv\":\"string\",\"mapping\":{},\"kind\":\"payment\",\"dryRun\":true,\"defaultCurrency\":\"string\"}"))
    .build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
Responses
200 A dry run: the first 20 parsed rows, every row error and the row count. An import of up to 500 rows: what was recorded. A larger file: 202 with a jobId.
Example
{
  "rows": [
    {}
  ],
  "errors": [
    {
      "row": 0,
      "error": "string"
    }
  ],
  "total": 0
}
Option 1
rowsobject[]required
errorsobject[]required
Show child parameters
rowintegerrequired
errorstringrequired
totalintegerrequired
{
  "rows": [
    {}
  ],
  "errors": [
    {
      "row": 0,
      "error": "string"
    }
  ],
  "total": 0
}
Option 2
recordedintegerrequired
duplicatesintegerrequired
errorsobject[]required
Show child parameters
rowintegerrequired
errorstringrequired
{
  "recorded": 0,
  "duplicates": 0,
  "errors": [
    {
      "row": 0,
      "error": "string"
    }
  ]
}
Option 3
jobIdstringrequired
Status 202: the file is recorded in the background; poll GET /v1/value/import/{jobId}.
{
  "jobId": "string"
}
400 The request is invalid. error.code is one of:
Example
{
  "error": {
    "code": "validation_error",
    "message": "the body or query failed validation, an unknown field was sent, the body is not valid json, or a session call has no `x-org-id`",
    "details": [
      {
        "code": "invalid_format",
        "path": [
          "destinationUrl"
        ],
        "message": "Invalid URL"
      }
    ],
    "docs_url": "https://referalli.com/docs/errors-and-limits#validation_error"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
401 Missing or invalid credentials. error.code is one of:
Example
{
  "error": {
    "code": "unauthorized",
    "message": "no credentials, an unknown, revoked or expired api key or session, or a signature that did not verify",
    "docs_url": "https://referalli.com/docs/errors-and-limits#unauthorized"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
403 Authenticated, but not allowed. error.code is one of:
Example
{
  "error": {
    "code": "forbidden",
    "message": "the wrong role, a key without the needed scope (the message names it), not a member, a suspended org, or a publishable key from an origin it does not allow",
    "docs_url": "https://referalli.com/docs/errors-and-limits#forbidden"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
404 No such resource. error.code is one of:
Example
{
  "error": {
    "code": "not_found",
    "message": "the resource does not exist in this org (ids from other orgs look the same), a referenced id does not exist, a list cursor is not in the list, or the endpoint does not exist",
    "docs_url": "https://referalli.com/docs/errors-and-limits#not_found"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
409 The request conflicts with the current state. error.code is one of:
Example
{
  "error": {
    "code": "conflict",
    "message": "a unique value is taken, or the action would break a rule (the message says which)",
    "docs_url": "https://referalli.com/docs/errors-and-limits#conflict"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
413 The body is too large. error.code is one of:
Example
{
  "error": {
    "code": "payload_too_large",
    "message": "a csv import over 5 mb or 10,000 rows",
    "docs_url": "https://referalli.com/docs/errors-and-limits#payload_too_large"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
422 The request cannot be processed as sent. error.code is one of:
Example
{
  "error": {
    "code": "idempotency_key_reused",
    "message": "the `idempotency-key` was used for a different request",
    "docs_url": "https://referalli.com/docs/errors-and-limits#idempotency_key_reused"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
429 Rate limited. error.code is one of:
Example
{
  "error": {
    "code": "rate_limited",
    "message": "an endpoint limit or the per-key quota was exceeded",
    "docs_url": "https://referalli.com/docs/errors-and-limits#rate_limited"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
500 Unexpected server error. error.code is one of:
Example
{
  "error": {
    "code": "internal_error",
    "message": "retry with backoff",
    "requestId": "req_8f2c1d4e5a6b7c8d",
    "docs_url": "https://referalli.com/docs/errors-and-limits#internal_error"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
default Any other error, in the same envelope.
Example
{
  "error": {
    "code": "string",
    "message": "string",
    "details": {},
    "requestId": "string",
    "docs_url": "string"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
GEThttps://referalli.com/v1/value/import/{jobId}
Get a value import job

Progress and result of a background import: status, processed and total rows, recorded and duplicate counts and row errors.

Auth: an API key with analytics:read (or full), or a session of any role.

Parameters
jobIdstringpathrequired
x-org-idstringheader
With a session: the org to act in (the user must be a member). Not used with API keys, which belong to one org.
referalli-modestringheader
test runs a session request against the org's test data. With an API key it must match the key's mode (400 mode_mismatch otherwise). The header name from before the rename is still accepted.
live | test
Code samples
cURL
curl -X GET "https://referalli.com/v1/value/import/{jobId}" \
  -H "x-org-id: <value>" \
  -H "referalli-mode: <value>"
TypeScript
const res = await fetch('https://referalli.com/v1/value/import/{jobId}', {
  method: 'GET',
  headers: {
    'x-org-id': '<value>',
    'referalli-mode': '<value>',
  },
});
const data = await res.json();
Python
import requests

res = requests.request(
    "GET",
    "https://referalli.com/v1/value/import/{jobId}",
    headers={
    "x-org-id": "<value>",
    "referalli-mode": "<value>",
    },
)
data = res.json()
Go
package main

import (
	"fmt"
	"io"
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://referalli.com/v1/value/import/{jobId}", nil)
	req.Header.Set("x-org-id", "<value>")
	req.Header.Set("referalli-mode", "<value>")
	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)
	fmt.Println(string(body))
}
PHP
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://referalli.com/v1/value/import/{jobId}');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['x-org-id: <value>', 'referalli-mode: <value>']);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
Ruby
require 'net/http'
require 'uri'

uri = URI('https://referalli.com/v1/value/import/{jobId}')
req = Net::HTTP::Get.new(uri)
req['x-org-id'] = '<value>'
req['referalli-mode'] = '<value>'
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
  http.request(req)
end
puts res.body
Java
import java.net.URI;
import java.net.http.*;
import java.net.http.HttpRequest.BodyPublishers;

HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://referalli.com/v1/value/import/{jobId}"))
    .header("x-org-id", "<value>")
    .header("referalli-mode", "<value>")
    .GET()
    .build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
Responses
200 OK
Example
{
  "status": "queued",
  "processed": 0,
  "total": 0,
  "recorded": 0,
  "duplicates": 0,
  "errors": [
    {
      "row": 0,
      "error": "string"
    }
  ],
  "error": "string"
}
Schema
statusstringrequired
queued | running | done | failed
processedintegerrequired
Parsed rows handed to recording so far.
totalintegerrequired
Parsed rows to record (rows that failed to parse are only in errors).
recordedintegerrequired
duplicatesintegerrequired
errorsobject[]required
Parse and record errors so far, by spreadsheet row (header is row 1).
Show child parameters
rowintegerrequired
errorstringrequired
errorstring
Why the job failed ('stale': its process stopped).
400 The request is invalid. error.code is one of:
Example
{
  "error": {
    "code": "validation_error",
    "message": "the body or query failed validation, an unknown field was sent, the body is not valid json, or a session call has no `x-org-id`",
    "details": [
      {
        "code": "invalid_format",
        "path": [
          "destinationUrl"
        ],
        "message": "Invalid URL"
      }
    ],
    "docs_url": "https://referalli.com/docs/errors-and-limits#validation_error"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
401 Missing or invalid credentials. error.code is one of:
Example
{
  "error": {
    "code": "unauthorized",
    "message": "no credentials, an unknown, revoked or expired api key or session, or a signature that did not verify",
    "docs_url": "https://referalli.com/docs/errors-and-limits#unauthorized"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
403 Authenticated, but not allowed. error.code is one of:
Example
{
  "error": {
    "code": "forbidden",
    "message": "the wrong role, a key without the needed scope (the message names it), not a member, a suspended org, or a publishable key from an origin it does not allow",
    "docs_url": "https://referalli.com/docs/errors-and-limits#forbidden"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
404 No such resource. error.code is one of:
Example
{
  "error": {
    "code": "not_found",
    "message": "the resource does not exist in this org (ids from other orgs look the same), a referenced id does not exist, a list cursor is not in the list, or the endpoint does not exist",
    "docs_url": "https://referalli.com/docs/errors-and-limits#not_found"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
429 Rate limited. error.code is one of:
Example
{
  "error": {
    "code": "rate_limited",
    "message": "an endpoint limit or the per-key quota was exceeded",
    "docs_url": "https://referalli.com/docs/errors-and-limits#rate_limited"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
500 Unexpected server error. error.code is one of:
Example
{
  "error": {
    "code": "internal_error",
    "message": "retry with backoff",
    "requestId": "req_8f2c1d4e5a6b7c8d",
    "docs_url": "https://referalli.com/docs/errors-and-limits#internal_error"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
default Any other error, in the same envelope.
Example
{
  "error": {
    "code": "string",
    "message": "string",
    "details": {},
    "requestId": "string",
    "docs_url": "string"
  }
}
Schema
errorobjectrequired
Show child parameters
codestringrequired
messagestringrequired
details
requestIdstring
docs_urlstringrequired
The docs entry for this error code: what it means and how to fix it.
Updated