Recipes

These patterns add validation around the intentionally small client API.

Production-oriented value wrapper

from datetime import date
import os

import pacifico


def get_snapshot(tickers):
    today = date.today()
    frame = pacifico.request(
        token=os.environ["PACIFICO_API_TOKEN"],
        ticker=list(tickers),
        dateStart=today,
        dateEnd=today,
        timeOut=600,
        timeFrecuency=1.0,
        format="dataFrame",
    )

    if "Ticker" not in frame.columns:
        raise RuntimeError("Unexpected Pacífico value schema.")
    if frame["Ticker"].eq("Error").any():
        raise RuntimeError("Pacífico returned a value error row.")
    return frame

Explicit dates prevent stale import-time defaults. A list preserves the client-supported multi-ticker path.

Metadata-driven selection

catalog = pacifico.request(
    "token.key",
    ticker="metadata",
)

eligible = catalog.loc[
    (catalog["Country"] == "Chile")
    & (catalog["Market"] == "RF")
    & (catalog["Family"] == "BCP"),
    "Ticker",
].dropna().drop_duplicates()

values = pacifico.request(
    "token.key",
    ticker=eligible.head(20).tolist(),
)

Cap batch sizes according to the workload rather than sending an unbounded catalog in one request.

Enforce the author client-side

Current server paths do not uniformly enforce source/version filters. Validate the result:

requested_author = "Pacifico"
expected_author_label = "Pacifico"

data = pacifico.request(
    "token.key",
    ticker="CHILE",
    author=requested_author,
)

scenario = data["Scenario"].astype(str).str.casefold()
label = expected_author_label.casefold()
allowed = scenario.eq(label) | scenario.str.startswith(label + "-")
unexpected = data[~allowed]
if not unexpected.empty:
    raise RuntimeError("Response contains an unexpected scenario.")

The server presents the public author under the display label Pacifico, normalizing any legacy internal provider identifier. A named version can extend it to Pacifico-<VERSION> (and may add a scenario suffix), so validate either the exact expected scenario or the author-label prefix appropriate to your policy. For reports, apply the same pattern to Author.

Select one field and pivot

history = pacifico.request(
    "token.key",
    ticker=["CHILE", "BCP0600323"],
    dateStart=start,
    dateEnd=end,
    fieldType="Price",
)

prices = history.pivot_table(
    index="Date Effective",
    columns="Ticker",
    values="Value",
    aggfunc="last",
)

Choose aggfunc deliberately. Multiple publications, scenarios, fixings, or tenors can otherwise collide at the same effective time.

Validate a historical boundary

effective = history["Date Effective"]

if not effective.empty:
    returned_dates = effective.dt.date
    if returned_dates.min() < start or returned_dates.max() > end:
        raise RuntimeError("Response falls outside the requested interval.")

This detects out-of-range output, but not a normalized request that returns a valid subset. Add domain-specific expected-date checks for audit-sensitive pipelines.

Separate report values by type

reports = pacifico.request(
    "token.key",
    item="97004000-5",
)

numbers = reports[
    reports["Value Type"].isin(["Integer", "Double"])
].copy()

text = reports[
    reports["Value Type"] == "String"
].copy()

Do not cast the full mixed Value column to a single dtype.

Keep raw payloads during onboarding

When adding a new ticker family, report document, or application:

import json

raw = pacifico.request(
    "token.key",
    document="<DOCUMENT>",
    item="<ITEM>",
    format="json",
)

decoded = json.loads(raw)
if not isinstance(decoded, (dict, list)):
    raise RuntimeError("Unexpected top-level JSON type.")

Review the sanitized raw schema, then implement and test DataFrame assumptions.

Inspect an application before running it

contract = pacifico.request(
    "token.key",
    app="<APPLICATION_NAME>",
    help=True,
)

types = contract.loc[
    contract["Subsection"] == "Type",
    ["Section", "Value"],
]
print(types)

Only send approved arguments after checking the current contract. Never use a credential file as a generic File argument.

Add bounded retries outside the client

import random
import time

import requests


def request_with_retry(request_call, attempts=3):
    for attempt in range(attempts):
        try:
            return request_call()
        except (requests.ConnectionError, requests.Timeout):
            if attempt + 1 == attempts:
                raise
            delay = (2 ** attempt) + random.random()
            time.sleep(delay)

Use this only when duplicate execution is safe. Do not broadly catch every exception: TypeError, ValueError, authentication failures, and schema failures need correction rather than retry.

Export with schema checks

required = {
    "Scenario",
    "Date Publication",
    "Date Effective",
    "Ticker",
    "Value",
    "Field",
}

missing = required.difference(data.columns)
if missing:
    raise RuntimeError(f"Missing columns: {sorted(missing)}")

data.to_parquet("outputs/value_snapshot.parquet", index=False)

Parquet export is performed by pandas and requires a compatible optional engine. It is separate from the client's built-in CSV/text writer.