Integration handoff
Dedicated revocable credential, verified intake field, 12 synthetic fixtures and the nine-attribute mapping. Synthetic data only, no bureau inquiries, no lender submissions, no client communications.
Fixtures carry the expected status, the credential state under test, the request and the sanitized response. No credential value appears in any file.
Authorization: Bearer pfmaia.<key_id>.<secret>read:credit_result. It cannot pull credit, submit to a lender, or reach any other function.The token belongs in a Make connection, never in the blueprint: HTTP → Make an API Key Auth request, parameter Authorization, value Bearer pfmaia.…, placement header.
Acceptance check before activation: the exported blueprint contains zero pfmaia. occurrences and the module references an opaque connection id.
PushFi cannot read Make blueprints, so this check is operator-attested, not verified here.
makeLeadsApi returns loan_application_id as a top-level field of the response body, for both submission types.
Make path: {{1.loan_application_id}} when the intake module is module 1. It is the system UUID, not the display application number.
{
"success": true,
"submission_type": "intake",
"customer_id": "fx-cust-0001",
"loan_application_id": "fx-app-0001",
"created_or_updated": "created",
"matched_by": "owner_email"
}| PushFi field | Type | Existing Make input | Verdict | Note |
|---|---|---|---|---|
| revolving_accounts | int (count) | none (revolving_balances = $, credit_utilization = %) | incompatible | Name-similar, meaning different. Mapping a count into revolving_balances would corrupt debt figures. |
| mortgage_accounts | int (count) | none | missing | No input slot exists. |
| derogatories | int (count) | credit_profile.negative_items | partial | Safe only if consumed as a plain count: PushFi counts collections and late payments separately, so mapping all three double-counts. |
| collections_count | int (count) | none distinct (absorbed by negative_items) | missing | Cannot be recovered downstream once folded into a single count. |
| late_payments_count | int (count) | none distinct (absorbed by negative_items) | missing | Same constraint as collections_count. |
| bankruptcy | boolean | none | missing | Cannot be inferred from a count. |
| foreclosure | boolean | none | missing | Cannot be inferred from a count. |
| monthly_debt_obligations | number (currency) | none | missing | No debt-service input exists today. |
| unsecured_debt | number (currency) | none (revolving_balances writes to business_liens_total) | incompatible | A different concept. Must not be aliased to revolving_balances. |
| PushFi field | Type | Existing Make input | Verdict | Note |
|---|---|---|---|---|
| credit_score | credit_profile.fico_score | compatible | Same meaning. | |
| bureau | credit_profile.bureau | compatible | Provider label. | |
| acquired_at / age_days / valid_through | none | missing | No freshness input. Gate on available + reusable instead of recomputing age. | |
| credit_profile.inquiries (Make side) | — not returned by PushFi — | unavailable | Keep Make's own value; do not derive it. Extend the contract deliberately if needed. | |
| credit_profile.credit_tier (Make side) | — not returned by PushFi — | unavailable | PushFi returns the score, not a band. Derive the tier or keep the existing source. |
POST https://push-fi-loan-orchestration-d379ddba.base44.app/functions/getExistingCreditResult
Content-Type: application/json
Authorization: Bearer pfmaia.<key_id>.<secret>
{ "application_id": "fx-app-0001",
"owner_applicant_id": "fx-owner-0001" }| HTTP | Reason | Handling |
|---|---|---|
| 400 | INVALID_REQUEST | Fix the mapping, do not retry |
| 401 | INVALID_CREDENTIAL | Do not retry, re-bind connection |
| 401 | CREDENTIAL_REVOKED / INACTIVE / EXPIRED | Stop, request rotation |
| 403 | SCOPE_NOT_PERMITTED | Stop, wrong credential |
| 403 | APPLICATION_NOT_PERMITTED | Stop, expected refusal |
| 404 | APPLICATION_NOT_FOUND | Create nothing, fix the id |
| 429 | RATE_LIMITED | Wait Retry-After, then retry |
| 500 | SERVER_ERROR | Retry once after 30s, then escalate |
Idempotency: pure read, always writes_performed: 0. Repeating a request returns the same underlying result. Retry only on 429 (after Retry-After) or once on 5xx. Read before pull: available: false routes to human review, never to an automatic pull.
testMaiaReadOnlyCredentialContract
16 / 16 passed · provider calls 0 · Synthetic rows only, removed after run
testCreditPullAuthAndReuse
23 / 23 passed · provider calls 0 · 0 writes performed
Covered: missing/wrong/revoked/expired credential, scope and allowlist refusal, rotation, rate limit, credential-domain separation, PII-free audit on allowed and denied attempts, and a mutation guard proving application, credit-snapshot, checkpoint, acquisition and authorization counts are unchanged.
negative_items convention, then add the seven missing Make inputs.inquiries and credit_tier are not returned by this endpoint — keep Make's own source or extend the contract deliberately.application_scope: all to an allowlist before general rollout.