{"openapi":"3.1.0","info":{"title":"Made Card Partners API","description":"# Overview\n\nThe Made Card Partners API lets a mortgage, real estate, or moving company offer Made Card to its own customers.\n\n- **Send them to Made.** You open a Made-hosted application. The customer creates their Made login there. You never collect an SSN, income, or card number.\n- **Stay connected.** Once the customer has a Made login, you receive a customer `access_token` (`link_...`). It stays valid until Made revokes it, so later visits do not ask for a Made password.\n- **Open Made Card.** A launch URL opens Made Card already signed in as that customer.\n- **Read the card.** Linked customers, transactions, payments, and rewards are available read-only.\n\nCustomers stay Made Card customers. Partner credentials cannot create payments, change an account, or read identity documents.\n\n## How the pieces fit\n\n1. Your server authenticates with `POST /v1/partners/auth` and gets a partner JWT.\n2. Your server starts a link session with `POST /v1/partners/link/sessions`.\n3. Your web page opens the returned `link_url` with Made Link, the web SDK. The customer applies on Made.\n4. Made Link calls your `onSuccess` with a one-time `public_token`. Your page sends it to your server.\n5. Your server exchanges it with `POST /v1/partners/link/token` and stores the customer `access_token`.\n6. Later, your server calls `POST /v1/partners/sessions/launch` or the read-only `GET` endpoints.\n\n## See it working\n\nNorthstar Home Loans (demo), at https://madepartner.com, is a sample partner built on this API and Made Link on staging. Open an account there and apply for Made Card to see every step from the customer's side. Its developer page shows the code behind each step.\n\n## Getting credentials\n\nApply on the Made Card partner site. Made reviews every application and emails you the decision. Once approved, sign in to the partner portal to see your `client_id` and `client_secret`. The secret is shown once. Keep it on your server. Questions: partners@madecard.com.\n\n# Quickstart\n\nConnect one customer end to end on staging. Replace the placeholders with your staging credentials.\n\n## 1. Get a partner JWT\n\n```bash\ncurl -X POST https://staging-api.getmcard.com/v1/partners/auth \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"client_id\": \"pk_yourcompany\", \"client_secret\": \"sk_...\"}'\n```\n\n```json\n{\n  \"error\": null,\n  \"message\": \"Authentication successful\",\n  \"data\": {\n    \"access_token\": \"eyJhbGciOi...\",\n    \"token_type\": \"bearer\",\n    \"expires_in\": 3600,\n    \"partner_id\": \"3d776894-8658-805d-9c11-dd9f326891a1\",\n    \"slug\": \"yourcompany\"\n  }\n}\n```\n\nSend `data.access_token` as `Authorization: Bearer <token>` on every other call. Request a new one before `expires_in` runs out.\n\n## 2. Start a link session\n\n```bash\ncurl -X POST https://staging-api.getmcard.com/v1/partners/link/sessions \\\n  -H \"Authorization: Bearer $PARTNER_JWT\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"kind\": \"apply\",\n    \"prefill\": {\n      \"first_name\": \"Ada\",\n      \"last_name\": \"Lovelace\",\n      \"email\": \"ada@example.com\",\n      \"address_line_1\": \"1 Main St\",\n      \"city\": \"Virginia Beach\",\n      \"state\": \"VA\",\n      \"zipcode\": \"23451\"\n    },\n    \"lock_fields\": [\"first_name\", \"last_name\", \"email\", \"address\"]\n  }'\n```\n\nThe response is HTTP 201 and contains `link_url`. It expires in 60 minutes.\n\n## 3. Open it in the browser\n\n```html\n<script src=\"https://staging-app.madecard.com/sdk/v1/made-link.js\"></script>\n<button id=\"apply\" disabled>Apply for Made Card</button>\n<script>\n  const button = document.getElementById(\"apply\");\n  let made;\n  fetch(\"/made/link-session\", { method: \"POST\" })\n    .then((r) => r.json())\n    .then(({ link_url }) => {\n      made = MadeLink.create({\n        linkUrl: link_url,\n        onSuccess: (publicToken) =>\n          fetch(\"/made/exchange\", {\n            method: \"POST\",\n            headers: { \"Content-Type\": \"application/json\" },\n            body: JSON.stringify({ public_token: publicToken }),\n          }),\n        onExit: (error) => console.log(\"Made Link ended:\", error ? error.code : \"closed by the customer\"),\n      });\n      button.disabled = false;\n    });\n  button.addEventListener(\"click\", () => made.open());\n</script>\n```\n\n`/made/link-session` and `/made/exchange` are routes on your own server. The browser never sees your partner JWT, `client_secret`, or the customer `access_token`. The session is created before the click so `open()` runs inside the click handler, where browsers allow new windows. The Web SDK page has the full example.\n\n## 4. Exchange the public token\n\n```bash\ncurl -X POST https://staging-api.getmcard.com/v1/partners/link/token \\\n  -H \"Authorization: Bearer $PARTNER_JWT\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"public_token\": \"public_...\"}'\n```\n\nStore `data.access_token` (`link_...`) and `data.user_id` against your own customer record.\n\n## 5. Open Made Card on a later visit\n\n```bash\ncurl -X POST https://staging-api.getmcard.com/v1/partners/sessions/launch \\\n  -H \"Authorization: Bearer $PARTNER_JWT\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"access_token\": \"link_...\", \"target_path\": \"/dashboard/home\"}'\n```\n\nThe response is HTTP 201. Open `data.launch_url` within 5 minutes, for example with `MadeLink.openLaunchUrl(launch_url)`. The customer lands in Made Card already signed in.\n\n# Environments\n\n| | Staging | Production |\n|---|---|---|\n| API base URL | `https://staging-api.getmcard.com/v1` | `https://api.getmcard.com/v1` |\n| Made Link script | `https://staging-app.madecard.com/sdk/v1/made-link.js` | `https://app.madecard.com/sdk/v1/made-link.js` |\n| Partner portal | `https://test-partners.madecard.com` | `https://partners.madecard.com` |\n| Docs | `https://staging-api.getmcard.com/partners/docs` | `https://api.getmcard.com/partners/docs` |\n| OpenAPI | `https://staging-api.getmcard.com/partners/openapi.json` | `https://api.getmcard.com/partners/openapi.json` |\n\nStaging and production credentials are separate. A staging `client_id` does not work in production. Testing and go-live covers how staging differs.\n\nAll requests and responses are JSON over HTTPS.\n\nThe original `partner-link.js` script (`Made.link`) still works at `/partner-link.js` on both hosts. New integrations should use Made Link.\n\n# Auth and tokens\n\nEvery endpoint except `POST /v1/partners/auth` needs a partner JWT in the `Authorization` header:\n\n```\nAuthorization: Bearer <partner_jwt>\n```\n\nGet one by exchanging your `client_id` and `client_secret` at `POST /v1/partners/auth`. It lasts about 60 minutes (`expires_in`, in seconds). Cache it on your server and request a new one shortly before it expires.\n\n## Tokens at a glance\n\n| Token | Who holds it | Lifetime | Used for |\n|---|---|---|---|\n| Partner JWT | Your server | About 60 minutes | `Authorization: Bearer` on every partner call |\n| `public_token` (`public_...`) | Your `onSuccess` callback, then your server | 10 minutes, single use | Exchanging for the customer `access_token` |\n| Customer `access_token` (`link_...`) | Your server | Until Made revokes it | Identifying one linked customer in request bodies |\n| Launch URL | The customer's browser | 5 minutes, single use | Opening Made Card signed in |\n\nThe customer `access_token` goes in the JSON body of `link/refresh` and `sessions/launch`. It is never an `Authorization` header, and it cannot call Made's customer APIs.\n\n## Keep secrets on your server\n\n- `client_secret`, the partner JWT, and every `link_...` token belong on your server only.\n- Only `link_url`, `public_token`, and `launch_url` pass through the browser, and each is short-lived.\n\n# Apply and link\n\n## Start a session\n\n`POST /v1/partners/link/sessions` returns HTTP 201 with a `link_url` that is valid for 60 minutes. It stops working once the customer is linked.\n\n- `kind: \"apply\"` is the normal path for a customer who is new to Made Card.\n- `kind: \"login\"` is for recovery only: you lost the stored `access_token`, Made revoked the link, or an existing Made customer is connecting to you for the first time.\n- `prefill` fills the application with what you already know: `first_name`, `last_name`, `email`, `phone`, `address_line_1`, `address_line_2`, `city`, `state`, `zipcode`. Every field is optional.\n- `lock_fields` makes prefilled values binding. Allowed values are `first_name`, `last_name`, `email`, and `address`. The address lock checks `address_line_1`, `city`, `state`, and `zipcode`. If the customer's Made profile does not match, the session does not complete, the Made window tells the customer, and your page gets `onExit` with `IDENTITY_MISMATCH`. A lock applies only to a field you prefill. Omit `lock_fields` or send `[]` to lock all four; to leave a field editable, list only the others. Any other name returns `PRTN_0031`.\n- `partner_agent_id` is an optional ID Made assigns to one of your loan officers or agents. Leave it `null` unless Made gave you one. An ID that is not one of yours returns `PRTN_0030`.\n\n### Prefill formats\n\nMade trims every value and treats an empty string as not sent. A value in the wrong format, or a field Made does not know (such as `zip` or `lockFields`), returns HTTP 422 and no session is created.\n\nAn `apply` session also checks each value against the Made application's own rules, because the customer cannot change a locked value to get past the application. A `login` session checks only the format, so it can still match an existing customer's profile.\n\n| Field | Format | Also for `apply` |\n|---|---|---|\n| `first_name`, `last_name` | Up to 100 characters | 2 to 50 characters, only letters and spaces. `O'Brien` and `Smith-Jones` are refused |\n| `address_line_1` | Up to 200 characters | 5 to 40 characters, and a street address: not a P.O. Box, PMB, or registered agent |\n| `address_line_2` | Up to 200 characters | Up to 40 characters, and not a P.O. Box, PMB, or registered agent |\n| `city` | Up to 100 characters | Only letters, spaces, hyphens, and apostrophes. `St. Louis` is refused; `St Louis` is fine |\n| `email` | An email address | |\n| `phone` | A US mobile number. Made removes spaces, dashes, dots, parentheses, and a leading `+1` or `1`, then requires 10 digits: `(757) 555-0123` is stored as `7575550123` | |\n| `state` | A two-letter US state or territory code, in any case: `va` is stored as `VA` | One of the 50 states or `DC` |\n| `zipcode` | Five digits. A ZIP+4 such as `23451-1234` is stored as `23451` | |\n\nIf a value such as a name with an apostrophe does not fit, leave that field out and the customer types it on the application.\n\nThe session response returns `prefill` as Made stored it.\n\n## Open it with Made Link\n\nLoad the Made Link script (see Web SDK), create a handler with the `link_url`, and call `open()` from the customer's click:\n\n```js\nconst made = MadeLink.create({\n  linkUrl: link_url, // from POST /v1/partners/link/sessions\n  onSuccess: (publicToken, metadata) => { /* send publicToken to your server */ },\n  onExit: (error, metadata) => { /* error is null, or { code: \"USER_CLOSED\" | ... } */ },\n});\nbutton.addEventListener(\"click\", () => made.open());\n```\n\n- `onSuccess` fires once with the `publicToken`. For `kind: \"apply\"` that happens as soon as the customer has a Made login; the Made window stays open while they finish the application.\n- For `kind: \"login\"`, the Made window asks the customer to sign in to Made Card the way they usually do: a one-time code, a password, or a passkey, and their second factor if they set one up. `onSuccess` fires once they are signed in, and the window then closes itself.\n- `onExit` fires once if the flow ends without success, with a code such as `POPUP_BLOCKED`, `USER_CLOSED`, or `SESSION_EXPIRED`. The Web SDK page lists every code.\n\n## Allowed origins\n\nMade returns the `public_token` only to a page on one of your allowed origins. The session response lists them in `allowed_origins`.\n\n- An origin is `https://` plus the host and an optional port, with no path: `https://www.yourcompany.com`. `http://` works only for `localhost`.\n- Add every site that opens Made Link, including staging and local development. Up to 20.\n- Manage the list in the partner portal after you sign in. Made starts it with your application's website.\n- From any other page, the Made window tells the customer, no `public_token` is issued, and your page gets `onExit` with `ORIGIN_NOT_ALLOWED`.\n\n## Exchange the public token\n\n`POST /v1/partners/link/token` with `{ \"public_token\": \"public_...\" }` returns the customer `access_token` (`link_...`) and `user_id`. The `public_token` works once and expires 10 minutes after the customer finishes.\n\nStore the `access_token` against your customer. `expires_in` is `null` because the link does not expire on a timer. It stays valid until Made revokes it. Linking the same customer again replaces the previous token.\n\n## Rotate the token\n\n`POST /v1/partners/link/refresh` with `{ \"access_token\": \"link_...\" }` issues a new `link_...` for the same customer. The previous token stops working immediately. The customer is not involved.\n\n## Attribution\n\nWhen a customer completes a link session, Made records you as the partner that brought them if they created their Made login in your `apply` session, or if Made has no channel for them yet:\n\n- The customer's channel is set to your partner slug. That is also how `GET /v1/partners/customers` finds customers who applied through you without an active link.\n- If you sent `partner_agent_id` and the customer has no loan officer or agent yet, that agent is recorded on the customer.\n\nThe first attribution stays. A customer who had a Made login before your session, or who came through another partner or agent, is not moved to you, but you can still read them while your link is active.\n\n# Web SDK\n\nMade Link is a small script with no dependencies. It opens the Made-hosted application in a window over your page and tells your page how it ended. Your server still makes every API call; the script only handles the browser side.\n\n## Load the script\n\n| | Staging | Production |\n|---|---|---|\n| Latest 1.x | `https://staging-app.madecard.com/sdk/v1/made-link.js` | `https://app.madecard.com/sdk/v1/made-link.js` |\n| Pinned 1.0.0 | `https://staging-app.madecard.com/sdk/v1/made-link@1.0.0.js` | `https://app.madecard.com/sdk/v1/made-link@1.0.0.js` |\n| TypeScript types | `https://staging-app.madecard.com/sdk/v1/made-link.d.ts` | `https://app.madecard.com/sdk/v1/made-link.d.ts` |\n\nA pinned file never changes, so you can check it with an integrity hash:\n\n```html\n<script\n  src=\"https://app.madecard.com/sdk/v1/made-link@1.0.0.js\"\n  integrity=\"sha384-fRjOnr9KxuJAAY+Ump/Gfx7Js/uSwQxb82AoHda8F5tR73rLzBqCFZTGET41xVMs\"\n  crossorigin=\"anonymous\"\n></script>\n```\n\nThe latest file follows the newest 1.x release and is cached for 5 minutes. The script defines `window.MadeLink`.\n\n## Full example\n\nCreate the link session before the customer clicks, so the click handler can open the Made window right away. Browsers block windows that open after a network wait.\n\n```html\n<button id=\"apply\" disabled>Apply for Made Card</button>\n<p id=\"status\" role=\"status\"></p>\n\n<script src=\"https://staging-app.madecard.com/sdk/v1/made-link.js\"></script>\n<script>\n  const button = document.getElementById(\"apply\");\n  const status = document.getElementById(\"status\");\n  let made = null;\n\n  // /made/link-session and /made/exchange are routes on your server. The browser never sees\n  // your client_secret, your partner JWT, or the customer's link_ token.\n  async function prepare() {\n    const { link_url } = await fetch(\"/made/link-session\", { method: \"POST\" }).then((r) => r.json());\n    if (made) made.destroy();\n    made = MadeLink.create({\n      linkUrl: link_url,\n      onSuccess: async (publicToken, metadata) => {\n        await fetch(\"/made/exchange\", {\n          method: \"POST\",\n          headers: { \"Content-Type\": \"application/json\" },\n          body: JSON.stringify({ public_token: publicToken }),\n        });\n        status.textContent = \"Your Made Card account is connected.\";\n      },\n      onExit: (error, metadata) => {\n        if (!error || error.code === \"USER_CLOSED\") status.textContent = \"You can apply any time.\";\n        else if (error.code === \"SESSION_EXPIRED\") prepare();\n        else status.textContent = \"Made Card could not open here. Please contact us.\";\n      },\n      onEvent: (eventName, metadata) => console.log(\"Made Link\", eventName, metadata),\n    });\n    button.disabled = false;\n  }\n\n  button.addEventListener(\"click\", () => made.open());\n  prepare();\n</script>\n```\n\nA `link_url` lasts 60 minutes. If your page can stay open longer, call `prepare()` again before then.\n\n## API\n\n`MadeLink.create(options)` returns a handler. It throws a `TypeError` if `linkUrl` is not a `link_url` from `POST /v1/partners/link/sessions`.\n\n| Option | Called with | When |\n|---|---|---|\n| `linkUrl` | | Required. The `link_url` your server received. |\n| `onSuccess` | `(publicToken, metadata)` | Required. The customer is linked to you. Send `publicToken` to your server. |\n| `onExit` | `(error, metadata)` | The flow ended without success. `error` is `null` when the customer closed it from inside the Made window. |\n| `onEvent` | `(eventName, metadata)` | Every step, for analytics and logs. |\n\n`metadata` is `{ sessionId, kind }`, where `kind` is `\"apply\"` or `\"login\"`.\n\n| Handler method | Does |\n|---|---|\n| `open()` | Opens the Made window, or focuses it if it is already open. Call it inside a click handler. |\n| `destroy()` | Closes the Made window and stops listening. No callback runs after it. |\n\nFor `kind: \"apply\"`, `onSuccess` fires as soon as the customer has a Made login, and the Made window stays open while they finish the application. Check the application later with the customer endpoints. For `kind: \"login\"`, the Made window closes itself after `onSuccess`.\n\n`MadeLink.version` is the loaded version, for example `\"1.0.0\"`.\n\n## Errors\n\n`onExit` receives `{ code, message }`. Branch on `code`; `message` is for your logs.\n\n| Code | What happened | What to do |\n|---|---|---|\n| `POPUP_BLOCKED` | The browser refused to open the window | Call `open()` inside the click handler, with the session created beforehand |\n| `USER_CLOSED` | The customer closed the Made window before finishing | Let them try again. The same `link_url` works until it expires |\n| `ORIGIN_NOT_ALLOWED` | Your page's origin is not one of your allowed origins | Add the origin in the partner portal |\n| `IDENTITY_MISMATCH` | The customer's existing Made profile does not match a field you locked | Check the details you sent, or lock fewer fields |\n| `SESSION_EXPIRED` | The `link_url` expired, was already used, or was not found | Create a new link session |\n\nThe Made window shows the customer a message for `ORIGIN_NOT_ALLOWED`, `IDENTITY_MISMATCH`, and `SESSION_EXPIRED`, and stays open until they close it.\n\n## Events\n\n| Event | When |\n|---|---|\n| `OPEN` | The Made window opened |\n| `READY` | The Made window loaded the session and accepted your page |\n| `SUCCESS` | Right before `onSuccess` |\n| `EXIT` | Right before `onExit`. `metadata.errorCode` holds the code, if any |\n| `ERROR` | Made reported an error. `metadata.errorCode` holds the code. `LOAD_TIMEOUT` means Made has not answered in 60 seconds; the flow stays open |\n\n## Open Made Card for a linked customer\n\nYour server creates a launch URL with `POST /v1/partners/sessions/launch`. Open it with:\n\n```js\nconst opened = MadeLink.openLaunchUrl(launch_url); // new tab\nif (!opened) MadeLink.openLaunchUrl(launch_url, { target: \"_self\" }); // the browser blocked the tab\n```\n\n`openLaunchUrl` returns `false` if the browser blocked the new tab. The tab opens without a reference back to your page. It throws a `TypeError` for anything other than a Made launch URL.\n\n## Types\n\nDownload `made-link.d.ts` into your project. It declares `window.MadeLink` and exports the types, including `MadeLinkOptions`, `MadeLinkError`, and `MadeLinkErrorCode`.\n\n## Security\n\n- Made Link accepts messages only from the origin of `linkUrl`, only from the window it opened, and only for that session.\n- The Made window sends the `public_token` only to an allowed origin. `publicToken` works once and expires 10 minutes after the customer finishes.\n- Keep the customer's `link_...` token on your server. Nothing in the browser needs it.\n\n## Moving from partner-link.js\n\n`partner-link.js` and `Made.link` keep working, now built on Made Link. To move:\n\n| partner-link.js | Made Link |\n|---|---|\n| `<script src=\".../partner-link.js\">` | `<script src=\".../sdk/v1/made-link.js\">` |\n| `Made.link({ linkUrl, onSuccess, onExit })`, which opens at once | `MadeLink.create({ linkUrl, onSuccess, onExit, onEvent })`, then `handler.open()` |\n| `onSuccess({ public_token, session_id })` | `onSuccess(publicToken, { sessionId, kind })` |\n| `onExit({ reason: \"popup_blocked\" })` | `onExit({ code: \"POPUP_BLOCKED\" })` |\n| `onExit({ reason: \"closed\" })` | `onExit({ code: \"USER_CLOSED\" })`, or the other codes above |\n| `handle.close()` | `handler.destroy()` |\n| `origin` option | Not needed. Messages are checked against the origin of `linkUrl` |\n\n# Launch URLs\n\n`POST /v1/partners/sessions/launch` turns a stored customer `access_token` into a one-time `launch_url`.\n\n```json\n{\n  \"access_token\": \"link_...\",\n  \"target_path\": \"/dashboard/home\"\n}\n```\n\nAllowed `target_path` values:\n\n| Path | Opens |\n|---|---|\n| `/dashboard/home` | Made Card home (default) |\n| `/dashboard/payments` | Payments |\n| `/dashboard/rewards` | Rewards |\n| `/dashboard/accounts` | Account details |\n| `/dashboard/transactions` | Transactions |\n\nAny other path returns `PRTN_0011`.\n\nOpen `launch_url` in a new tab within 5 minutes. It works once. The customer is signed in as themselves, and payments and every other action happen in Made Card, not through your credentials.\n\n`target_path` applies once the customer has a Made Card account. Before that, the launch URL opens their application instead: while it is in review, after a decline, and after an approval until they accept the offer. `account_id` in `GET /v1/partners/customers/{user_id}` tells you which case you are in.\n\nIf Made has stopped the customer from signing in, the launch URL shows Made's message and signs no one in. Your page is not told.\n\nUse launch for every return visit. Do not start a `login` session for a customer you already have an `access_token` for.\n\n# Customer data\n\nAll customer endpoints are read-only `GET` calls with your partner JWT.\n\n## Who you can see\n\nYour customers are the Made customers who:\n\n- have an active link with you (they finished a link session you started), or\n- Made attributes to you because they applied through your partner channel or through one of your agents.\n\nAn attributed customer with no active link shows `linked_at: null`. `GET /v1/partners/customers` lists newest first. Asking for anyone else returns `PRTN_0013`.\n\n## Endpoints\n\n| Endpoint | Returns |\n|---|---|\n| `GET /v1/partners/customers?limit=20&offset=0` | `customers`, `total`, `limit`, `offset` |\n| `GET /v1/partners/customers/{user_id}` | One customer summary |\n| `GET /v1/partners/customers/{user_id}/transactions?limit=20&offset=0` | Card transactions: pending first, then newest first |\n| `GET /v1/partners/customers/{user_id}/payments?limit=20&offset=0` | Upcoming scheduled payments that have not been submitted yet |\n| `GET /v1/partners/customers/{user_id}/rewards` | Points balance and earn breakdown since the last statement |\n\n`limit` is 1 to 100 (default 20). `offset` starts at 0.\n\nTransactions leave out voided and zero-amount rows. Payments the customer already made show up in transactions, not in `/payments`.\n\nThe transactions, payments, and rewards endpoints return `PRTN_0014` while the customer has no card account yet, for example while their application is still in review. A customer with an account but no transactions gets an empty `data` list.\n\nThere is no partner endpoint to create a payment, transfer money, or change a card.\n\nThere are no webhooks either. To follow an application, read the customer summary; Testing and go-live explains what `account_id` and `account_status` tell you.\n\n# Errors\n\nEvery response uses the same envelope. On success `error` is `null` and `data` holds the result. `POST /v1/partners/link/sessions` and `POST /v1/partners/sessions/launch` answer HTTP 201; every other success is HTTP 200.\n\nOn failure `error` is a stable code and `message` is safe to log:\n\n```json\n{ \"error\": \"PRTN_0010\", \"message\": \"This customer connection is invalid or has been revoked\" }\n```\n\nBranch on `error`, not on `message`.\n\nRequest validation failures return HTTP 422. There `error` is a list with one entry per problem, `field` is the top-level request field, and each message names the exact value:\n\n```json\n{\n  \"error\": [{ \"field\": \"prefill\", \"message\": \"Value error, phone must be a 10-digit US number, for example 7575550123\" }],\n  \"message\": \"• prefill: Value error, phone must be a 10-digit US number, for example 7575550123\",\n  \"data\": null\n}\n```\n\nThese are every error code the partner API returns.\n\n## Auth errors\n\n| HTTP | Code | Meaning | What to do |\n|---|---|---|---|\n| 401 | `AUTH_0013` | No `Authorization: Bearer` header | Send the partner JWT |\n| 401 | `AUTH_0010` / `AUTH_0011` / `AUTH_0012` | Partner JWT expired or invalid | Call `POST /v1/partners/auth` again |\n| 401 | `PRTN_0001` | The `Authorization` header is not a Bearer token | Send `Authorization: Bearer <partner JWT>` |\n| 401 | `PRTN_0003` | The partner JWT could not be read | Call `POST /v1/partners/auth` again |\n| 401 | `PRTN_0002` | Wrong `client_id` or `client_secret` | Check your credentials for this environment |\n| 403 | `PRTN_0004` | The token is not a partner JWT | Use the token from `/v1/partners/auth` |\n| 403 | `PRTN_0015` | Your partner account is disabled | Contact Made |\n| 404 | `PRTN_0005` | Partner not found | Contact Made |\n\n## Link and launch errors\n\n| HTTP | Code | Meaning | What to do |\n|---|---|---|---|\n| 400 | `PRTN_0009` | `public_token` invalid, already used, or expired | See Retries in Testing and go-live |\n| 401 | `PRTN_0010` | Customer `access_token` invalid or revoked | Start a `kind: \"login\"` session to reconnect |\n| 400 | `PRTN_0011` | `target_path` is not allowed | Use one of the five launch paths |\n| 400 | `PRTN_0030` | `partner_agent_id` is not one of your loan officers or agents | Send an ID Made gave you, or `null` |\n| 400 | `PRTN_0031` | `lock_fields` has a name Made cannot lock | Use `first_name`, `last_name`, `email`, or `address` |\n\n## In the Made window\n\nSome problems happen while the customer is in the Made window. They never reach your server as HTTP errors. The window tells the customer, and Made Link calls your `onExit`:\n\n| Made reports | Your page gets | Cause |\n|---|---|---|\n| `PRTN_0027` | `ORIGIN_NOT_ALLOWED` | The page that opened Made Link is not one of your allowed origins. Add it in the partner portal |\n| `PRTN_0008` | `IDENTITY_MISMATCH` | The customer's Made profile does not match a field you locked |\n| `PRTN_0006` / `PRTN_0007` | `SESSION_EXPIRED` | The link session expired, was already used, or was not found |\n\n## Customer errors\n\n| HTTP | Code | Meaning | What to do |\n|---|---|---|---|\n| 404 | `PRTN_0013` | This customer is not yours | Check the `user_id` |\n| 404 | `PRTN_0014` | The customer has no card account yet | Try again after they are approved |\n\n# Testing and go-live\n\n## Testing on staging\n\n- Staging is `https://staging-api.getmcard.com/v1`, with the partner portal at `https://test-partners.madecard.com`. Staging keys work only on staging.\n- Staging sends email only to addresses Made has allowed. If a sign-in code or a decision email does not arrive, write to partners@madecard.com and ask Made to allow your domain.\n- Identity and credit checks run in sandbox mode on staging, so made-up applicant details go through. Never enter a real person's SSN on staging.\n- Staging decisions are simulated. An application can be approved or declined whatever details you enter.\n- A declined test customer counts as failing identity checks, so Made blocks their email and SSN. They can't sign in to Made again: their launch URL shows Made's message, and a `login` session can't connect them. Try again with a new email, phone number, and SSN.\n- Add `http://localhost:<port>` to your allowed origins to open Made Link from local development.\n- To see the whole flow on a working partner first, open an account at https://madepartner.com (Northstar Home Loans, demo) and apply for Made Card there.\n\n## Retries\n\n| Situation | What to do |\n|---|---|\n| `AUTH_0010`, `AUTH_0011`, `AUTH_0012`, or `PRTN_0003` | Get a new partner JWT and retry once |\n| `PRTN_0009` on `POST /v1/partners/link/token` | The `public_token` was used or is more than 10 minutes old. If you already stored the customer's `link_` token, use it. Otherwise start a `kind: \"login\"` session: the customer now has a Made login |\n| `PRTN_0010` | The customer's `link_` token was revoked. Start a `kind: \"login\"` session to reconnect them |\n| `SESSION_EXPIRED` in `onExit` | Create a new link session. Link sessions last 60 minutes and stop working once the customer is linked |\n| HTTP 5xx or a network error | Retry with exponential backoff. Every read is safe to retry. Link sessions and launch URLs are cheap to create again |\n\nExchange each `public_token` once, and save the result before you answer the browser.\n\n## Rate limits\n\nMade does not publish a per-partner rate limit. Keep your traffic modest:\n\n- Reuse the partner JWT for its whole hour instead of calling `/v1/partners/auth` for every request.\n- Page through `GET /v1/partners/customers` with `limit` and `offset` instead of refetching everything.\n- Check a customer's status when they visit, or at most every few minutes in the background.\n- Treat HTTP 429 or 503 as temporary and back off before retrying.\n\n## Checking application status\n\nThere are no webhooks. After `onSuccess`, read `GET /v1/partners/customers/{user_id}`:\n\n- `account_id` is `null` while the application is in progress, in review, or declined, and after approval until the customer accepts their offer.\n- Once the customer accepts and Made opens the card account, `account_id` and `account_status` (for example `ACTIVE`) appear.\n- Transactions, payments, and rewards return `PRTN_0014` until then.\n\nThe partner API does not return the application decision itself.\n\n## Go-live checklist\n\n- [ ] Get production keys. Production is not open to new partners yet: when your staging integration works end to end, email partners@madecard.com and Made sets up your production access. Production keys are separate from staging keys.\n- [ ] Keep the production `client_secret` in your server's secret store. If it leaks, rotate it in the partner portal.\n- [ ] Add your production origins in the production partner portal.\n- [ ] Switch the API base URL to `https://api.getmcard.com/v1` and load Made Link from `https://app.madecard.com`, pinned with its integrity hash.\n- [ ] Handle every `onExit` code and every `PRTN_` code your calls can return.\n- [ ] Store `link_` tokens encrypted, and never log them, the partner JWT, or the `client_secret`.\n- [ ] Try the whole flow: apply, exchange, launch, reconnect with `kind: \"login\"`, and a closed Made window.\n- [ ] Questions: partners@madecard.com.\n\n# For AI agents\n\nThis page is written for coding agents building a Made Card partner integration. The machine-readable sources are:\n\n- `/partners/openapi.json`: the full partner API as OpenAPI 3.1\n- `/partners/llms.txt`: an index of these docs in llms.txt format\n- `/partners/llms-full.txt`: every guide in one markdown file\n- `/partners/docs/<page>.md`: any single guide as raw markdown\n\n## The integration in ten lines\n\n1. Server: `POST /v1/partners/auth` with `client_id` and `client_secret`, cache `data.access_token` as the partner JWT.\n2. Server: send `Authorization: Bearer <partner JWT>` on every other call.\n3. Server: `POST /v1/partners/link/sessions` with `kind: \"apply\"` and the customer's `prefill`, return `data.link_url` to the page.\n4. Browser: load `/sdk/v1/made-link.js`, build `MadeLink.create({ linkUrl, onSuccess, onExit })` as soon as the page has `link_url`, and call `handler.open()` inside the click handler.\n5. Browser: in `onSuccess(publicToken)`, send `publicToken` to your server. Nothing else.\n6. Server: `POST /v1/partners/link/token` with `public_token`, store `data.access_token` (`link_...`) and `data.user_id`.\n7. Server, later visits: `POST /v1/partners/sessions/launch` with that `access_token` and a `target_path`, then open `data.launch_url`.\n8. Server: read data with `GET /v1/partners/customers/{user_id}` and its `/transactions`, `/payments`, `/rewards`.\n9. On `PRTN_0010`, start a `kind: \"login\"` session to reconnect that customer.\n10. On any `AUTH_001x`, get a new partner JWT and retry once.\n\n## Rules\n\n- Never send `client_secret`, the partner JWT, or a `link_...` token to a browser or mobile app.\n- The customer `access_token` goes in the JSON body. It is never an `Authorization` header.\n- Use `kind: \"apply\"` for new customers. Use `kind: \"login\"` only to reconnect. Returning customers get a launch URL, not a new session.\n- Create the link session before the click and call `open()` synchronously in the click handler. Otherwise browsers block the window and `onExit` receives `POPUP_BLOCKED`.\n- The page that opens Made Link must be on one of the partner's allowed origins (see Apply and link). Otherwise `onExit` receives `ORIGIN_NOT_ALLOWED` and `onSuccess` never fires.\n- Handle every `onExit` code: `POPUP_BLOCKED`, `USER_CLOSED`, `ORIGIN_NOT_ALLOWED`, `IDENTITY_MISMATCH`, `SESSION_EXPIRED`. `onExit(null)` means the customer left from inside the Made window.\n- For `kind: \"apply\"`, `onSuccess` fires once the customer has a Made login. The Made window stays open while they finish; check the application with `GET /v1/partners/customers/{user_id}`.\n- A launch URL opens `target_path` only once `account_id` is set. Before that it opens the customer's application.\n- A working reference integration runs at https://madepartner.com (Northstar Home Loans, demo, on staging).\n- `public_token` and `launch_url` are single use. Do not store or reuse them.\n- Branch on the `error` code, not the message.\n- Nothing in this API moves money or changes an account. Do not look for a payment endpoint.\n\n## Prompt you can paste\n\n```text\nIntegrate my app with the Made Card Partners API.\nSpec: https://staging-api.getmcard.com/partners/openapi.json\nGuide: https://staging-api.getmcard.com/partners/llms-full.txt\nFollow the \"For AI agents\" rules exactly. Keep client_secret, the partner JWT,\nand every link_ token on the server. Build: a server route that creates a link\nsession, a page that loads Made Link and opens it from a button, a server route\nthat exchanges the public_token and stores the access_token, and a route that\nreturns a launch URL.\nUse environment variables MADE_API_BASE, MADE_CLIENT_ID, MADE_CLIENT_SECRET.\n```\n\n## Minimal Node server\n\n```js\nimport express from \"express\";\n\nconst API = process.env.MADE_API_BASE; // https://staging-api.getmcard.com/v1\nconst app = express();\napp.use(express.json());\n\nlet jwt = null;\nlet jwtExpiresAt = 0;\n\nasync function partnerJwt() {\n  if (jwt && Date.now() < jwtExpiresAt - 60_000) return jwt;\n  const res = await fetch(`${API}/partners/auth`, {\n    method: \"POST\",\n    headers: { \"Content-Type\": \"application/json\" },\n    body: JSON.stringify({ client_id: process.env.MADE_CLIENT_ID, client_secret: process.env.MADE_CLIENT_SECRET }),\n  });\n  const { data } = await res.json();\n  jwt = data.access_token;\n  jwtExpiresAt = Date.now() + data.expires_in * 1000;\n  return jwt;\n}\n\nasync function made(path, body) {\n  const res = await fetch(`${API}${path}`, {\n    method: \"POST\",\n    headers: { Authorization: `Bearer ${await partnerJwt()}`, \"Content-Type\": \"application/json\" },\n    body: JSON.stringify(body),\n  });\n  const payload = await res.json();\n  if (!res.ok) throw Object.assign(new Error(payload.message), { code: payload.error, status: res.status });\n  return payload.data;\n}\n\napp.post(\"/made/link-session\", async (req, res) => {\n  const session = await made(\"/partners/link/sessions\", { kind: \"apply\", prefill: req.body.prefill ?? {} });\n  res.json({ link_url: session.link_url });\n});\n\napp.post(\"/made/exchange\", async (req, res) => {\n  const link = await made(\"/partners/link/token\", { public_token: req.body.public_token });\n  // Save link.access_token and link.user_id with your customer record here.\n  res.json({ connected: true });\n});\n\napp.post(\"/made/launch\", async (req, res) => {\n  const accessToken = \"link_...\"; // Load the stored token for the signed-in customer.\n  const launch = await made(\"/partners/sessions/launch\", { access_token: accessToken, target_path: \"/dashboard/home\" });\n  res.json({ launch_url: launch.launch_url });\n});\n\napp.listen(3000);\n```\n","contact":{"name":"Made Card Partner Support","email":"partners@madecard.com"},"version":"1.0.0"},"paths":{"/v1/partners/auth":{"post":{"tags":["Authentication"],"summary":"Authenticate partner","description":"Exchange client_id and client_secret for a partner JWT. Send that JWT as Authorization: Bearer on every other partner API.","operationId":"authenticate_partner_v1_partners_auth_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerAuthRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BaseResponse_PartnerAuthResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"401":{"description":"`PRTN_0002` Invalid partner client credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerError"},"examples":{"PRTN_0002":{"summary":"Invalid partner client credentials","value":{"error":"PRTN_0002","message":"Invalid client credentials"}}}}}},"403":{"description":"`PRTN_0015` Partner tenant is disabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerError"},"examples":{"PRTN_0015":{"summary":"Partner tenant is disabled","value":{"error":"PRTN_0015","message":"This partner is not active"}}}}}},"404":{"description":"`PRTN_0005` Partner tenant not found or inactive","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerError"},"examples":{"PRTN_0005":{"summary":"Partner tenant not found or inactive","value":{"error":"PRTN_0005","message":"Partner not found"}}}}}}}}},"/v1/partners/link/sessions":{"post":{"tags":["Apply and login"],"summary":"Start apply or login","description":"Create a Made-hosted apply page, or a login page for recovery or for an existing Made customer who is not linked to you yet. Open link_url with Made Link, the web SDK, within 60 minutes. Return visits use POST /v1/partners/sessions/launch, not this endpoint.","operationId":"create_link_session_v1_partners_link_sessions_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateLinkSessionRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BaseResponse_LinkSessionResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"`PRTN_0031` lock_fields contains a name Made cannot lock; `PRTN_0030` partner_agent_id is not one of this partner's loan officers or agents","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerError"},"examples":{"PRTN_0031":{"summary":"lock_fields contains a name Made cannot lock","value":{"error":"PRTN_0031","message":"lock_fields accepts only first_name, last_name, email, and address"}},"PRTN_0030":{"summary":"partner_agent_id is not one of this partner's loan officers or agents","value":{"error":"PRTN_0030","message":"partner_agent_id is not one of your loan officers or agents. Leave it null unless Made gave you the ID"}}}}}},"401":{"description":"`AUTH_0013` Invalid authentication scheme; `AUTH_0011` Signature is invalid; `AUTH_0010` Signature has expired; `PRTN_0001` Invalid authentication scheme for partner APIs; `PRTN_0003` Invalid or expired partner token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerError"},"examples":{"AUTH_0013":{"summary":"Invalid authentication scheme","value":{"error":"AUTH_0013","message":"Your session has expired, please login again."}},"AUTH_0011":{"summary":"Signature is invalid","value":{"error":"AUTH_0011","message":"Your session has expired, please login again."}},"AUTH_0010":{"summary":"Signature has expired","value":{"error":"AUTH_0010","message":"Your session has expired, please login again."}},"PRTN_0001":{"summary":"Invalid authentication scheme for partner APIs","value":{"error":"PRTN_0001","message":"Invalid authentication scheme"}},"PRTN_0003":{"summary":"Invalid or expired partner token","value":{"error":"PRTN_0003","message":"Invalid token or expired token"}}}}}},"403":{"description":"`PRTN_0004` Token is not a partner application token; `PRTN_0015` Partner tenant is disabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerError"},"examples":{"PRTN_0004":{"summary":"Token is not a partner application token","value":{"error":"PRTN_0004","message":"This endpoint requires a partner token"}},"PRTN_0015":{"summary":"Partner tenant is disabled","value":{"error":"PRTN_0015","message":"This partner is not active"}}}}}},"404":{"description":"`PRTN_0005` Partner tenant not found or inactive","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerError"},"examples":{"PRTN_0005":{"summary":"Partner tenant not found or inactive","value":{"error":"PRTN_0005","message":"Partner not found"}}}}}}},"security":[{"Bearer":[]}]}},"/v1/partners/link/token":{"post":{"tags":["Apply and login"],"summary":"Exchange public token","description":"Turn the one-time public_token from the Made Link onSuccess callback into a per-customer access_token (link_...). Store it on your server. It stays valid until Made revokes it, and linking the same customer again replaces it. It is not a user JWT and cannot create payments.","operationId":"exchange_public_token_v1_partners_link_token_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExchangePublicTokenRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BaseResponse_PartnerUserAccessTokenResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"`PRTN_0009` Partner public token is invalid, used, or expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerError"},"examples":{"PRTN_0009":{"summary":"Partner public token is invalid, used, or expired","value":{"error":"PRTN_0009","message":"This connection token is invalid or has expired"}}}}}},"401":{"description":"`AUTH_0013` Invalid authentication scheme; `AUTH_0011` Signature is invalid; `AUTH_0010` Signature has expired; `PRTN_0001` Invalid authentication scheme for partner APIs; `PRTN_0003` Invalid or expired partner token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerError"},"examples":{"AUTH_0013":{"summary":"Invalid authentication scheme","value":{"error":"AUTH_0013","message":"Your session has expired, please login again."}},"AUTH_0011":{"summary":"Signature is invalid","value":{"error":"AUTH_0011","message":"Your session has expired, please login again."}},"AUTH_0010":{"summary":"Signature has expired","value":{"error":"AUTH_0010","message":"Your session has expired, please login again."}},"PRTN_0001":{"summary":"Invalid authentication scheme for partner APIs","value":{"error":"PRTN_0001","message":"Invalid authentication scheme"}},"PRTN_0003":{"summary":"Invalid or expired partner token","value":{"error":"PRTN_0003","message":"Invalid token or expired token"}}}}}},"403":{"description":"`PRTN_0004` Token is not a partner application token; `PRTN_0015` Partner tenant is disabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerError"},"examples":{"PRTN_0004":{"summary":"Token is not a partner application token","value":{"error":"PRTN_0004","message":"This endpoint requires a partner token"}},"PRTN_0015":{"summary":"Partner tenant is disabled","value":{"error":"PRTN_0015","message":"This partner is not active"}}}}}},"404":{"description":"`PRTN_0005` Partner tenant not found or inactive","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerError"},"examples":{"PRTN_0005":{"summary":"Partner tenant not found or inactive","value":{"error":"PRTN_0005","message":"Partner not found"}}}}}}},"security":[{"Bearer":[]}]}},"/v1/partners/link/refresh":{"post":{"tags":["Apply and login"],"summary":"Refresh customer access token","description":"Optional rotation. Issues a new link_ token for the same customer. The previous token stops working immediately. No Made UI and no customer password.","operationId":"refresh_access_token_v1_partners_link_refresh_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefreshAccessTokenRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BaseResponse_PartnerUserAccessTokenResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"401":{"description":"`AUTH_0013` Invalid authentication scheme; `AUTH_0011` Signature is invalid; `AUTH_0010` Signature has expired; `PRTN_0001` Invalid authentication scheme for partner APIs; `PRTN_0003` Invalid or expired partner token; `PRTN_0010` Partner user access token is invalid or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerError"},"examples":{"AUTH_0013":{"summary":"Invalid authentication scheme","value":{"error":"AUTH_0013","message":"Your session has expired, please login again."}},"AUTH_0011":{"summary":"Signature is invalid","value":{"error":"AUTH_0011","message":"Your session has expired, please login again."}},"AUTH_0010":{"summary":"Signature has expired","value":{"error":"AUTH_0010","message":"Your session has expired, please login again."}},"PRTN_0001":{"summary":"Invalid authentication scheme for partner APIs","value":{"error":"PRTN_0001","message":"Invalid authentication scheme"}},"PRTN_0003":{"summary":"Invalid or expired partner token","value":{"error":"PRTN_0003","message":"Invalid token or expired token"}},"PRTN_0010":{"summary":"Partner user access token is invalid or revoked","value":{"error":"PRTN_0010","message":"This customer connection is invalid or has been revoked"}}}}}},"403":{"description":"`PRTN_0004` Token is not a partner application token; `PRTN_0015` Partner tenant is disabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerError"},"examples":{"PRTN_0004":{"summary":"Token is not a partner application token","value":{"error":"PRTN_0004","message":"This endpoint requires a partner token"}},"PRTN_0015":{"summary":"Partner tenant is disabled","value":{"error":"PRTN_0015","message":"This partner is not active"}}}}}},"404":{"description":"`PRTN_0005` Partner tenant not found or inactive","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerError"},"examples":{"PRTN_0005":{"summary":"Partner tenant not found or inactive","value":{"error":"PRTN_0005","message":"Partner not found"}}}}}}},"security":[{"Bearer":[]}]}},"/v1/partners/sessions/launch":{"post":{"tags":["Open Made Card"],"summary":"Create launch URL","description":"Create a single-use URL, valid for 5 minutes, that opens Made Card already signed in from the stored link. The customer is not asked for a Made password. Allowed target_path values: /dashboard/home, /dashboard/payments, /dashboard/rewards, /dashboard/accounts, /dashboard/transactions.","operationId":"create_launch_session_v1_partners_sessions_launch_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateLaunchSessionRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BaseResponse_LaunchSessionResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"`PRTN_0011` Requested Made Card launch path is not allowed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerError"},"examples":{"PRTN_0011":{"summary":"Requested Made Card launch path is not allowed","value":{"error":"PRTN_0011","message":"That Made Card page cannot be opened from a partner"}}}}}},"401":{"description":"`AUTH_0013` Invalid authentication scheme; `AUTH_0011` Signature is invalid; `AUTH_0010` Signature has expired; `PRTN_0001` Invalid authentication scheme for partner APIs; `PRTN_0003` Invalid or expired partner token; `PRTN_0010` Partner user access token is invalid or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerError"},"examples":{"AUTH_0013":{"summary":"Invalid authentication scheme","value":{"error":"AUTH_0013","message":"Your session has expired, please login again."}},"AUTH_0011":{"summary":"Signature is invalid","value":{"error":"AUTH_0011","message":"Your session has expired, please login again."}},"AUTH_0010":{"summary":"Signature has expired","value":{"error":"AUTH_0010","message":"Your session has expired, please login again."}},"PRTN_0001":{"summary":"Invalid authentication scheme for partner APIs","value":{"error":"PRTN_0001","message":"Invalid authentication scheme"}},"PRTN_0003":{"summary":"Invalid or expired partner token","value":{"error":"PRTN_0003","message":"Invalid token or expired token"}},"PRTN_0010":{"summary":"Partner user access token is invalid or revoked","value":{"error":"PRTN_0010","message":"This customer connection is invalid or has been revoked"}}}}}},"403":{"description":"`PRTN_0004` Token is not a partner application token; `PRTN_0015` Partner tenant is disabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerError"},"examples":{"PRTN_0004":{"summary":"Token is not a partner application token","value":{"error":"PRTN_0004","message":"This endpoint requires a partner token"}},"PRTN_0015":{"summary":"Partner tenant is disabled","value":{"error":"PRTN_0015","message":"This partner is not active"}}}}}},"404":{"description":"`PRTN_0005` Partner tenant not found or inactive","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerError"},"examples":{"PRTN_0005":{"summary":"Partner tenant not found or inactive","value":{"error":"PRTN_0005","message":"Partner not found"}}}}}}},"security":[{"Bearer":[]}]}},"/v1/partners/customers":{"get":{"tags":["Customers"],"summary":"List customers","description":"Read-only list, newest first, of Made customers with an active link to you or attributed to you through your partner channel or agents.","operationId":"list_customers_v1_partners_customers_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"exclusiveMinimum":0,"default":20,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BaseResponse_PartnerCustomerListResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"401":{"description":"`AUTH_0013` Invalid authentication scheme; `AUTH_0011` Signature is invalid; `AUTH_0010` Signature has expired; `PRTN_0001` Invalid authentication scheme for partner APIs; `PRTN_0003` Invalid or expired partner token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerError"},"examples":{"AUTH_0013":{"summary":"Invalid authentication scheme","value":{"error":"AUTH_0013","message":"Your session has expired, please login again."}},"AUTH_0011":{"summary":"Signature is invalid","value":{"error":"AUTH_0011","message":"Your session has expired, please login again."}},"AUTH_0010":{"summary":"Signature has expired","value":{"error":"AUTH_0010","message":"Your session has expired, please login again."}},"PRTN_0001":{"summary":"Invalid authentication scheme for partner APIs","value":{"error":"PRTN_0001","message":"Invalid authentication scheme"}},"PRTN_0003":{"summary":"Invalid or expired partner token","value":{"error":"PRTN_0003","message":"Invalid token or expired token"}}}}}},"403":{"description":"`PRTN_0004` Token is not a partner application token; `PRTN_0015` Partner tenant is disabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerError"},"examples":{"PRTN_0004":{"summary":"Token is not a partner application token","value":{"error":"PRTN_0004","message":"This endpoint requires a partner token"}},"PRTN_0015":{"summary":"Partner tenant is disabled","value":{"error":"PRTN_0015","message":"This partner is not active"}}}}}},"404":{"description":"`PRTN_0005` Partner tenant not found or inactive","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerError"},"examples":{"PRTN_0005":{"summary":"Partner tenant not found or inactive","value":{"error":"PRTN_0005","message":"Partner not found"}}}}}}},"security":[{"Bearer":[]}]}},"/v1/partners/customers/{user_id}":{"get":{"tags":["Customers"],"summary":"Get customer","description":"Read-only summary for one of your customers.","operationId":"get_customer_v1_partners_customers__user_id__get","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BaseResponse_PartnerCustomerSummary_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"401":{"description":"`AUTH_0013` Invalid authentication scheme; `AUTH_0011` Signature is invalid; `AUTH_0010` Signature has expired; `PRTN_0001` Invalid authentication scheme for partner APIs; `PRTN_0003` Invalid or expired partner token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerError"},"examples":{"AUTH_0013":{"summary":"Invalid authentication scheme","value":{"error":"AUTH_0013","message":"Your session has expired, please login again."}},"AUTH_0011":{"summary":"Signature is invalid","value":{"error":"AUTH_0011","message":"Your session has expired, please login again."}},"AUTH_0010":{"summary":"Signature has expired","value":{"error":"AUTH_0010","message":"Your session has expired, please login again."}},"PRTN_0001":{"summary":"Invalid authentication scheme for partner APIs","value":{"error":"PRTN_0001","message":"Invalid authentication scheme"}},"PRTN_0003":{"summary":"Invalid or expired partner token","value":{"error":"PRTN_0003","message":"Invalid token or expired token"}}}}}},"403":{"description":"`PRTN_0004` Token is not a partner application token; `PRTN_0015` Partner tenant is disabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerError"},"examples":{"PRTN_0004":{"summary":"Token is not a partner application token","value":{"error":"PRTN_0004","message":"This endpoint requires a partner token"}},"PRTN_0015":{"summary":"Partner tenant is disabled","value":{"error":"PRTN_0015","message":"This partner is not active"}}}}}},"404":{"description":"`PRTN_0005` Partner tenant not found or inactive; `PRTN_0013` Requested customer is not linked to this partner","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerError"},"examples":{"PRTN_0005":{"summary":"Partner tenant not found or inactive","value":{"error":"PRTN_0005","message":"Partner not found"}},"PRTN_0013":{"summary":"Requested customer is not linked to this partner","value":{"error":"PRTN_0013","message":"Customer not found"}}}}}}},"security":[{"Bearer":[]}]}},"/v1/partners/customers/{user_id}/transactions":{"get":{"tags":["Customers"],"summary":"List customer transactions","description":"Read-only card transactions for one of your customers: pending first, then newest first. Voided and zero-amount rows are left out. Returns an empty list when there are none.","operationId":"get_customer_transactions_v1_partners_customers__user_id__transactions_get","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"exclusiveMinimum":0,"default":20,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Card transactions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BaseResponse_list_PartnerTransaction__"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"401":{"description":"`AUTH_0013` Invalid authentication scheme; `AUTH_0011` Signature is invalid; `AUTH_0010` Signature has expired; `PRTN_0001` Invalid authentication scheme for partner APIs; `PRTN_0003` Invalid or expired partner token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerError"},"examples":{"AUTH_0013":{"summary":"Invalid authentication scheme","value":{"error":"AUTH_0013","message":"Your session has expired, please login again."}},"AUTH_0011":{"summary":"Signature is invalid","value":{"error":"AUTH_0011","message":"Your session has expired, please login again."}},"AUTH_0010":{"summary":"Signature has expired","value":{"error":"AUTH_0010","message":"Your session has expired, please login again."}},"PRTN_0001":{"summary":"Invalid authentication scheme for partner APIs","value":{"error":"PRTN_0001","message":"Invalid authentication scheme"}},"PRTN_0003":{"summary":"Invalid or expired partner token","value":{"error":"PRTN_0003","message":"Invalid token or expired token"}}}}}},"403":{"description":"`PRTN_0004` Token is not a partner application token; `PRTN_0015` Partner tenant is disabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerError"},"examples":{"PRTN_0004":{"summary":"Token is not a partner application token","value":{"error":"PRTN_0004","message":"This endpoint requires a partner token"}},"PRTN_0015":{"summary":"Partner tenant is disabled","value":{"error":"PRTN_0015","message":"This partner is not active"}}}}}},"404":{"description":"`PRTN_0005` Partner tenant not found or inactive; `PRTN_0013` Requested customer is not linked to this partner; `PRTN_0014` Linked customer has no card account","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerError"},"examples":{"PRTN_0005":{"summary":"Partner tenant not found or inactive","value":{"error":"PRTN_0005","message":"Partner not found"}},"PRTN_0013":{"summary":"Requested customer is not linked to this partner","value":{"error":"PRTN_0013","message":"Customer not found"}},"PRTN_0014":{"summary":"Linked customer has no card account","value":{"error":"PRTN_0014","message":"This customer does not have a card account yet"}}}}}}},"security":[{"Bearer":[]}]}},"/v1/partners/customers/{user_id}/payments":{"get":{"tags":["Customers"],"summary":"List scheduled payments","description":"Read-only upcoming scheduled payments for one of your customers that have not been submitted yet. Payments already made appear in transactions. There is no partner API to trigger a payment.","operationId":"get_customer_payments_v1_partners_customers__user_id__payments_get","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"exclusiveMinimum":0,"default":20,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Scheduled payments","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BaseResponse_list_PartnerScheduledPayment__"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"401":{"description":"`AUTH_0013` Invalid authentication scheme; `AUTH_0011` Signature is invalid; `AUTH_0010` Signature has expired; `PRTN_0001` Invalid authentication scheme for partner APIs; `PRTN_0003` Invalid or expired partner token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerError"},"examples":{"AUTH_0013":{"summary":"Invalid authentication scheme","value":{"error":"AUTH_0013","message":"Your session has expired, please login again."}},"AUTH_0011":{"summary":"Signature is invalid","value":{"error":"AUTH_0011","message":"Your session has expired, please login again."}},"AUTH_0010":{"summary":"Signature has expired","value":{"error":"AUTH_0010","message":"Your session has expired, please login again."}},"PRTN_0001":{"summary":"Invalid authentication scheme for partner APIs","value":{"error":"PRTN_0001","message":"Invalid authentication scheme"}},"PRTN_0003":{"summary":"Invalid or expired partner token","value":{"error":"PRTN_0003","message":"Invalid token or expired token"}}}}}},"403":{"description":"`PRTN_0004` Token is not a partner application token; `PRTN_0015` Partner tenant is disabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerError"},"examples":{"PRTN_0004":{"summary":"Token is not a partner application token","value":{"error":"PRTN_0004","message":"This endpoint requires a partner token"}},"PRTN_0015":{"summary":"Partner tenant is disabled","value":{"error":"PRTN_0015","message":"This partner is not active"}}}}}},"404":{"description":"`PRTN_0005` Partner tenant not found or inactive; `PRTN_0013` Requested customer is not linked to this partner; `PRTN_0014` Linked customer has no card account","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerError"},"examples":{"PRTN_0005":{"summary":"Partner tenant not found or inactive","value":{"error":"PRTN_0005","message":"Partner not found"}},"PRTN_0013":{"summary":"Requested customer is not linked to this partner","value":{"error":"PRTN_0013","message":"Customer not found"}},"PRTN_0014":{"summary":"Linked customer has no card account","value":{"error":"PRTN_0014","message":"This customer does not have a card account yet"}}}}}}},"security":[{"Bearer":[]}]}},"/v1/partners/customers/{user_id}/rewards":{"get":{"tags":["Customers"],"summary":"Get customer rewards","description":"Read-only points balance and earn breakdown since the last statement for one of your customers.","operationId":"get_customer_rewards_v1_partners_customers__user_id__rewards_get","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}}],"responses":{"200":{"description":"Rewards summary","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BaseResponse_PartnerRewardsSummary_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"401":{"description":"`AUTH_0013` Invalid authentication scheme; `AUTH_0011` Signature is invalid; `AUTH_0010` Signature has expired; `PRTN_0001` Invalid authentication scheme for partner APIs; `PRTN_0003` Invalid or expired partner token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerError"},"examples":{"AUTH_0013":{"summary":"Invalid authentication scheme","value":{"error":"AUTH_0013","message":"Your session has expired, please login again."}},"AUTH_0011":{"summary":"Signature is invalid","value":{"error":"AUTH_0011","message":"Your session has expired, please login again."}},"AUTH_0010":{"summary":"Signature has expired","value":{"error":"AUTH_0010","message":"Your session has expired, please login again."}},"PRTN_0001":{"summary":"Invalid authentication scheme for partner APIs","value":{"error":"PRTN_0001","message":"Invalid authentication scheme"}},"PRTN_0003":{"summary":"Invalid or expired partner token","value":{"error":"PRTN_0003","message":"Invalid token or expired token"}}}}}},"403":{"description":"`PRTN_0004` Token is not a partner application token; `PRTN_0015` Partner tenant is disabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerError"},"examples":{"PRTN_0004":{"summary":"Token is not a partner application token","value":{"error":"PRTN_0004","message":"This endpoint requires a partner token"}},"PRTN_0015":{"summary":"Partner tenant is disabled","value":{"error":"PRTN_0015","message":"This partner is not active"}}}}}},"404":{"description":"`PRTN_0005` Partner tenant not found or inactive; `PRTN_0013` Requested customer is not linked to this partner; `PRTN_0014` Linked customer has no card account","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerError"},"examples":{"PRTN_0005":{"summary":"Partner tenant not found or inactive","value":{"error":"PRTN_0005","message":"Partner not found"}},"PRTN_0013":{"summary":"Requested customer is not linked to this partner","value":{"error":"PRTN_0013","message":"Customer not found"}},"PRTN_0014":{"summary":"Linked customer has no card account","value":{"error":"PRTN_0014","message":"This customer does not have a card account yet"}}}}}}},"security":[{"Bearer":[]}]}}},"components":{"schemas":{"BaseResponse_LaunchSessionResponse_":{"properties":{"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"},"message":{"type":"string","title":"Message"},"data":{"anyOf":[{"$ref":"#/components/schemas/LaunchSessionResponse"},{"type":"null"}]}},"type":"object","required":["message"],"title":"BaseResponse[LaunchSessionResponse]"},"BaseResponse_LinkSessionResponse_":{"properties":{"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"},"message":{"type":"string","title":"Message"},"data":{"anyOf":[{"$ref":"#/components/schemas/LinkSessionResponse"},{"type":"null"}]}},"type":"object","required":["message"],"title":"BaseResponse[LinkSessionResponse]"},"BaseResponse_PartnerAuthResponse_":{"properties":{"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"},"message":{"type":"string","title":"Message"},"data":{"anyOf":[{"$ref":"#/components/schemas/PartnerAuthResponse"},{"type":"null"}]}},"type":"object","required":["message"],"title":"BaseResponse[PartnerAuthResponse]"},"BaseResponse_PartnerCustomerListResponse_":{"properties":{"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"},"message":{"type":"string","title":"Message"},"data":{"anyOf":[{"$ref":"#/components/schemas/PartnerCustomerListResponse"},{"type":"null"}]}},"type":"object","required":["message"],"title":"BaseResponse[PartnerCustomerListResponse]"},"BaseResponse_PartnerCustomerSummary_":{"properties":{"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"},"message":{"type":"string","title":"Message"},"data":{"anyOf":[{"$ref":"#/components/schemas/PartnerCustomerSummary"},{"type":"null"}]}},"type":"object","required":["message"],"title":"BaseResponse[PartnerCustomerSummary]"},"BaseResponse_PartnerRewardsSummary_":{"properties":{"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"},"message":{"type":"string","title":"Message"},"data":{"anyOf":[{"$ref":"#/components/schemas/PartnerRewardsSummary"},{"type":"null"}]}},"type":"object","required":["message"],"title":"BaseResponse[PartnerRewardsSummary]"},"BaseResponse_PartnerUserAccessTokenResponse_":{"properties":{"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"},"message":{"type":"string","title":"Message"},"data":{"anyOf":[{"$ref":"#/components/schemas/PartnerUserAccessTokenResponse"},{"type":"null"}]}},"type":"object","required":["message"],"title":"BaseResponse[PartnerUserAccessTokenResponse]"},"BaseResponse_list_PartnerScheduledPayment__":{"properties":{"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"},"message":{"type":"string","title":"Message"},"data":{"anyOf":[{"items":{"$ref":"#/components/schemas/PartnerScheduledPayment"},"type":"array"},{"type":"null"}],"title":"Data"}},"type":"object","required":["message"],"title":"BaseResponse[list[PartnerScheduledPayment]]"},"BaseResponse_list_PartnerTransaction__":{"properties":{"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"},"message":{"type":"string","title":"Message"},"data":{"anyOf":[{"items":{"$ref":"#/components/schemas/PartnerTransaction"},"type":"array"},{"type":"null"}],"title":"Data"}},"type":"object","required":["message"],"title":"BaseResponse[list[PartnerTransaction]]"},"CreateLaunchSessionRequest":{"properties":{"access_token":{"type":"string","title":"Access Token","description":"The stored customer access token (`link_...`).","examples":["link_9Vd2..."]},"target_path":{"type":"string","enum":["/dashboard/home","/dashboard/payments","/dashboard/rewards","/dashboard/accounts","/dashboard/transactions"],"title":"Target Path","description":"Made Card page to open.","default":"/dashboard/home"}},"type":"object","required":["access_token"],"title":"CreateLaunchSessionRequest"},"CreateLinkSessionRequest":{"properties":{"kind":{"type":"string","enum":["apply","login"],"title":"Kind","description":"`apply` for a customer new to Made Card. `login` only to reconnect a customer whose link you lost or Made revoked, or an existing Made customer connecting to you for the first time.","default":"apply"},"prefill":{"$ref":"#/components/schemas/PartnerIdentityPrefill","description":"Customer details you already have. They fill the Made application. For `apply`, each value must also pass the application's own rules."},"lock_fields":{"items":{"type":"string","enum":["first_name","last_name","email","address"]},"type":"array","title":"Lock Fields","description":"Prefilled values the customer's Made profile must match. `address` checks address_line_1, city, state, and zipcode. A lock applies only to a field you prefill. Omit it or send `[]` to lock all four. Any other name fails with `PRTN_0031`."},"partner_agent_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Partner Agent Id","description":"Optional Made-assigned ID for one of your loan officers or agents. Leave null unless Made gave you one. An ID that is not yours fails with `PRTN_0030`."}},"additionalProperties":false,"type":"object","title":"CreateLinkSessionRequest"},"ExchangePublicTokenRequest":{"properties":{"public_token":{"type":"string","title":"Public Token","description":"One-time token from the Made Link `onSuccess` callback. Expires 10 minutes after Made links the customer.","examples":["public_3q2x..."]}},"type":"object","required":["public_token"],"title":"ExchangePublicTokenRequest"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"LaunchSessionResponse":{"properties":{"launch_url":{"type":"string","title":"Launch Url","description":"Single-use URL that opens Made Card signed in. Open it within `expires_in` seconds.","examples":["https://staging-app.madecard.com/partner/launch?code=launch_Qe7..."]},"expires_in":{"type":"integer","title":"Expires In","description":"Seconds the launch URL stays valid, 300.","examples":[300]},"target_path":{"type":"string","title":"Target Path","description":"The Made Card page it opens.","examples":["/dashboard/home"]}},"type":"object","required":["launch_url","expires_in","target_path"],"title":"LaunchSessionResponse"},"LinkSessionResponse":{"properties":{"session_id":{"type":"string","format":"uuid","title":"Session Id","description":"Link session ID."},"kind":{"type":"string","title":"Kind","description":"`apply` or `login`.","examples":["apply"]},"link_url":{"type":"string","title":"Link Url","description":"Made-hosted page to open with Made Link, the web SDK. Valid for 60 minutes, and stops working once the customer is linked.","examples":["https://staging-app.madecard.com/partner/apply?session=5b0c9a1e-0d7e-4c6e-9d0a-2f4b8e6f1a33"]},"expires_at":{"type":"string","format":"date-time","title":"Expires At","description":"When `link_url` stops working."},"prefill":{"additionalProperties":true,"type":"object","title":"Prefill","description":"The prefill Made stored for this session."},"lock_fields":{"items":{"type":"string"},"type":"array","title":"Lock Fields","description":"The fields Made will enforce."},"partner_slug":{"type":"string","title":"Partner Slug","description":"Your partner slug."},"partner_name":{"type":"string","title":"Partner Name","description":"Your partner name, as shown to the customer."},"allowed_origins":{"items":{"type":"string"},"type":"array","title":"Allowed Origins","description":"Web origins allowed to open `link_url` with Made Link. Made returns the `public_token` only to a page on one of these. Manage them in the partner portal.","examples":[["https://www.yourcompany.com"]]}},"type":"object","required":["session_id","kind","link_url","expires_at","prefill","lock_fields","partner_slug","partner_name"],"title":"LinkSessionResponse"},"PartnerAuthRequest":{"properties":{"client_id":{"type":"string","title":"Client Id","description":"Your partner client ID from Made.","examples":["pk_yourcompany"]},"client_secret":{"type":"string","title":"Client Secret","description":"Your partner client secret. Keep it on your server.","examples":["sk_your_secret"]}},"type":"object","required":["client_id","client_secret"],"title":"PartnerAuthRequest"},"PartnerAuthResponse":{"properties":{"access_token":{"type":"string","title":"Access Token","description":"Partner JWT. Send it as `Authorization: Bearer` on every other call."},"token_type":{"type":"string","title":"Token Type","description":"Always `bearer`.","default":"bearer"},"expires_in":{"type":"integer","title":"Expires In","description":"Seconds until the partner JWT expires, about 3600.","examples":[3600]},"partner_id":{"type":"string","format":"uuid","title":"Partner Id","description":"Your partner ID at Made."},"slug":{"type":"string","title":"Slug","description":"Your partner slug at Made.","examples":["yourcompany"]}},"type":"object","required":["access_token","expires_in","partner_id","slug"],"title":"PartnerAuthResponse"},"PartnerCustomerListResponse":{"properties":{"customers":{"items":{"$ref":"#/components/schemas/PartnerCustomerSummary"},"type":"array","title":"Customers","description":"Customers on this page, newest first."},"total":{"type":"integer","title":"Total","description":"Total customers you can see."},"limit":{"type":"integer","title":"Limit","description":"Page size used."},"offset":{"type":"integer","title":"Offset","description":"Offset used."}},"type":"object","required":["customers","total","limit","offset"],"title":"PartnerCustomerListResponse"},"PartnerCustomerSummary":{"properties":{"user_id":{"type":"string","format":"uuid","title":"User Id","description":"Made customer ID."},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email","description":"Customer email."},"first_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"First Name","description":"Customer first name."},"last_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Name","description":"Customer last name."},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone","description":"Customer mobile number."},"account_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Account Id","description":"Card account ID. Null until the customer has an account."},"account_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Account Status","description":"Card account status, for example `ACTIVE`."},"linked_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Linked At","description":"When the current link with you was created. Null if Made attributes the customer to you without an active link."}},"type":"object","required":["user_id"],"title":"PartnerCustomerSummary"},"PartnerError":{"title":"PartnerError","type":"object","required":["error","message"],"properties":{"error":{"type":"string","description":"Stable error code. Branch on this.","examples":["PRTN_0010"]},"message":{"type":"string","description":"Human-readable message, safe to log."}}},"PartnerIdentityPrefill":{"properties":{"first_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"First Name","description":"Customer first name, up to 100 characters. For `apply`, 2 to 50 letters or spaces.","examples":["Ada"]},"last_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Name","description":"Customer last name, up to 100 characters. For `apply`, 2 to 50 letters or spaces.","examples":["Lovelace"]},"email":{"anyOf":[{"type":"string","format":"email"},{"type":"null"}],"title":"Email","description":"Customer email.","examples":["ada@example.com"]},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone","description":"Customer US mobile number. Made removes spaces, dashes, dots, parentheses, and a leading +1 or 1, then requires 10 digits.","examples":["7575550123"]},"address_line_1":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Address Line 1","description":"Street address, up to 200 characters. For `apply`, 5 to 40 characters, and not a P.O. Box or registered agent.","examples":["1 Main St"]},"address_line_2":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Address Line 2","description":"Apartment, suite, or unit, up to 200 characters. For `apply`, up to 40 characters, and not a P.O. Box or registered agent.","examples":["Apt 4"]},"city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"City","description":"City, up to 100 characters. For `apply`, only letters, spaces, hyphens, and apostrophes.","examples":["Virginia Beach"]},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State","description":"Two-letter US state or territory code, in any case. For `apply`, one of the 50 states or DC.","examples":["VA"]},"zipcode":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Zipcode","description":"Five-digit ZIP code. A ZIP+4 such as 23451-1234 is shortened to five digits.","examples":["23451"]}},"additionalProperties":false,"type":"object","title":"PartnerIdentityPrefill","description":"Every field is optional. Made trims each value, and an empty string counts as not sent."},"PartnerPointsBalance":{"properties":{"earned_points":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Earned Points","description":"Points earned."},"pending_points":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Pending Points","description":"Points from transactions that have not settled."},"redeemable_points":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Redeemable Points","description":"Points the customer can redeem now."},"mortgage_unlocked_points":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Mortgage Unlocked Points","description":"Mortgage Match points unlocked."},"mortgage_earnable_points":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Mortgage Earnable Points","description":"Mortgage Match points still available to earn."}},"type":"object","title":"PartnerPointsBalance","description":"Documents reward_schemas.AccountPointsBalanceResponse for partners; field names must stay in sync."},"PartnerPointsBucket":{"properties":{"label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Label","description":"Bucket name.","examples":["3x Essentials"]},"points":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Points","description":"Points earned in this bucket."}},"type":"object","title":"PartnerPointsBucket","description":"Documents reward_schemas.AccountPointsMultiplierBreakdownResponse for partners; field names must stay in sync."},"PartnerRewardsSummary":{"properties":{"account_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Account Id","description":"Card account ID."},"year_month":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Year Month","description":"Statement month as YYYYMM.","examples":[202609]},"start_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Start Date","description":"Start of the period, the last statement date."},"end_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"End Date","description":"End of the period. Null for the current period."},"balance":{"anyOf":[{"$ref":"#/components/schemas/PartnerPointsBalance"},{"type":"null"}],"description":"Points balance."},"multiplier_breakdown":{"anyOf":[{"additionalProperties":{"$ref":"#/components/schemas/PartnerPointsBucket"},"type":"object"},{"type":"null"}],"title":"Multiplier Breakdown","description":"Points earned by multiplier, keyed `1`, `2`, and `3`."}},"type":"object","title":"PartnerRewardsSummary","description":"Documents reward_schemas.AccountPointsSummaryResponse for partners; field names must stay in sync."},"PartnerScheduledPayment":{"properties":{"id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Id","description":"Payment ID."},"account_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Account Id","description":"Card account ID."},"effective_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Effective Date","description":"Date the payment is scheduled for."},"amount":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Amount","description":"Payment amount in dollars."},"principal":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Principal","description":"Portion applied to principal."},"interest":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Interest","description":"Portion applied to interest."},"fees":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Fees","description":"Portion applied to fees."},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status","description":"Always `SCHEDULED` here.","examples":["SCHEDULED"]},"repayment_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Repayment Type","description":"`ONE_TIME` or `RECURRING`.","examples":["RECURRING"]},"repayment_strategy":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Repayment Strategy","description":"How the amount is chosen, for example `MINIMUM_PAYMENT`."},"is_business_day":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Business Day","description":"Whether `effective_date` is a business day."},"actual_effective_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Actual Effective Date","description":"Date the payment will actually process."},"bank_account_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Bank Account Id","description":"Bank account the payment pulls from."},"is_paused":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Paused","description":"Whether the customer paused it."},"is_scheduled_on_due_date":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Scheduled On Due Date","description":"Whether it is set to run on the due date."},"is_payment_done_by_check":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Payment Done By Check","description":"Whether it is a check payment."}},"type":"object","title":"PartnerScheduledPayment","description":"Documents payment_schemas.AccountRepaymentResponse for partners; field names must stay in sync."},"PartnerTransaction":{"properties":{"id":{"type":"string","format":"uuid","title":"Id","description":"Transaction ID."},"card_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Card Id","description":"Card the transaction was made on."},"transaction_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Transaction Type","description":"`DEBIT`, `CREDIT`, `FEE`, and similar."},"amount":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Amount","description":"Amount in dollars, including related fees."},"requested_amount":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Requested Amount","description":"Amount requested at authorization."},"additional_fees_amount":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Additional Fees Amount","description":"Related fees rolled into `amount`."},"original_amount":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Original Amount","description":"Amount before related fees."},"original_requested_amount":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Original Requested Amount","description":"Requested amount before related fees."},"currency":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Currency","description":"Currency code.","examples":["USD"]},"merchant_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Merchant Name","description":"Merchant name."},"merchant_category":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Merchant Category","description":"Merchant category."},"merchant_sub_category":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Merchant Sub Category","description":"Merchant sub-category."},"merchant_category_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Merchant Category Code","description":"Four-digit MCC."},"merchant_logo":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Merchant Logo","description":"Category logo URL."},"transaction_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Transaction Date","description":"Display date.","examples":["Sep 21, 2026"]},"latest_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Latest Status","description":"Latest status, for example `PENDING` or `COMPLETED`."},"is_in_dispute":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is In Dispute","description":"Whether the customer disputed it."},"merchant_city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Merchant City","description":"Merchant city."},"merchant_state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Merchant State","description":"Merchant state."},"merchant_zipcode":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Merchant Zipcode","description":"Merchant ZIP code."},"on_statement_as":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"On Statement As","description":"How it appears on the statement."},"local_transaction_amount":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Local Transaction Amount","description":"Amount in the local currency."},"local_currency":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Local Currency","description":"Local currency code."},"is_void":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Void","description":"Always false here; voided rows are omitted."},"merchant_name_sanitized":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Merchant Name Sanitized","description":"Cleaned merchant name."},"merchant_icon_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Merchant Icon Url","description":"Merchant icon URL."},"location_address_latitude":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Location Address Latitude","description":"Merchant latitude."},"location_address_longitude":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Location Address Longitude","description":"Merchant longitude."},"multiplier":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Multiplier","description":"Points multiplier applied, 1 to 3."},"hsr_eligibility":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Hsr Eligibility","description":"Made home-services redemption state."},"zero_percent_apr_eligibility":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Zero Percent Apr Eligibility","description":"Made 0% APR offer state."},"is_eligible_for_price_match":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Eligible For Price Match","description":"Whether price match can be claimed."},"price_match_merchant_claim_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Price Match Merchant Claim Url","description":"Price match claim URL."},"merchant_price_match_coverage_days":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Merchant Price Match Coverage Days","description":"Price match window in days."}},"type":"object","required":["id"],"title":"PartnerTransaction","description":"A card transaction as returned to partners. Mirrors the Made card transaction list."},"PartnerUserAccessTokenResponse":{"properties":{"access_token":{"type":"string","title":"Access Token","description":"Customer access token (`link_...`). Store it on your server. It stays valid until Made revokes it.","examples":["link_9Vd2..."]},"token_type":{"type":"string","title":"Token Type","description":"Always `bearer`.","default":"bearer"},"expires_in":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Expires In","description":"Always null. The link does not expire on a timer; it stays valid until Made revokes it."},"user_id":{"type":"string","format":"uuid","title":"User Id","description":"The Made customer ID for this link."}},"type":"object","required":["access_token","user_id"],"title":"PartnerUserAccessTokenResponse"},"RefreshAccessTokenRequest":{"properties":{"access_token":{"type":"string","title":"Access Token","description":"The current customer access token (`link_...`). It stops working once the new one is issued.","examples":["link_9Vd2..."]}},"type":"object","required":["access_token"],"title":"RefreshAccessTokenRequest"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}},"securitySchemes":{"Bearer":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Partner JWT from POST /v1/partners/auth. Not the customer link_ token."}}},"servers":[{"url":"https://staging-api.getmcard.com","description":"Staging"},{"url":"https://api.getmcard.com","description":"Production"}]}